Commit 67e7631b authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into tom2drum/issue-1446

parents 1c78a12c 9facb82d
...@@ -5,6 +5,9 @@ const RESTRICTED_MODULES = { ...@@ -5,6 +5,9 @@ const RESTRICTED_MODULES = {
{ name: '@metamask/providers', message: 'Please lazy-load @metamask/providers or use useProvider hook instead' }, { name: '@metamask/providers', message: 'Please lazy-load @metamask/providers or use useProvider hook instead' },
{ name: '@metamask/post-message-stream', message: 'Please lazy-load @metamask/post-message-stream or use useProvider hook instead' }, { name: '@metamask/post-message-stream', message: 'Please lazy-load @metamask/post-message-stream or use useProvider hook instead' },
], ],
patterns: [
'icons/*',
],
}; };
module.exports = { module.exports = {
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
/out/ /out/
/public/assets/ /public/assets/
/public/envs.js /public/envs.js
/public/icons/sprite.svg
/public/icons/README.md
/analyze /analyze
# production # production
......
...@@ -265,7 +265,7 @@ ...@@ -265,7 +265,7 @@
}, },
{ {
"type": "npm", "type": "npm",
"script": "format-svg", "script": "svg:format",
"problemMatcher": [], "problemMatcher": [],
"label": "format svg", "label": "format svg",
"detail": "format svg files with svgo", "detail": "format svg files with svgo",
......
...@@ -58,6 +58,7 @@ RUN ./collect_envs.sh ./docs/ENVS.md ...@@ -58,6 +58,7 @@ RUN ./collect_envs.sh ./docs/ENVS.md
# Build app for production # Build app for production
RUN yarn build RUN yarn build
RUN yarn svg:build-sprite
### FEATURE REPORTER ### FEATURE REPORTER
......
...@@ -182,7 +182,8 @@ We have 3 pre-configured projects. You can run your test with the desired projec ...@@ -182,7 +182,8 @@ We have 3 pre-configured projects. You can run your test with the desired projec
| `yarn lint:eslint` | lint project files with ESLint | | `yarn lint:eslint` | lint project files with ESLint |
| `yarn lint:eslint:fix` | lint project files with ESLint and automatically fix problems | | `yarn lint:eslint:fix` | lint project files with ESLint and automatically fix problems |
| `yarn lint:tsc` | compile project typescript files using TypeScript Compiler | | `yarn lint:tsc` | compile project typescript files using TypeScript Compiler |
| `yarn format-svg` | format and optimize SVG icons in the `/icons` folder using SVGO tool | | `yarn svg:format` | format and optimize SVG icons in the `/icons` folder using SVGO tool |
| `yarn svg:build-sprite` | build SVG icons sprite |
| **Testing** | | **Testing** |
| `yarn test:jest` | run all Jest unit tests | | `yarn test:jest` | run all Jest unit tests |
| `yarn test:jest:watch` | run all Jest unit tests in watch mode | | `yarn test:jest:watch` | run all Jest unit tests in watch mode |
......
...@@ -4,28 +4,6 @@ import React from 'react'; ...@@ -4,28 +4,6 @@ import React from 'react';
import type { NavItemInternal, NavItem, NavGroupItem } from 'types/client/navigation-items'; import type { NavItemInternal, NavItem, NavGroupItem } from 'types/client/navigation-items';
import config from 'configs/app'; import config from 'configs/app';
import abiIcon from 'icons/ABI.svg';
import apiKeysIcon from 'icons/API.svg';
import appsIcon from 'icons/apps.svg';
import withdrawalsIcon from 'icons/arrows/north-east.svg';
import depositsIcon from 'icons/arrows/south-east.svg';
import blocksIcon from 'icons/block.svg';
import gearIcon from 'icons/gear.svg';
import globeIcon from 'icons/globe-b.svg';
import graphQLIcon from 'icons/graphQL.svg';
import outputRootsIcon from 'icons/output_roots.svg';
import privateTagIcon from 'icons/privattags.svg';
import publicTagIcon from 'icons/publictags.svg';
import apiDocsIcon from 'icons/restAPI.svg';
import rpcIcon from 'icons/RPC.svg';
import statsIcon from 'icons/stats.svg';
import tokensIcon from 'icons/token.svg';
import topAccountsIcon from 'icons/top-accounts.svg';
import transactionsIcon from 'icons/transactions.svg';
import txnBatchIcon from 'icons/txn_batches.svg';
import verifiedIcon from 'icons/verified.svg';
import verifyContractIcon from 'icons/verify-contract.svg';
import watchlistIcon from 'icons/watchlist.svg';
import { rightLineArrow } from 'lib/html-entities'; import { rightLineArrow } from 'lib/html-entities';
import UserAvatar from 'ui/shared/UserAvatar'; import UserAvatar from 'ui/shared/UserAvatar';
...@@ -50,35 +28,43 @@ export default function useNavItems(): ReturnType { ...@@ -50,35 +28,43 @@ export default function useNavItems(): ReturnType {
return React.useMemo(() => { return React.useMemo(() => {
let blockchainNavItems: Array<NavItem> | Array<Array<NavItem>> = []; let blockchainNavItems: Array<NavItem> | Array<Array<NavItem>> = [];
const topAccounts = !config.UI.views.address.hiddenViews?.top_accounts ? { const topAccounts: NavItem | null = !config.UI.views.address.hiddenViews?.top_accounts ? {
text: 'Top accounts', text: 'Top accounts',
nextRoute: { pathname: '/accounts' as const }, nextRoute: { pathname: '/accounts' as const },
icon: topAccountsIcon, icon: 'top-accounts',
isActive: pathname === '/accounts', isActive: pathname === '/accounts',
} : null; } : null;
const blocks = { const blocks: NavItem | null = {
text: 'Blocks', text: 'Blocks',
nextRoute: { pathname: '/blocks' as const }, nextRoute: { pathname: '/blocks' as const },
icon: blocksIcon, icon: 'block',
isActive: pathname === '/blocks' || pathname === '/block/[height_or_hash]', isActive: pathname === '/blocks' || pathname === '/block/[height_or_hash]',
}; };
const txs = { const txs: NavItem | null = {
text: 'Transactions', text: 'Transactions',
nextRoute: { pathname: '/txs' as const }, nextRoute: { pathname: '/txs' as const },
icon: transactionsIcon, icon: 'transactions',
isActive: pathname === '/txs' || pathname === '/tx/[hash]', isActive: pathname === '/txs' || pathname === '/tx/[hash]',
}; };
const verifiedContracts = const verifiedContracts: NavItem | null =
// eslint-disable-next-line max-len {
{ text: 'Verified contracts', nextRoute: { pathname: '/verified-contracts' as const }, icon: verifiedIcon, isActive: pathname === '/verified-contracts' }; text: 'Verified contracts',
nextRoute: { pathname: '/verified-contracts' as const },
icon: 'verified',
isActive: pathname === '/verified-contracts',
};
if (config.features.zkEvmRollup.isEnabled) { if (config.features.zkEvmRollup.isEnabled) {
blockchainNavItems = [ blockchainNavItems = [
[ [
txs, txs,
blocks, blocks,
// eslint-disable-next-line max-len {
{ text: 'Txn batches', nextRoute: { pathname: '/zkevm-l2-txn-batches' as const }, icon: txnBatchIcon, isActive: pathname === '/zkevm-l2-txn-batches' || pathname === '/zkevm-l2-txn-batch/[number]' }, text: 'Txn batches',
nextRoute: { pathname: '/zkevm-l2-txn-batches' as const },
icon: 'txn_batches',
isActive: pathname === '/zkevm-l2-txn-batches' || pathname === '/zkevm-l2-txn-batch/[number]',
},
], ],
[ [
topAccounts, topAccounts,
...@@ -90,16 +76,16 @@ export default function useNavItems(): ReturnType { ...@@ -90,16 +76,16 @@ export default function useNavItems(): ReturnType {
[ [
txs, txs,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/l2-deposits' as const }, icon: depositsIcon, isActive: pathname === '/l2-deposits' }, { text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/l2-deposits' as const }, icon: 'arrows/south-east', isActive: pathname === '/l2-deposits' },
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/l2-withdrawals' as const }, icon: withdrawalsIcon, isActive: pathname === '/l2-withdrawals' }, { text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/l2-withdrawals' as const }, icon: 'arrows/north-east', isActive: pathname === '/l2-withdrawals' },
], ],
[ [
blocks, blocks,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: 'Txn batches', nextRoute: { pathname: '/l2-txn-batches' as const }, icon: txnBatchIcon, isActive: pathname === '/l2-txn-batches' }, { text: 'Txn batches', nextRoute: { pathname: '/l2-txn-batches' as const }, icon: 'txn_batches', isActive: pathname === '/l2-txn-batches' },
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
{ text: 'Output roots', nextRoute: { pathname: '/l2-output-roots' as const }, icon: outputRootsIcon, isActive: pathname === '/l2-output-roots' }, { text: 'Output roots', nextRoute: { pathname: '/l2-output-roots' as const }, icon: 'output_roots', isActive: pathname === '/l2-output-roots' },
], ],
[ [
topAccounts, topAccounts,
...@@ -115,7 +101,7 @@ export default function useNavItems(): ReturnType { ...@@ -115,7 +101,7 @@ export default function useNavItems(): ReturnType {
config.features.beaconChain.isEnabled && { config.features.beaconChain.isEnabled && {
text: 'Withdrawals', text: 'Withdrawals',
nextRoute: { pathname: '/withdrawals' as const }, nextRoute: { pathname: '/withdrawals' as const },
icon: withdrawalsIcon, icon: 'arrows/north-east',
isActive: pathname === '/withdrawals', isActive: pathname === '/withdrawals',
}, },
].filter(Boolean); ].filter(Boolean);
...@@ -125,23 +111,23 @@ export default function useNavItems(): ReturnType { ...@@ -125,23 +111,23 @@ export default function useNavItems(): ReturnType {
config.features.restApiDocs.isEnabled ? { config.features.restApiDocs.isEnabled ? {
text: 'REST API', text: 'REST API',
nextRoute: { pathname: '/api-docs' as const }, nextRoute: { pathname: '/api-docs' as const },
icon: apiDocsIcon, icon: 'restAPI',
isActive: pathname === '/api-docs', isActive: pathname === '/api-docs',
} : null, } : null,
config.features.graphqlApiDocs.isEnabled ? { config.features.graphqlApiDocs.isEnabled ? {
text: 'GraphQL', text: 'GraphQL',
nextRoute: { pathname: '/graphiql' as const }, nextRoute: { pathname: '/graphiql' as const },
icon: graphQLIcon, icon: 'graphQL',
isActive: pathname === '/graphiql', isActive: pathname === '/graphiql',
} : null, } : null,
!config.UI.sidebar.hiddenLinks?.rpc_api && { !config.UI.sidebar.hiddenLinks?.rpc_api && {
text: 'RPC API', text: 'RPC API',
icon: rpcIcon, icon: 'RPC',
url: 'https://docs.blockscout.com/for-users/api/rpc-endpoints', url: 'https://docs.blockscout.com/for-users/api/rpc-endpoints',
}, },
!config.UI.sidebar.hiddenLinks?.eth_rpc_api && { !config.UI.sidebar.hiddenLinks?.eth_rpc_api && {
text: 'Eth RPC API', text: 'Eth RPC API',
icon: rpcIcon, icon: 'RPC',
url: ' https://docs.blockscout.com/for-users/api/eth-rpc', url: ' https://docs.blockscout.com/for-users/api/eth-rpc',
}, },
].filter(Boolean); ].filter(Boolean);
...@@ -149,42 +135,42 @@ export default function useNavItems(): ReturnType { ...@@ -149,42 +135,42 @@ export default function useNavItems(): ReturnType {
const mainNavItems: ReturnType['mainNavItems'] = [ const mainNavItems: ReturnType['mainNavItems'] = [
{ {
text: 'Blockchain', text: 'Blockchain',
icon: globeIcon, icon: 'globe-b',
isActive: blockchainNavItems.flat().some(item => isInternalItem(item) && item.isActive), isActive: blockchainNavItems.flat().some(item => isInternalItem(item) && item.isActive),
subItems: blockchainNavItems, subItems: blockchainNavItems,
}, },
{ {
text: 'Tokens', text: 'Tokens',
nextRoute: { pathname: '/tokens' as const }, nextRoute: { pathname: '/tokens' as const },
icon: tokensIcon, icon: 'token',
isActive: pathname.startsWith('/token'), isActive: pathname.startsWith('/token'),
}, },
config.features.marketplace.isEnabled ? { config.features.marketplace.isEnabled ? {
text: 'Apps', text: 'Apps',
nextRoute: { pathname: '/apps' as const }, nextRoute: { pathname: '/apps' as const },
icon: appsIcon, icon: 'apps',
isActive: pathname.startsWith('/app'), isActive: pathname.startsWith('/app'),
} : null, } : null,
config.features.stats.isEnabled ? { config.features.stats.isEnabled ? {
text: 'Charts & stats', text: 'Charts & stats',
nextRoute: { pathname: '/stats' as const }, nextRoute: { pathname: '/stats' as const },
icon: statsIcon, icon: 'stats',
isActive: pathname === '/stats', isActive: pathname === '/stats',
} : null, } : null,
apiNavItems.length > 0 && { apiNavItems.length > 0 && {
text: 'API', text: 'API',
icon: apiDocsIcon, icon: 'restAPI',
isActive: apiNavItems.some(item => isInternalItem(item) && item.isActive), isActive: apiNavItems.some(item => isInternalItem(item) && item.isActive),
subItems: apiNavItems, subItems: apiNavItems,
}, },
{ {
text: 'Other', text: 'Other',
icon: gearIcon, icon: 'gear',
subItems: [ subItems: [
{ {
text: 'Verify contract', text: 'Verify contract',
nextRoute: { pathname: '/contract-verification' as const }, nextRoute: { pathname: '/contract-verification' as const },
icon: verifyContractIcon, icon: 'verify-contract',
isActive: pathname.startsWith('/contract-verification'), isActive: pathname.startsWith('/contract-verification'),
}, },
...config.UI.sidebar.otherLinks, ...config.UI.sidebar.otherLinks,
...@@ -196,35 +182,37 @@ export default function useNavItems(): ReturnType { ...@@ -196,35 +182,37 @@ export default function useNavItems(): ReturnType {
{ {
text: 'Watch list', text: 'Watch list',
nextRoute: { pathname: '/account/watchlist' as const }, nextRoute: { pathname: '/account/watchlist' as const },
icon: watchlistIcon, icon: 'watchlist',
isActive: pathname === '/account/watchlist', isActive: pathname === '/account/watchlist',
}, },
{ {
text: 'Private tags', text: 'Private tags',
nextRoute: { pathname: '/account/tag-address' as const }, nextRoute: { pathname: '/account/tag-address' as const },
icon: privateTagIcon, icon: 'privattags',
isActive: pathname === '/account/tag-address', isActive: pathname === '/account/tag-address',
}, },
{ {
text: 'Public tags', text: 'Public tags',
nextRoute: { pathname: '/account/public-tags-request' as const }, nextRoute: { pathname: '/account/public-tags-request' as const },
icon: publicTagIcon, isActive: pathname === '/account/public-tags-request', icon: 'publictags',
isActive: pathname === '/account/public-tags-request',
}, },
{ {
text: 'API keys', text: 'API keys',
nextRoute: { pathname: '/account/api-key' as const }, nextRoute: { pathname: '/account/api-key' as const },
icon: apiKeysIcon, isActive: pathname === '/account/api-key', icon: 'API',
isActive: pathname === '/account/api-key',
}, },
{ {
text: 'Custom ABI', text: 'Custom ABI',
nextRoute: { pathname: '/account/custom-abi' as const }, nextRoute: { pathname: '/account/custom-abi' as const },
icon: abiIcon, icon: 'ABI',
isActive: pathname === '/account/custom-abi', isActive: pathname === '/account/custom-abi',
}, },
config.features.addressVerification.isEnabled && { config.features.addressVerification.isEnabled && {
text: 'Verified addrs', text: 'Verified addrs',
nextRoute: { pathname: '/account/verified-addresses' as const }, nextRoute: { pathname: '/account/verified-addresses' as const },
icon: verifiedIcon, icon: 'verified',
isActive: pathname === '/account/verified-addresses', isActive: pathname === '/account/verified-addresses',
}, },
].filter(Boolean); ].filter(Boolean);
......
import type { WalletType, WalletInfo } from 'types/client/wallets'; import type { WalletType, WalletInfo } from 'types/client/wallets';
import coinbaseIcon from 'icons/wallets/coinbase.svg';
import metamaskIcon from 'icons/wallets/metamask.svg';
import tokenPocketIcon from 'icons/wallets/token-pocket.svg';
export const WALLETS_INFO: Record<Exclude<WalletType, 'none'>, WalletInfo> = { export const WALLETS_INFO: Record<Exclude<WalletType, 'none'>, WalletInfo> = {
metamask: { metamask: {
name: 'MetaMask', name: 'MetaMask',
icon: metamaskIcon, icon: 'wallets/metamask',
}, },
coinbase: { coinbase: {
name: 'Coinbase Wallet', name: 'Coinbase Wallet',
icon: coinbaseIcon, icon: 'wallets/coinbase',
}, },
token_pocket: { token_pocket: {
name: 'TokenPocket', name: 'TokenPocket',
icon: tokenPocketIcon, icon: 'wallets/token-pocket',
}, },
}; };
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
"lint:tsc": "tsc -p ./tsconfig.json", "lint:tsc": "tsc -p ./tsconfig.json",
"lint:envs-validator:test": "cd ./deploy/tools/envs-validator && ./test.sh", "lint:envs-validator:test": "cd ./deploy/tools/envs-validator && ./test.sh",
"prepare": "husky install", "prepare": "husky install",
"format-svg": "svgo -r ./icons", "svg:format": "svgo -r ./icons",
"svg:build-sprite": "icons build -i ./icons -o ./public/icons --optimize",
"test:pw": "./tools/scripts/pw.sh", "test:pw": "./tools/scripts/pw.sh",
"test:pw:local": "export NODE_PATH=$(pwd)/node_modules && yarn test:pw", "test:pw:local": "export NODE_PATH=$(pwd)/node_modules && yarn test:pw",
"test:pw:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.35.1-focal ./tools/scripts/pw.docker.sh", "test:pw:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.35.1-focal ./tools/scripts/pw.docker.sh",
...@@ -136,6 +137,7 @@ ...@@ -136,6 +137,7 @@
"lint-staged": ">=10", "lint-staged": ">=10",
"mockdate": "^3.0.5", "mockdate": "^3.0.5",
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"svg-icons-cli": "^0.0.5",
"svgo": "^2.8.0", "svgo": "^2.8.0",
"ts-jest": "^29.0.3", "ts-jest": "^29.0.3",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
......
...@@ -6,6 +6,7 @@ import React from 'react'; ...@@ -6,6 +6,7 @@ import React from 'react';
import * as serverTiming from 'nextjs/utils/serverTiming'; import * as serverTiming from 'nextjs/utils/serverTiming';
import theme from 'theme'; import theme from 'theme';
import * as svgSprite from 'ui/shared/IconSvg';
class MyDocument extends Document { class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) { static async getInitialProps(ctx: DocumentContext) {
...@@ -48,6 +49,8 @@ class MyDocument extends Document { ...@@ -48,6 +49,8 @@ class MyDocument extends Document {
<link rel="icon" sizes="16x16" type="image/png"href="/favicon/favicon-16x16.png"/> <link rel="icon" sizes="16x16" type="image/png"href="/favicon/favicon-16x16.png"/>
<link rel="apple-touch-icon" href="/favicon/apple-touch-icon-180x180.png"/> <link rel="apple-touch-icon" href="/favicon/apple-touch-icon-180x180.png"/>
<link rel="mask-icon" href="/favicon/safari-pinned-tab.svg"/> <link rel="mask-icon" href="/favicon/safari-pinned-tab.svg"/>
<link rel="preload" as="image" href={ svgSprite.href }/>
</Head> </Head>
<body> <body>
<ColorModeScript initialColorMode={ theme.config.initialColorMode }/> <ColorModeScript initialColorMode={ theme.config.initialColorMode }/>
......
...@@ -9,5 +9,6 @@ ...@@ -9,5 +9,6 @@
<div id="root"></div> <div id="root"></div>
<script type="module" src="/playwright/envs.js"></script> <script type="module" src="/playwright/envs.js"></script>
<script type="module" src="/playwright/index.ts"></script> <script type="module" src="/playwright/index.ts"></script>
<link rel="preload" as="image" href="/public/icons/sprite.svg"/>
</body> </body>
</html> </html>
// This file is generated by npm run build:icons
export type IconName =
| "ABI"
| "API"
| "apps"
| "arrows/down-right"
| "arrows/east-mini"
| "arrows/east"
| "arrows/north-east"
| "arrows/south-east"
| "arrows/up-down"
| "block_slim"
| "block"
| "brands/safe"
| "burger"
| "check"
| "clock-light"
| "clock"
| "coins/bitcoin"
| "collection"
| "contract_verified"
| "contract"
| "copy"
| "cross"
| "delete"
| "discussions"
| "docs"
| "donate"
| "edit"
| "email-sent"
| "email"
| "empty_search_result"
| "error-pages/404"
| "error-pages/422"
| "error-pages/429"
| "error-pages/500"
| "explorer"
| "files/csv"
| "files/image"
| "files/json"
| "files/placeholder"
| "files/sol"
| "files/yul"
| "filter"
| "finalized"
| "flame"
| "gas"
| "gear"
| "globe-b"
| "globe"
| "graphQL"
| "info"
| "key"
| "link"
| "lock"
| "minus"
| "monaco/file"
| "monaco/folder-open"
| "monaco/folder"
| "monaco/solidity"
| "monaco/vyper"
| "moon-with-star"
| "moon"
| "networks"
| "networks/icon-placeholder"
| "networks/logo-placeholder"
| "nft_shield"
| "output_roots"
| "plus"
| "privattags"
| "profile"
| "publictags_slim"
| "publictags"
| "qr_code"
| "repeat_arrow"
| "restAPI"
| "rocket"
| "RPC"
| "scope"
| "score/score-not-ok"
| "score/score-ok"
| "search"
| "social/canny"
| "social/coingecko"
| "social/coinmarketcap"
| "social/defi_llama"
| "social/discord_filled"
| "social/discord"
| "social/facebook_filled"
| "social/git"
| "social/github_filled"
| "social/linkedin_filled"
| "social/medium_filled"
| "social/opensea_filled"
| "social/reddit_filled"
| "social/slack_filled"
| "social/stats"
| "social/telega"
| "social/telegram_filled"
| "social/tweet"
| "social/twitter_filled"
| "star_filled"
| "star_outline"
| "stats"
| "status/error"
| "status/pending"
| "status/success"
| "status/warning"
| "sun"
| "testnet"
| "token-placeholder"
| "token"
| "tokens"
| "tokens/xdai"
| "top-accounts"
| "transactions_slim"
| "transactions"
| "txn_batches_slim"
| "txn_batches"
| "unfinalized"
| "uniswap"
| "verified_token"
| "verified"
| "verify-contract"
| "vertical_dots"
| "wallet"
| "wallets/coinbase"
| "wallets/metamask"
| "wallets/token-pocket"
| "watchlist";
\ No newline at end of file
...@@ -5,11 +5,11 @@ module.exports = { ...@@ -5,11 +5,11 @@ module.exports = {
params: { params: {
overrides: { overrides: {
removeViewBox: false, removeViewBox: false,
removeHiddenElems: false,
}, },
}, },
}, },
'removeDimensions', 'removeDimensions',
'prefixIds',
], ],
js2svg: { js2svg: {
indent: 2, indent: 2,
......
...@@ -19,6 +19,9 @@ dotenv \ ...@@ -19,6 +19,9 @@ dotenv \
-e $config_file \ -e $config_file \
-- bash -c './deploy/scripts/download_assets.sh ./public/assets' -- bash -c './deploy/scripts/download_assets.sh ./public/assets'
yarn svg:build-sprite
echo ""
# generate envs.js file and run the app # generate envs.js file and run the app
dotenv \ dotenv \
-v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \ -v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \
......
...@@ -8,6 +8,9 @@ dotenv \ ...@@ -8,6 +8,9 @@ dotenv \
-e .env \ -e .env \
-- bash -c './deploy/scripts/download_assets.sh ./public/assets' -- bash -c './deploy/scripts/download_assets.sh ./public/assets'
yarn svg:build-sprite
echo ""
# generate envs.js file and run the app # generate envs.js file and run the app
dotenv \ dotenv \
-v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \ -v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \
......
...@@ -8,6 +8,8 @@ dotenv \ ...@@ -8,6 +8,8 @@ dotenv \
-e $config_file \ -e $config_file \
-- bash -c './deploy/scripts/make_envs_script.sh ./playwright/envs.js' -- bash -c './deploy/scripts/make_envs_script.sh ./playwright/envs.js'
yarn svg:build-sprite
dotenv \ dotenv \
-v NODE_OPTIONS=\"--max-old-space-size=4096\" \ -v NODE_OPTIONS=\"--max-old-space-size=4096\" \
-e $config_file \ -e $config_file \
......
...@@ -2,8 +2,10 @@ import type React from 'react'; ...@@ -2,8 +2,10 @@ import type React from 'react';
import type { Route } from 'nextjs-routes'; import type { Route } from 'nextjs-routes';
import type { IconName } from 'ui/shared/IconSvg';
type NavIconOrComponent = { type NavIconOrComponent = {
icon?: React.FunctionComponent<React.SVGAttributes<SVGElement>>; icon?: IconName;
} | { } | {
iconComponent?: React.FC<{size?: number}>; iconComponent?: React.FC<{size?: number}>;
}; };
......
import type { ArrayElement } from 'types/utils'; import type { ArrayElement } from 'types/utils';
import type { IconName } from 'ui/shared/IconSvg';
export const SUPPORTED_WALLETS = [ export const SUPPORTED_WALLETS = [
'metamask', 'metamask',
'coinbase', 'coinbase',
...@@ -10,5 +12,5 @@ export type WalletType = ArrayElement<typeof SUPPORTED_WALLETS>; ...@@ -10,5 +12,5 @@ export type WalletType = ArrayElement<typeof SUPPORTED_WALLETS>;
export interface WalletInfo { export interface WalletInfo {
name: string; name: string;
icon: React.ElementType; icon: IconName;
} }
import { chakra, Icon, Tooltip, Hide, Skeleton, Flex } from '@chakra-ui/react'; import { chakra, Tooltip, Hide, Skeleton, Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { CsvExportParams } from 'types/client/address'; import type { CsvExportParams } from 'types/client/address';
...@@ -6,9 +6,9 @@ import type { CsvExportParams } from 'types/client/address'; ...@@ -6,9 +6,9 @@ import type { CsvExportParams } from 'types/client/address';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import svgFileIcon from 'icons/files/csv.svg';
import useIsInitialLoading from 'lib/hooks/useIsInitialLoading'; import useIsInitialLoading from 'lib/hooks/useIsInitialLoading';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
interface Props { interface Props {
...@@ -47,7 +47,7 @@ const AddressCsvExportLink = ({ className, address, params, isLoading }: Props) ...@@ -47,7 +47,7 @@ const AddressCsvExportLink = ({ className, address, params, isLoading }: Props)
href={ route({ pathname: '/csv-export', query: { ...params, address } }) } href={ route({ pathname: '/csv-export', query: { ...params, address } }) }
flexShrink={ 0 } flexShrink={ 0 }
> >
<Icon as={ svgFileIcon } boxSize={{ base: '30px', lg: 6 }}/> <IconSvg name="files/csv" boxSize={{ base: '30px', lg: 6 }}/>
<Hide ssr={ false } below="lg"><chakra.span ml={ 1 }>Download CSV</chakra.span></Hide> <Hide ssr={ false } below="lg"><chakra.span ml={ 1 }>Download CSV</chakra.span></Hide>
</LinkInternal> </LinkInternal>
</Tooltip> </Tooltip>
......
...@@ -5,8 +5,6 @@ import React from 'react'; ...@@ -5,8 +5,6 @@ import React from 'react';
import type { NFTTokenType } from 'types/api/token'; import type { NFTTokenType } from 'types/api/token';
import type { PaginationParams } from 'ui/shared/pagination/types'; import type { PaginationParams } from 'ui/shared/pagination/types';
import listIcon from 'icons/apps.svg';
import collectionIcon from 'icons/collection.svg';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery'; import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
...@@ -125,8 +123,8 @@ const AddressTokens = () => { ...@@ -125,8 +123,8 @@ const AddressTokens = () => {
defaultValue={ nftDisplayType } defaultValue={ nftDisplayType }
name="type" name="type"
options={ [ options={ [
{ title: 'By collection', value: 'collection', icon: collectionIcon, onlyIcon: isMobile }, { title: 'By collection', value: 'collection', icon: 'collection', onlyIcon: isMobile },
{ title: 'List', value: 'list', icon: listIcon, onlyIcon: isMobile }, { title: 'List', value: 'list', icon: 'apps', onlyIcon: isMobile },
] } ] }
/> />
); );
......
...@@ -4,7 +4,6 @@ import { ...@@ -4,7 +4,6 @@ import {
Text, Text,
Grid, Grid,
Button, Button,
Icon,
chakra, chakra,
Popover, Popover,
PopoverTrigger, PopoverTrigger,
...@@ -19,10 +18,9 @@ import React from 'react'; ...@@ -19,10 +18,9 @@ import React from 'react';
import { SolidityscanReport } from 'types/api/contract'; import { SolidityscanReport } from 'types/api/contract';
import scoreNotOkIcon from 'icons/score/score-not-ok.svg';
import scoreOkIcon from 'icons/score/score-ok.svg';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { SOLIDITYSCAN_REPORT } from 'stubs/contract'; import { SOLIDITYSCAN_REPORT } from 'stubs/contract';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal'; import LinkExternal from 'ui/shared/LinkExternal';
type DistributionItem = { type DistributionItem = {
...@@ -125,7 +123,7 @@ const SolidityscanReport = ({ className, hash }: Props) => { ...@@ -125,7 +123,7 @@ const SolidityscanReport = ({ className, hash }: Props) => {
h="32px" h="32px"
flexShrink={ 0 } flexShrink={ 0 }
> >
<Icon as={ score < 80 ? scoreNotOkIcon : scoreOkIcon } boxSize={ 5 } mr={ 1 }/> <IconSvg name={ score < 80 ? 'score/score-not-ok' : 'score/score-ok' } boxSize={ 5 } mr={ 1 }/>
{ score } { score }
</Button> </Button>
</Skeleton> </Skeleton>
...@@ -143,7 +141,7 @@ const SolidityscanReport = ({ className, hash }: Props) => { ...@@ -143,7 +141,7 @@ const SolidityscanReport = ({ className, hash }: Props) => {
mr={ 3 } mr={ 3 }
> >
<Center position="absolute" w="38px" h="38px" top="5px" right="5px" bg={ popoverBgColor } borderRadius="20px"> <Center position="absolute" w="38px" h="38px" top="5px" right="5px" bg={ popoverBgColor } borderRadius="20px">
<Icon as={ score < 80 ? scoreNotOkIcon : scoreOkIcon } boxSize={ 5 } color={ scoreColor }/> <IconSvg name={ score < 80 ? 'score/score-not-ok' : 'score/score-ok' } boxSize={ 5 } color={ scoreColor }/>
</Center> </Center>
</Box> </Box>
<Box> <Box>
......
...@@ -78,6 +78,31 @@ test('verified with changed byte code socket', async({ mount, page, createSocket ...@@ -78,6 +78,31 @@ test('verified with changed byte code socket', async({ mount, page, createSocket
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
test('verified via lookup in eth_bytecode_db', async({ mount, page, createSocket }) => {
await page.route(CONTRACT_API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(contractMock.nonVerified),
}));
await page.route('https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/**', (route) => route.abort());
await mount(
<TestApp withSocket>
<ContractCode addressHash={ addressHash }/>
</TestApp>,
{ hooksConfig },
);
const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, 'addresses:' + addressHash.toLowerCase());
await page.waitForResponse(CONTRACT_API_URL);
socketServer.sendMessage(socket, channel, 'smart_contract_was_verified', {});
const request = await page.waitForRequest(CONTRACT_API_URL);
expect(request).toBeTruthy();
});
test('verified with multiple sources', async({ mount, page }) => { test('verified with multiple sources', async({ mount, page }) => {
await page.route(CONTRACT_API_URL, (route) => route.fulfill({ await page.route(CONTRACT_API_URL, (route) => route.fulfill({
status: 200, status: 200,
......
...@@ -38,7 +38,6 @@ const ContractCode = ({ addressHash, noSocket }: Props) => { ...@@ -38,7 +38,6 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
const [ isChangedBytecodeSocket, setIsChangedBytecodeSocket ] = React.useState<boolean>(); const [ isChangedBytecodeSocket, setIsChangedBytecodeSocket ] = React.useState<boolean>();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const refetchQueries = queryClient.refetchQueries;
const addressInfo = queryClient.getQueryData<AddressInfo>(getResourceKey('address', { pathParams: { hash: addressHash } })); const addressInfo = queryClient.getQueryData<AddressInfo>(getResourceKey('address', { pathParams: { hash: addressHash } }));
const { data, isPlaceholderData, isError } = useApiQuery('contract', { const { data, isPlaceholderData, isError } = useApiQuery('contract', {
...@@ -55,13 +54,13 @@ const ContractCode = ({ addressHash, noSocket }: Props) => { ...@@ -55,13 +54,13 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
}, [ ]); }, [ ]);
const handleContractWasVerifiedMessage: SocketMessage.SmartContractWasVerified['handler'] = React.useCallback(() => { const handleContractWasVerifiedMessage: SocketMessage.SmartContractWasVerified['handler'] = React.useCallback(() => {
refetchQueries({ queryClient.refetchQueries({
queryKey: getResourceKey('address', { pathParams: { hash: addressHash } }), queryKey: getResourceKey('address', { pathParams: { hash: addressHash } }),
}); });
refetchQueries({ queryClient.refetchQueries({
queryKey: getResourceKey('contract', { pathParams: { hash: addressHash } }), queryKey: getResourceKey('contract', { pathParams: { hash: addressHash } }),
}); });
}, [ addressHash, refetchQueries ]); }, [ addressHash, queryClient ]);
const enableQuery = React.useCallback(() => setIsQueryEnabled(true), []); const enableQuery = React.useCallback(() => setIsQueryEnabled(true), []);
......
...@@ -4,7 +4,6 @@ import { ...@@ -4,7 +4,6 @@ import {
Button, Button,
Flex, Flex,
Heading, Heading,
Icon,
Modal, Modal,
ModalCloseButton, ModalCloseButton,
ModalContent, ModalContent,
...@@ -20,11 +19,10 @@ import React from 'react'; ...@@ -20,11 +19,10 @@ import React from 'react';
import type { SmartContractExternalLibrary } from 'types/api/contract'; import type { SmartContractExternalLibrary } from 'types/api/contract';
import arrowIcon from 'icons/arrows/east-mini.svg';
import iconWarning from 'icons/status/warning.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import { apos } from 'lib/html-entities'; import { apos } from 'lib/html-entities';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -66,8 +64,8 @@ const ContractExternalLibraries = ({ className, data }: Props) => { ...@@ -66,8 +64,8 @@ const ContractExternalLibraries = ({ className, data }: Props) => {
aria-label="View external libraries" aria-label="View external libraries"
> >
<span>{ data.length } { data.length > 1 ? 'Libraries' : 'Library' } </span> <span>{ data.length } { data.length > 1 ? 'Libraries' : 'Library' } </span>
<Icon as={ iconWarning } boxSize={ 5 } color="orange.400" ml="2px"/> <IconSvg name="status/warning" boxSize={ 5 } color="orange.400" ml="2px"/>
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 2 }/> <IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 2 }/>
</Button> </Button>
); );
......
import { Box, Button, chakra, Flex, Icon, Text } from '@chakra-ui/react'; import { Box, Button, chakra, Flex, Text } from '@chakra-ui/react';
import _fromPairs from 'lodash/fromPairs'; import _fromPairs from 'lodash/fromPairs';
import React from 'react'; import React from 'react';
import type { SubmitHandler } from 'react-hook-form'; import type { SubmitHandler } from 'react-hook-form';
...@@ -7,8 +7,8 @@ import { useForm } from 'react-hook-form'; ...@@ -7,8 +7,8 @@ import { useForm } from 'react-hook-form';
import type { MethodFormFields, ContractMethodCallResult } from './types'; import type { MethodFormFields, ContractMethodCallResult } from './types';
import type { SmartContractMethodInput, SmartContractMethod } from 'types/api/contract'; import type { SmartContractMethodInput, SmartContractMethod } from 'types/api/contract';
import arrowIcon from 'icons/arrows/down-right.svg';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
import ContractMethodField from './ContractMethodField'; import ContractMethodField from './ContractMethodField';
...@@ -157,7 +157,7 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit, ...@@ -157,7 +157,7 @@ const ContractMethodCallable = <T extends SmartContractMethod>({ data, onSubmit,
</chakra.form> </chakra.form>
{ 'outputs' in data && !isWrite && data.outputs.length > 0 && ( { 'outputs' in data && !isWrite && data.outputs.length > 0 && (
<Flex mt={ 3 }> <Flex mt={ 3 }>
<Icon as={ arrowIcon } boxSize={ 5 } mr={ 1 }/> <IconSvg name="arrows/down-right" boxSize={ 5 } mr={ 1 }/>
<Text>{ data.outputs.map(({ type }) => type).join(', ') }</Text> <Text>{ data.outputs.map(({ type }) => type).join(', ') }</Text>
</Flex> </Flex>
) } ) }
......
...@@ -8,15 +8,13 @@ import { ...@@ -8,15 +8,13 @@ import {
Button, Button,
List, List,
ListItem, ListItem,
Icon,
useDisclosure, useDisclosure,
Input, Input,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconEastMini from 'icons/arrows/east-mini.svg';
import iconCheck from 'icons/check.svg';
import { times } from 'lib/html-entities'; import { times } from 'lib/html-entities';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
onClick: (power: number) => void; onClick: (power: number) => void;
...@@ -80,7 +78,7 @@ const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => { ...@@ -80,7 +78,7 @@ const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => {
onClick={ onToggle } onClick={ onToggle }
isDisabled={ isDisabled } isDisabled={ isDisabled }
> >
<Icon as={ iconEastMini } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } boxSize={ 6 }/> <IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } boxSize={ 6 }/>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<Portal> <Portal>
...@@ -99,7 +97,7 @@ const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => { ...@@ -99,7 +97,7 @@ const ContractMethodFieldZeroes = ({ onClick, isDisabled }: Props) => {
cursor="pointer" cursor="pointer"
> >
<span>10*{ id }</span> <span>10*{ id }</span>
{ selectedOption === id && <Icon as={ iconCheck } boxSize={ 6 } color="blue.600"/> } { selectedOption === id && <IconSvg name="check" boxSize={ 6 } color="blue.600"/> }
</ListItem> </ListItem>
)) } )) }
<ListItem <ListItem
......
import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Icon, Tooltip, useClipboard, useDisclosure } from '@chakra-ui/react'; import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Tooltip, useClipboard, useDisclosure } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { Element } from 'react-scroll'; import { Element } from 'react-scroll';
...@@ -7,8 +7,8 @@ import type { SmartContractMethod } from 'types/api/contract'; ...@@ -7,8 +7,8 @@ import type { SmartContractMethod } from 'types/api/contract';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import iconLink from 'icons/link.svg';
import Hint from 'ui/shared/Hint'; import Hint from 'ui/shared/Hint';
import IconSvg from 'ui/shared/IconSvg';
interface Props<T extends SmartContractMethod> { interface Props<T extends SmartContractMethod> {
data: T; data: T;
...@@ -57,7 +57,7 @@ const ContractMethodsAccordionItem = <T extends SmartContractMethod>({ data, ind ...@@ -57,7 +57,7 @@ const ContractMethodsAccordionItem = <T extends SmartContractMethod>({ data, ind
onMouseEnter={ onOpen } onMouseEnter={ onOpen }
onMouseLeave={ onClose } onMouseLeave={ onClose }
> >
<Icon as={ iconLink } boxSize={ 5 }/> <IconSvg name="link" boxSize={ 5 }/>
</Box> </Box>
</Tooltip> </Tooltip>
) } ) }
......
import { Icon, chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react'; import { chakra, Tooltip, IconButton, useDisclosure } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import useIsAccountActionAllowed from 'lib/hooks/useIsAccountActionAllowed'; import useIsAccountActionAllowed from 'lib/hooks/useIsAccountActionAllowed';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing'; import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal'; import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal'; import DeleteAddressModal from 'ui/watchlist/DeleteAddressModal';
...@@ -73,7 +72,7 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => { ...@@ -73,7 +72,7 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => {
pr="6px" pr="6px"
flexShrink={ 0 } flexShrink={ 0 }
onClick={ handleClick } onClick={ handleClick }
icon={ <Icon as={ watchListId ? starFilledIcon : starOutlineIcon } boxSize={ 5 }/> } icon={ <IconSvg name={ watchListId ? 'star_filled' : 'star_outline' } boxSize={ 5 }/> }
onFocusCapture={ onFocusCapture } onFocusCapture={ onFocusCapture }
/> />
</Tooltip> </Tooltip>
......
import { import {
chakra, chakra,
Alert, Alert,
Icon,
Modal, Modal,
ModalBody, ModalBody,
ModalContent, ModalContent,
...@@ -22,10 +21,10 @@ import React from 'react'; ...@@ -22,10 +21,10 @@ import React from 'react';
import type { Address as AddressType } from 'types/api/address'; import type { Address as AddressType } from 'types/api/address';
import qrCodeIcon from 'icons/qr_code.svg';
import getPageType from 'lib/mixpanel/getPageType'; import getPageType from 'lib/mixpanel/getPageType';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import IconSvg from 'ui/shared/IconSvg';
const SVG_OPTIONS = { const SVG_OPTIONS = {
margin: 0, margin: 0,
...@@ -78,7 +77,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => { ...@@ -78,7 +77,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => {
pl="6px" pl="6px"
pr="6px" pr="6px"
onClick={ onOpen } onClick={ onOpen }
icon={ <Icon as={ qrCodeIcon } boxSize={ 5 }/> } icon={ <IconSvg name="qr_code" boxSize={ 5 }/> }
flexShrink={ 0 } flexShrink={ 0 }
/> />
</Tooltip> </Tooltip>
......
...@@ -5,13 +5,12 @@ import React from 'react'; ...@@ -5,13 +5,12 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction'; import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app'; import config from 'configs/app';
import eastArrowIcon from 'icons/arrows/east.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
...@@ -76,7 +75,7 @@ const TxInternalsListItem = ({ ...@@ -76,7 +75,7 @@ const TxInternalsListItem = ({
/> />
{ (isIn || isOut) ? { (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading }/> : <InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading }/> :
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
} }
{ toData && ( { toData && (
<AddressEntity <AddressEntity
......
...@@ -5,13 +5,12 @@ import React from 'react'; ...@@ -5,13 +5,12 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction'; import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils'; import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
...@@ -89,7 +88,7 @@ const AddressIntTxsTableItem = ({ ...@@ -89,7 +88,7 @@ const AddressIntTxsTableItem = ({
<Td px={ 0 } verticalAlign="middle"> <Td px={ 0 } verticalAlign="middle">
{ (isIn || isOut) ? { (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading } w="100%"/> : <InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading } w="100%"/> :
<Icon as={ rightArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
} }
</Td> </Td>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
......
import { Box, Flex, Icon, IconButton, Skeleton, Tooltip } from '@chakra-ui/react'; import { Box, Flex, IconButton, Skeleton, Tooltip } from '@chakra-ui/react';
import { useQueryClient, useIsFetching } from '@tanstack/react-query'; import { useQueryClient, useIsFetching } from '@tanstack/react-query';
import _sumBy from 'lodash/sumBy'; import _sumBy from 'lodash/sumBy';
import NextLink from 'next/link'; import NextLink from 'next/link';
...@@ -7,11 +7,11 @@ import React from 'react'; ...@@ -7,11 +7,11 @@ import React from 'react';
import type { Address } from 'types/api/address'; import type { Address } from 'types/api/address';
import walletIcon from 'icons/wallet.svg';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import IconSvg from 'ui/shared/IconSvg';
import useFetchTokens from '../utils/useFetchTokens'; import useFetchTokens from '../utils/useFetchTokens';
import TokenSelectDesktop from './TokenSelectDesktop'; import TokenSelectDesktop from './TokenSelectDesktop';
...@@ -69,7 +69,7 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -69,7 +69,7 @@ const TokenSelect = ({ onClick }: Props) => {
size="sm" size="sm"
pl="6px" pl="6px"
pr="6px" pr="6px"
icon={ <Icon as={ walletIcon } boxSize={ 5 }/> } icon={ <IconSvg name="wallet" boxSize={ 5 }/> }
as="a" as="a"
onClick={ handleIconButtonClick } onClick={ handleIconButtonClick }
/> />
......
import { Box, Button, Icon, Skeleton, Text, useColorModeValue } from '@chakra-ui/react'; import { Box, Button, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FormattedData } from './types'; import type { FormattedData } from './types';
import arrowIcon from 'icons/arrows/east-mini.svg';
import tokensIcon from 'icons/tokens.svg';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
import { getTokensTotalInfo } from '../utils/tokenUtils'; import { getTokensTotalInfo } from '../utils/tokenUtils';
...@@ -41,10 +40,10 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea ...@@ -41,10 +40,10 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea
onClick={ handleClick } onClick={ handleClick }
aria-label="Token select" aria-label="Token select"
> >
<Icon as={ tokensIcon } boxSize={ 4 } mr={ 2 }/> <IconSvg name="tokens" boxSize={ 4 } mr={ 2 }/>
<Text fontWeight={ 600 }>{ prefix }{ num }</Text> <Text fontWeight={ 600 }>{ prefix }{ num }</Text>
<Text whiteSpace="pre" variant="secondary" fontWeight={ 400 }> ({ prefix }${ usd.toFormat(2) })</Text> <Text whiteSpace="pre" variant="secondary" fontWeight={ 400 }> ({ prefix }${ usd.toFormat(2) })</Text>
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 3 }/> <IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 3 }/>
</Button> </Button>
{ isLoading && !isOpen && <Skeleton h="100%" w="100%" position="absolute" top={ 0 } left={ 0 } bgColor={ skeletonBgColor }/> } { isLoading && !isOpen && <Skeleton h="100%" w="100%" position="absolute" top={ 0 } left={ 0 } bgColor={ skeletonBgColor }/> }
</Box> </Box>
......
import { Icon, Text, Box, Input, InputGroup, InputLeftElement, useColorModeValue, Flex, Link } from '@chakra-ui/react'; import { Text, Box, Input, InputGroup, InputLeftElement, useColorModeValue, Flex, Link } from '@chakra-ui/react';
import _sumBy from 'lodash/sumBy'; import _sumBy from 'lodash/sumBy';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -6,8 +6,7 @@ import React from 'react'; ...@@ -6,8 +6,7 @@ import React from 'react';
import type { FormattedData } from './types'; import type { FormattedData } from './types';
import type { TokenType } from 'types/api/token'; import type { TokenType } from 'types/api/token';
import arrowIcon from 'icons/arrows/east.svg'; import IconSvg from 'ui/shared/IconSvg';
import searchIcon from 'icons/search.svg';
import type { Sort } from '../utils/tokenUtils'; import type { Sort } from '../utils/tokenUtils';
import { sortTokenGroups, sortingFns } from '../utils/tokenUtils'; import { sortTokenGroups, sortingFns } from '../utils/tokenUtils';
...@@ -32,7 +31,7 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, filteredData, onInputChange, ...@@ -32,7 +31,7 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, filteredData, onInputChange,
<> <>
<InputGroup size="xs" mb={ 5 }> <InputGroup size="xs" mb={ 5 }>
<InputLeftElement > <InputLeftElement >
<Icon as={ searchIcon } boxSize={ 4 } color={ searchIconColor }/> <IconSvg name="search" boxSize={ 4 } color={ searchIconColor }/>
</InputLeftElement> </InputLeftElement>
<Input <Input
paddingInlineStart="38px" paddingInlineStart="38px"
...@@ -72,7 +71,7 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, filteredData, onInputChange, ...@@ -72,7 +71,7 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, filteredData, onInputChange,
<Text mb={ 3 } color="gray.500" fontWeight={ 600 } fontSize="sm">{ type } tokens ({ numPrefix }{ tokenInfo.items.length })</Text> <Text mb={ 3 } color="gray.500" fontWeight={ 600 } fontSize="sm">{ type } tokens ({ numPrefix }{ tokenInfo.items.length })</Text>
{ hasSort && ( { hasSort && (
<Link data-type={ type } onClick={ onSortClick } aria-label={ `Sort ${ type } tokens` }> <Link data-type={ type } onClick={ onSortClick } aria-label={ `Sort ${ type } tokens` }>
<Icon as={ arrowIcon } boxSize={ 5 } transform={ arrowTransform } transitionDuration="faster"/> <IconSvg name="arrows/east" boxSize={ 5 } transform={ arrowTransform } transitionDuration="faster"/>
</Link> </Link>
) } ) }
</Flex> </Flex>
......
...@@ -22,7 +22,13 @@ const ERC20TokensTableItem = ({ ...@@ -22,7 +22,13 @@ const ERC20TokensTableItem = ({
} = getCurrencyValue({ value: value, exchangeRate: token.exchange_rate, decimals: token.decimals, accuracy: 8, accuracyUsd: 2 }); } = getCurrencyValue({ value: value, exchangeRate: token.exchange_rate, decimals: token.decimals, accuracy: 8, accuracyUsd: 2 });
return ( return (
<Tr> <Tr
sx={{
'&:hover [aria-label="Add token to wallet"]': {
opacity: 1,
},
}}
>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
<TokenEntity <TokenEntity
token={ token } token={ token }
...@@ -39,7 +45,7 @@ const ERC20TokensTableItem = ({ ...@@ -39,7 +45,7 @@ const ERC20TokensTableItem = ({
isLoading={ isLoading } isLoading={ isLoading }
noIcon noIcon
/> />
<AddressAddToWallet token={ token } ml={ 4 } isLoading={ isLoading }/> <AddressAddToWallet token={ token } ml={ 4 } isLoading={ isLoading } opacity="0"/>
</Flex> </Flex>
</Td> </Td>
<Td isNumeric verticalAlign="middle"> <Td isNumeric verticalAlign="middle">
......
import { Box, Flex, Icon, Skeleton, Text, useColorModeValue } from '@chakra-ui/react'; import { Box, Flex, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import walletIcon from 'icons/wallet.svg'; import IconSvg from 'ui/shared/IconSvg';
const TokenBalancesItem = ({ name, value, isLoading }: {name: string; value: string; isLoading: boolean }) => { const TokenBalancesItem = ({ name, value, isLoading }: {name: string; value: string; isLoading: boolean }) => {
...@@ -9,7 +9,7 @@ const TokenBalancesItem = ({ name, value, isLoading }: {name: string; value: str ...@@ -9,7 +9,7 @@ const TokenBalancesItem = ({ name, value, isLoading }: {name: string; value: str
return ( return (
<Flex p={ 5 } bgColor={ bgColor } borderRadius="16px" alignItems="center"> <Flex p={ 5 } bgColor={ bgColor } borderRadius="16px" alignItems="center">
<Icon as={ walletIcon } boxSize="30px" mr={ 3 }/> <IconSvg name="wallet" boxSize="30px" mr={ 3 }/>
<Box> <Box>
<Text variant="secondary" fontSize="xs">{ name }</Text> <Text variant="secondary" fontSize="xs">{ name }</Text>
<Skeleton isLoaded={ !isLoading } fontWeight="500">{ value }</Skeleton> <Skeleton isLoaded={ !isLoading } fontWeight="500">{ value }</Skeleton>
......
import { Icon, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Link } from '@chakra-ui/react'; import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { AddressVerificationFormFirstStepFields, AddressCheckStatusSuccess } from './types'; import type { AddressVerificationFormFirstStepFields, AddressCheckStatusSuccess } from './types';
import type { VerifiedAddress } from 'types/api/account'; import type { VerifiedAddress } from 'types/api/account';
import eastArrowIcon from 'icons/arrows/east.svg';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
import Web3ModalProvider from 'ui/shared/Web3ModalProvider'; import Web3ModalProvider from 'ui/shared/Web3ModalProvider';
import AddressVerificationStepAddress from './steps/AddressVerificationStepAddress'; import AddressVerificationStepAddress from './steps/AddressVerificationStepAddress';
...@@ -100,7 +100,7 @@ const AddressVerificationModal = ({ defaultAddress, isOpen, onClose, onSubmit, o ...@@ -100,7 +100,7 @@ const AddressVerificationModal = ({ defaultAddress, isOpen, onClose, onSubmit, o
<ModalHeader fontWeight="500" textStyle="h3" mb={ 6 }> <ModalHeader fontWeight="500" textStyle="h3" mb={ 6 }>
{ stepIndex !== 0 && ( { stepIndex !== 0 && (
<Link mr={ 3 } onClick={ handleGoToPrevStep }> <Link mr={ 3 } onClick={ handleGoToPrevStep }>
<Icon as={ eastArrowIcon } boxSize={ 6 } transform="rotate(180deg)" verticalAlign="middle"/> <IconSvg name="arrows/east" boxSize={ 6 } transform="rotate(180deg)" verticalAlign="middle"/>
</Link> </Link>
) } ) }
<span>{ step.title }</span> <span>{ step.title }</span>
......
...@@ -11,8 +11,6 @@ import type { Block } from 'types/api/block'; ...@@ -11,8 +11,6 @@ import type { Block } from 'types/api/block';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import clockIcon from 'icons/clock.svg';
import flameIcon from 'icons/flame.svg';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import getBlockReward from 'lib/block/getBlockReward'; import getBlockReward from 'lib/block/getBlockReward';
import { GWEI, WEI, WEI_IN_GWEI, ZERO } from 'lib/consts'; import { GWEI, WEI, WEI_IN_GWEI, ZERO } from 'lib/consts';
...@@ -20,7 +18,6 @@ import dayjs from 'lib/date/dayjs'; ...@@ -20,7 +18,6 @@ import dayjs from 'lib/date/dayjs';
import { space } from 'lib/html-entities'; import { space } from 'lib/html-entities';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
...@@ -28,6 +25,7 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider'; ...@@ -28,6 +25,7 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio'; import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import PrevNext from 'ui/shared/PrevNext'; import PrevNext from 'ui/shared/PrevNext';
import RawDataSnippet from 'ui/shared/RawDataSnippet'; import RawDataSnippet from 'ui/shared/RawDataSnippet';
...@@ -169,7 +167,7 @@ const BlockDetails = ({ query }: Props) => { ...@@ -169,7 +167,7 @@ const BlockDetails = ({ query }: Props) => {
hint="Date & time at which block was produced." hint="Date & time at which block was produced."
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/> <IconSvg name="clock" boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
<Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }> <Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }>
{ dayjs(data.timestamp).fromNow() } { dayjs(data.timestamp).fromNow() }
</Skeleton> </Skeleton>
...@@ -318,7 +316,7 @@ const BlockDetails = ({ query }: Props) => { ...@@ -318,7 +316,7 @@ const BlockDetails = ({ query }: Props) => {
} }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/> <IconSvg name="flame" boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
<Skeleton isLoaded={ !isPlaceholderData } ml={ 2 }> <Skeleton isLoaded={ !isPlaceholderData } ml={ 2 }>
{ burntFees.dividedBy(WEI).toFixed() } { config.chain.currency.symbol } { burntFees.dividedBy(WEI).toFixed() } { config.chain.currency.symbol }
</Skeleton> </Skeleton>
......
...@@ -8,15 +8,14 @@ import type { Block } from 'types/api/block'; ...@@ -8,15 +8,14 @@ import type { Block } from 'types/api/block';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import flameIcon from 'icons/flame.svg';
import getBlockTotalReward from 'lib/block/getBlockTotalReward'; import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import { WEI } from 'lib/consts'; import { WEI } from 'lib/consts';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import BlockTimestamp from 'ui/blocks/BlockTimestamp'; import BlockTimestamp from 'ui/blocks/BlockTimestamp';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio'; import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
...@@ -106,7 +105,7 @@ const BlocksListItem = ({ data, isLoading, enableTimeIncrement }: Props) => { ...@@ -106,7 +105,7 @@ const BlocksListItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
<Text fontWeight={ 500 }>Burnt fees</Text> <Text fontWeight={ 500 }>Burnt fees</Text>
<Flex columnGap={ 4 } mt={ 2 }> <Flex columnGap={ 4 } mt={ 2 }>
<Flex> <Flex>
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="flame" boxSize={ 5 } color="gray.500" isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } display="inline-block" color="text_secondary" ml={ 2 }> <Skeleton isLoaded={ !isLoading } display="inline-block" color="text_secondary" ml={ 2 }>
<span>{ burntFees.div(WEI).toFixed() }</span> <span>{ burntFees.div(WEI).toFixed() }</span>
</Skeleton> </Skeleton>
......
...@@ -8,14 +8,13 @@ import type { Block } from 'types/api/block'; ...@@ -8,14 +8,13 @@ import type { Block } from 'types/api/block';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import flameIcon from 'icons/flame.svg';
import getBlockTotalReward from 'lib/block/getBlockTotalReward'; import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import { WEI } from 'lib/consts'; import { WEI } from 'lib/consts';
import BlockTimestamp from 'ui/blocks/BlockTimestamp'; import BlockTimestamp from 'ui/blocks/BlockTimestamp';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio'; import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
import Utilization from 'ui/shared/Utilization/Utilization'; import Utilization from 'ui/shared/Utilization/Utilization';
...@@ -116,7 +115,7 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => { ...@@ -116,7 +115,7 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
{ !isRollup && !config.UI.views.block.hiddenFields?.burnt_fees && ( { !isRollup && !config.UI.views.block.hiddenFields?.burnt_fees && (
<Td fontSize="sm"> <Td fontSize="sm">
<Flex alignItems="center" columnGap={ 2 }> <Flex alignItems="center" columnGap={ 2 }>
<Icon as={ flameIcon } boxSize={ 5 } color={ burntFeesIconColor } isLoading={ isLoading }/> <IconSvg name="flame" boxSize={ 5 } color={ burntFeesIconColor } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton isLoaded={ !isLoading } display="inline-block">
{ burntFees.dividedBy(WEI).toFixed(8) } { burntFees.dividedBy(WEI).toFixed(8) }
</Skeleton> </Skeleton>
......
import { chakra, Checkbox, Code, Icon } from '@chakra-ui/react'; import { chakra, Checkbox, Code } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
import type { ControllerRenderProps } from 'react-hook-form'; import type { ControllerRenderProps } from 'react-hook-form';
...@@ -7,10 +7,10 @@ import { useFormContext, Controller } from 'react-hook-form'; ...@@ -7,10 +7,10 @@ import { useFormContext, Controller } from 'react-hook-form';
import type { FormFields } from '../types'; import type { FormFields } from '../types';
import type { SmartContractVerificationConfig } from 'types/api/contract'; import type { SmartContractVerificationConfig } from 'types/api/contract';
import iconSearch from 'icons/search.svg';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import FancySelect from 'ui/shared/FancySelect/FancySelect'; import FancySelect from 'ui/shared/FancySelect/FancySelect';
import IconSvg from 'ui/shared/IconSvg';
import ContractVerificationFormRow from '../ContractVerificationFormRow'; import ContractVerificationFormRow from '../ContractVerificationFormRow';
...@@ -56,7 +56,7 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => { ...@@ -56,7 +56,7 @@ const ContractVerificationFieldCompiler = ({ isVyper }: Props) => {
defaultOptions defaultOptions
size={ isMobile ? 'md' : 'lg' } size={ isMobile ? 'md' : 'lg' }
placeholder="Compiler (enter version or use the dropdown)" placeholder="Compiler (enter version or use the dropdown)"
placeholderIcon={ <Icon as={ iconSearch }/> } placeholderIcon={ <IconSvg name="search"/> }
isDisabled={ formState.isSubmitting } isDisabled={ formState.isSubmitting }
error={ error } error={ error }
isRequired isRequired
......
import { Flex, FormControl, Icon, IconButton, Input, Text } from '@chakra-ui/react'; import { Flex, FormControl, IconButton, Input, Text } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { Control, ControllerRenderProps, FieldError } from 'react-hook-form'; import type { Control, ControllerRenderProps, FieldError } from 'react-hook-form';
import { Controller } from 'react-hook-form'; import { Controller } from 'react-hook-form';
import type { FormFields } from '../types'; import type { FormFields } from '../types';
import minusIcon from 'icons/minus.svg';
import plusIcon from 'icons/plus.svg';
import { ADDRESS_REGEXP } from 'lib/validations/address'; import { ADDRESS_REGEXP } from 'lib/validations/address';
import IconSvg from 'ui/shared/IconSvg';
import InputPlaceholder from 'ui/shared/InputPlaceholder'; import InputPlaceholder from 'ui/shared/InputPlaceholder';
import ContractVerificationFormRow from '../ContractVerificationFormRow'; import ContractVerificationFormRow from '../ContractVerificationFormRow';
...@@ -86,7 +85,7 @@ const ContractVerificationFieldLibraryItem = ({ control, index, fieldsLength, on ...@@ -86,7 +85,7 @@ const ContractVerificationFieldLibraryItem = ({ control, index, fieldsLength, on
w="30px" w="30px"
h="30px" h="30px"
onClick={ handleRemoveButtonClick } onClick={ handleRemoveButtonClick }
icon={ <Icon as={ minusIcon } w="20px" h="20px"/> } icon={ <IconSvg name="minus" w="20px" h="20px"/> }
isDisabled={ isDisabled } isDisabled={ isDisabled }
/> />
) } ) }
...@@ -97,7 +96,7 @@ const ContractVerificationFieldLibraryItem = ({ control, index, fieldsLength, on ...@@ -97,7 +96,7 @@ const ContractVerificationFieldLibraryItem = ({ control, index, fieldsLength, on
w="30px" w="30px"
h="30px" h="30px"
onClick={ handleAddButtonClick } onClick={ handleAddButtonClick }
icon={ <Icon as={ plusIcon } w="20px" h="20px"/> } icon={ <IconSvg name="plus" w="20px" h="20px"/> }
isDisabled={ isDisabled } isDisabled={ isDisabled }
/> />
) } ) }
......
import { import {
Link, Link,
Icon,
chakra, chakra,
Popover, Popover,
PopoverTrigger, PopoverTrigger,
...@@ -20,9 +19,9 @@ import { Controller } from 'react-hook-form'; ...@@ -20,9 +19,9 @@ import { Controller } from 'react-hook-form';
import type { FormFields } from '../types'; import type { FormFields } from '../types';
import type { SmartContractVerificationConfig, SmartContractVerificationMethod } from 'types/api/contract'; import type { SmartContractVerificationConfig, SmartContractVerificationMethod } from 'types/api/contract';
import infoIcon from 'icons/info.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import FancySelect from 'ui/shared/FancySelect/FancySelect'; import FancySelect from 'ui/shared/FancySelect/FancySelect';
import IconSvg from 'ui/shared/IconSvg';
import { METHOD_LABELS } from '../utils'; import { METHOD_LABELS } from '../utils';
...@@ -105,7 +104,7 @@ const ContractVerificationFieldMethod = ({ control, isDisabled, methods }: Props ...@@ -105,7 +104,7 @@ const ContractVerificationFieldMethod = ({ control, isDisabled, methods }: Props
<Popover trigger="hover" isLazy placement={ isMobile ? 'bottom-end' : 'right-start' } offset={ [ -8, 8 ] }> <Popover trigger="hover" isLazy placement={ isMobile ? 'bottom-end' : 'right-start' } offset={ [ -8, 8 ] }>
<PopoverTrigger> <PopoverTrigger>
<chakra.span display="inline-block" ml={ 1 } cursor="pointer" verticalAlign="middle" h="22px"> <chakra.span display="inline-block" ml={ 1 } cursor="pointer" verticalAlign="middle" h="22px">
<Icon as={ infoIcon } boxSize={ 5 } color="link" _hover={{ color: 'link_hovered' }}/> <IconSvg name="info" boxSize={ 5 } color="link" _hover={{ color: 'link_hovered' }}/>
</chakra.span> </chakra.span>
</PopoverTrigger> </PopoverTrigger>
<Portal> <Portal>
......
...@@ -11,12 +11,11 @@ import React from 'react'; ...@@ -11,12 +11,11 @@ import React from 'react';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import getValueWithUnit from 'lib/getValueWithUnit'; import getValueWithUnit from 'lib/getValueWithUnit';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
import TxFeeStability from 'ui/shared/tx/TxFeeStability'; import TxFeeStability from 'ui/shared/tx/TxFeeStability';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags'; import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
...@@ -81,8 +80,8 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -81,8 +80,8 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
</Box> </Box>
</Flex> </Flex>
<Flex alignItems="center" alignSelf="flex-start"> <Flex alignItems="center" alignSelf="flex-start">
<Icon <IconSvg
as={ rightArrowIcon } name="arrows/east"
boxSize={ 6 } boxSize={ 6 }
color="gray.500" color="gray.500"
transform="rotate(90deg)" transform="rotate(90deg)"
......
...@@ -10,12 +10,11 @@ import React from 'react'; ...@@ -10,12 +10,11 @@ import React from 'react';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import getValueWithUnit from 'lib/getValueWithUnit'; import getValueWithUnit from 'lib/getValueWithUnit';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
import TxFeeStability from 'ui/shared/tx/TxFeeStability'; import TxFeeStability from 'ui/shared/tx/TxFeeStability';
import TxWatchListTags from 'ui/shared/tx/TxWatchListTags'; import TxWatchListTags from 'ui/shared/tx/TxWatchListTags';
...@@ -76,8 +75,8 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => { ...@@ -76,8 +75,8 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
fontWeight="500" fontWeight="500"
mr={ 2 } mr={ 2 }
/> />
<Icon <IconSvg
as={ rightArrowIcon } name="arrows/east"
boxSize={ 6 } boxSize={ 6 }
color="gray.500" color="gray.500"
isLoading={ isLoading } isLoading={ isLoading }
......
...@@ -5,13 +5,6 @@ import React from 'react'; ...@@ -5,13 +5,6 @@ import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import blockIcon from 'icons/block.svg';
import clockIcon from 'icons/clock-light.svg';
import bitcoinIcon from 'icons/coins/bitcoin.svg';
import gasIcon from 'icons/gas.svg';
import txIcon from 'icons/transactions.svg';
import batchesIcon from 'icons/txn_batches.svg';
import walletIcon from 'icons/wallet.svg';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { WEI } from 'lib/consts'; import { WEI } from 'lib/consts';
import { HOMEPAGE_STATS } from 'stubs/stats'; import { HOMEPAGE_STATS } from 'stubs/stats';
...@@ -58,7 +51,7 @@ const Stats = () => { ...@@ -58,7 +51,7 @@ const Stats = () => {
<> <>
{ config.features.zkEvmRollup.isEnabled ? ( { config.features.zkEvmRollup.isEnabled ? (
<StatsItem <StatsItem
icon={ batchesIcon } icon="txn_batches"
title="Latest batch" title="Latest batch"
value={ (zkEvmLatestBatchQuery.data || 0).toLocaleString() } value={ (zkEvmLatestBatchQuery.data || 0).toLocaleString() }
url={ route({ pathname: '/zkevm-l2-txn-batches' }) } url={ route({ pathname: '/zkevm-l2-txn-batches' }) }
...@@ -66,7 +59,7 @@ const Stats = () => { ...@@ -66,7 +59,7 @@ const Stats = () => {
/> />
) : ( ) : (
<StatsItem <StatsItem
icon={ blockIcon } icon="block"
title="Total blocks" title="Total blocks"
value={ Number(data.total_blocks).toLocaleString() } value={ Number(data.total_blocks).toLocaleString() }
url={ route({ pathname: '/blocks' }) } url={ route({ pathname: '/blocks' }) }
...@@ -75,21 +68,21 @@ const Stats = () => { ...@@ -75,21 +68,21 @@ const Stats = () => {
) } ) }
{ hasAvgBlockTime && ( { hasAvgBlockTime && (
<StatsItem <StatsItem
icon={ clockIcon } icon="clock-light"
title="Average block time" title="Average block time"
value={ `${ (data.average_block_time / 1000).toFixed(1) }s` } value={ `${ (data.average_block_time / 1000).toFixed(1) }s` }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
/> />
) } ) }
<StatsItem <StatsItem
icon={ txIcon } icon="transactions"
title="Total transactions" title="Total transactions"
value={ Number(data.total_transactions).toLocaleString() } value={ Number(data.total_transactions).toLocaleString() }
url={ route({ pathname: '/txs' }) } url={ route({ pathname: '/txs' }) }
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
/> />
<StatsItem <StatsItem
icon={ walletIcon } icon="wallet"
title="Wallet addresses" title="Wallet addresses"
value={ Number(data.total_addresses).toLocaleString() } value={ Number(data.total_addresses).toLocaleString() }
_last={ isOdd ? lastItemTouchStyle : undefined } _last={ isOdd ? lastItemTouchStyle : undefined }
...@@ -97,7 +90,7 @@ const Stats = () => { ...@@ -97,7 +90,7 @@ const Stats = () => {
/> />
{ hasGasTracker && data.gas_prices && ( { hasGasTracker && data.gas_prices && (
<StatsItem <StatsItem
icon={ gasIcon } icon="gas"
title="Gas tracker" title="Gas tracker"
value={ `${ Number(data.gas_prices.average).toLocaleString() } Gwei` } value={ `${ Number(data.gas_prices.average).toLocaleString() } Gwei` }
_last={ isOdd ? lastItemTouchStyle : undefined } _last={ isOdd ? lastItemTouchStyle : undefined }
...@@ -107,7 +100,7 @@ const Stats = () => { ...@@ -107,7 +100,7 @@ const Stats = () => {
) } ) }
{ data.rootstock_locked_btc && ( { data.rootstock_locked_btc && (
<StatsItem <StatsItem
icon={ bitcoinIcon } icon="coins/bitcoin"
title="BTC Locked in 2WP" title="BTC Locked in 2WP"
value={ `${ BigNumber(data.rootstock_locked_btc).div(WEI).dp(0).toFormat() } RBTC` } value={ `${ BigNumber(data.rootstock_locked_btc).div(WEI).dp(0).toFormat() } RBTC` }
_last={ isOdd ? lastItemTouchStyle : undefined } _last={ isOdd ? lastItemTouchStyle : undefined }
......
...@@ -3,11 +3,12 @@ import { Skeleton, Flex, useColorModeValue, chakra, LightMode } from '@chakra-ui ...@@ -3,11 +3,12 @@ import { Skeleton, Flex, useColorModeValue, chakra, LightMode } from '@chakra-ui
import React from 'react'; import React from 'react';
import breakpoints from 'theme/foundations/breakpoints'; import breakpoints from 'theme/foundations/breakpoints';
import Icon from 'ui/shared/chakra/Icon';
import Hint from 'ui/shared/Hint'; import Hint from 'ui/shared/Hint';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
icon: React.FC<React.SVGAttributes<SVGElement>>; icon: IconName;
title: string; title: string;
value: string; value: string;
className?: string; className?: string;
...@@ -57,7 +58,7 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url, isLoading ...@@ -57,7 +58,7 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url, isLoading
href: url, href: url,
} : {}) } } : {}) }
> >
<Icon as={ icon } boxSize={ 7 } isLoading={ isLoading } borderRadius="base"/> <IconSvg name={ icon } boxSize={ 7 } isLoading={ isLoading } borderRadius="base"/>
<Flex <Flex
flexDirection="column" flexDirection="column"
alignItems="start" alignItems="start"
......
import { Icon } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TChainIndicator } from '../types'; import type { TChainIndicator } from '../types';
import config from 'configs/app'; import config from 'configs/app';
import globeIcon from 'icons/globe.svg';
import lockIcon from 'icons/lock.svg';
import txIcon from 'icons/transactions.svg';
import { sortByDateDesc } from 'ui/shared/chart/utils/sorts'; import { sortByDateDesc } from 'ui/shared/chart/utils/sorts';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = { const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
id: 'daily_txs', id: 'daily_txs',
title: 'Daily transactions', title: 'Daily transactions',
value: (stats) => Number(stats.transactions_today).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }), value: (stats) => Number(stats.transactions_today).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
icon: <Icon as={ txIcon } boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>, icon: <IconSvg name="transactions" boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>,
hint: `Number of transactions yesterday (0:00 - 23:59 UTC). The chart displays daily transactions for the past 30 days.`, hint: `Number of transactions yesterday (0:00 - 23:59 UTC). The chart displays daily transactions for the past 30 days.`,
api: { api: {
resourceName: 'homepage_chart_txs', resourceName: 'homepage_chart_txs',
...@@ -58,7 +55,7 @@ const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = { ...@@ -58,7 +55,7 @@ const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
id: 'market_cap', id: 'market_cap',
title: 'Market cap', title: 'Market cap',
value: (stats) => '$' + Number(stats.market_cap).toLocaleString(undefined, { maximumFractionDigits: 0, notation: 'compact' }), value: (stats) => '$' + Number(stats.market_cap).toLocaleString(undefined, { maximumFractionDigits: 0, notation: 'compact' }),
icon: <Icon as={ globeIcon } boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>, icon: <IconSvg name="globe" boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.', hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.',
api: { api: {
...@@ -81,7 +78,7 @@ const tvlIndicator: TChainIndicator<'homepage_chart_market'> = { ...@@ -81,7 +78,7 @@ const tvlIndicator: TChainIndicator<'homepage_chart_market'> = {
id: 'tvl', id: 'tvl',
title: 'Total value locked', title: 'Total value locked',
value: (stats) => '$' + Number(stats.tvl).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }), value: (stats) => '$' + Number(stats.tvl).toLocaleString(undefined, { maximumFractionDigits: 2, notation: 'compact' }),
icon: <Icon as={ lockIcon } boxSize={ 6 } bgColor="#517FDB" borderRadius="base" color="white"/>, icon: <IconSvg name="lock" boxSize={ 6 } bgColor="#517FDB" borderRadius="base" color="white"/>,
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
hint: 'Total value of digital assets locked or staked in a chain', hint: 'Total value of digital assets locked or staked in a chain',
api: { api: {
......
import { Box, Icon, IconButton, Image, Link, LinkBox, Skeleton, useColorModeValue } from '@chakra-ui/react'; import { Box, IconButton, Image, Link, LinkBox, Skeleton, useColorModeValue } from '@chakra-ui/react';
import type { MouseEvent } from 'react'; import type { MouseEvent } from 'react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { MarketplaceAppPreview } from 'types/client/marketplace'; import type { MarketplaceAppPreview } from 'types/client/marketplace';
import northEastIcon from 'icons/arrows/north-east.svg'; import IconSvg from 'ui/shared/IconSvg';
import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg';
import MarketplaceAppCardLink from './MarketplaceAppCardLink'; import MarketplaceAppCardLink from './MarketplaceAppCardLink';
...@@ -152,8 +150,8 @@ const MarketplaceAppCard = ({ ...@@ -152,8 +150,8 @@ const MarketplaceAppCard = ({
> >
More More
<Icon <IconSvg
as={ northEastIcon } name="arrows/north-east"
marginLeft={ 1 } marginLeft={ 1 }
/> />
</Link> </Link>
...@@ -175,8 +173,8 @@ const MarketplaceAppCard = ({ ...@@ -175,8 +173,8 @@ const MarketplaceAppCard = ({
h={ 8 } h={ 8 }
onClick={ handleFavoriteClick } onClick={ handleFavoriteClick }
icon={ isFavorite ? icon={ isFavorite ?
<Icon as={ starFilledIcon } w={ 4 } h={ 4 } color="yellow.400"/> : <IconSvg name="star_filled" w={ 4 } h={ 4 } color="yellow.400"/> :
<Icon as={ starOutlineIcon } w={ 4 } h={ 4 } color="gray.300"/> <IconSvg name="star_outline" w={ 4 } h={ 4 } color="gray.300"/>
} }
/> />
) } ) }
......
import { import {
Box, Flex, Heading, Icon, IconButton, Image, Link, List, Modal, ModalBody, Box, Flex, Heading, IconButton, Image, Link, List, Modal, ModalBody,
ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Tag, Text, useColorModeValue, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Tag, Text, useColorModeValue,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { MarketplaceAppOverview } from 'types/client/marketplace'; import type { MarketplaceAppOverview } from 'types/client/marketplace';
import linkIcon from 'icons/link.svg';
import ghIcon from 'icons/social/git.svg';
import tgIcon from 'icons/social/telega.svg';
import twIcon from 'icons/social/tweet.svg';
import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import { nbsp } from 'lib/html-entities'; import { nbsp } from 'lib/html-entities';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
import MarketplaceAppModalLink from './MarketplaceAppModalLink'; import MarketplaceAppModalLink from './MarketplaceAppModalLink';
...@@ -47,15 +43,15 @@ const MarketplaceAppModal = ({ ...@@ -47,15 +43,15 @@ const MarketplaceAppModal = ({
const socialLinks = [ const socialLinks = [
telegram ? { telegram ? {
icon: tgIcon, icon: 'social/telega' as IconName,
url: telegram, url: telegram,
} : null, } : null,
twitter ? { twitter ? {
icon: twIcon, icon: 'social/tweet' as IconName,
url: twitter, url: twitter,
} : null, } : null,
github ? { github ? {
icon: ghIcon, icon: 'social/git' as IconName,
url: github, url: github,
} : null, } : null,
].filter(Boolean); ].filter(Boolean);
...@@ -138,8 +134,8 @@ const MarketplaceAppModal = ({ ...@@ -138,8 +134,8 @@ const MarketplaceAppModal = ({
h={ 8 } h={ 8 }
onClick={ handleFavoriteClick } onClick={ handleFavoriteClick }
icon={ isFavorite ? icon={ isFavorite ?
<Icon as={ starFilledIcon } w={ 4 } h={ 4 } color="yellow.400"/> : <IconSvg name="star_filled" w={ 4 } h={ 4 } color="yellow.400"/> :
<Icon as={ starOutlineIcon } w={ 4 } h={ 4 } color="gray.300"/> } <IconSvg name="star_outline" w={ 4 } h={ 4 } color="gray.300"/> }
/> />
</Box> </Box>
</Box> </Box>
...@@ -188,8 +184,8 @@ const MarketplaceAppModal = ({ ...@@ -188,8 +184,8 @@ const MarketplaceAppModal = ({
maxW="100%" maxW="100%"
overflow="hidden" overflow="hidden"
> >
<Icon <IconSvg
as={ linkIcon } name="link"
display="inline" display="inline"
verticalAlign="baseline" verticalAlign="baseline"
boxSize="18px" boxSize="18px"
...@@ -227,8 +223,8 @@ const MarketplaceAppModal = ({ ...@@ -227,8 +223,8 @@ const MarketplaceAppModal = ({
w={ 10 } w={ 10 }
h={ 10 } h={ 10 }
> >
<Icon <IconSvg
as={ icon } name={ icon }
w="20px" w="20px"
h="20px" h="20px"
display="block" display="block"
......
import { Box, Button, Icon, Menu, MenuButton, MenuList, Skeleton } from '@chakra-ui/react'; import { Box, Button, Menu, MenuButton, MenuList, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { MarketplaceCategory } from 'types/client/marketplace'; import { MarketplaceCategory } from 'types/client/marketplace';
import eastMiniArrowIcon from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
import MarketplaceCategoriesMenuItem from './MarketplaceCategoriesMenuItem'; import MarketplaceCategoriesMenuItem from './MarketplaceCategoriesMenuItem';
...@@ -50,7 +50,7 @@ const MarketplaceCategoriesMenu = ({ selectedCategoryId, onSelect, categories, i ...@@ -50,7 +50,7 @@ const MarketplaceCategoriesMenu = ({ selectedCategoryId, onSelect, categories, i
alignItems="center" alignItems="center"
> >
{ selectedCategoryId } { selectedCategoryId }
<Icon transform="rotate(-90deg)" ml={{ base: 'auto', sm: 1 }} as={ eastMiniArrowIcon } w={ 5 } h={ 5 }/> <IconSvg transform="rotate(-90deg)" ml={{ base: 'auto', sm: 1 }} name="arrows/east-mini" w={ 5 } h={ 5 }/>
</Box> </Box>
</MenuButton> </MenuButton>
......
import { Icon, MenuItem } from '@chakra-ui/react'; import { MenuItem } from '@chakra-ui/react';
import type { FunctionComponent, SVGAttributes } from 'react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { MarketplaceCategory } from 'types/client/marketplace'; import { MarketplaceCategory } from 'types/client/marketplace';
import starFilledIcon from 'icons/star_filled.svg'; import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
id: string; id: string;
onClick: (category: string) => void; onClick: (category: string) => void;
} }
const ICONS: Record<string, FunctionComponent<SVGAttributes<SVGElement>>> = { const ICONS: Record<string, IconName> = {
[MarketplaceCategory.FAVORITES]: starFilledIcon, [MarketplaceCategory.FAVORITES]: 'star_filled',
}; };
const MarketplaceCategoriesMenuItem = ({ id, onClick }: Props) => { const MarketplaceCategoriesMenuItem = ({ id, onClick }: Props) => {
...@@ -27,7 +27,7 @@ const MarketplaceCategoriesMenuItem = ({ id, onClick }: Props) => { ...@@ -27,7 +27,7 @@ const MarketplaceCategoriesMenuItem = ({ id, onClick }: Props) => {
display="flex" display="flex"
alignItems="center" alignItems="center"
> >
{ id in ICONS && <Icon mr={ 3 } as={ ICONS[id] } w={ 4 } h={ 4 } color="blackAlpha.800"/> } { id in ICONS && <IconSvg mr={ 3 } name={ ICONS[id] } w={ 4 } h={ 4 } color="blackAlpha.800"/> }
{ id } { id }
</MenuItem> </MenuItem>
); );
......
import { Box, Flex, HStack, Icon } from '@chakra-ui/react'; import { Box, Flex, HStack } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { RoutedTab } from 'ui/shared/Tabs/types'; import type { RoutedTab } from 'ui/shared/Tabs/types';
import config from 'configs/app'; import config from 'configs/app';
import iconSuccess from 'icons/status/success.svg';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import useContractTabs from 'lib/hooks/useContractTabs'; import useContractTabs from 'lib/hooks/useContractTabs';
...@@ -30,6 +29,7 @@ import TextAd from 'ui/shared/ad/TextAd'; ...@@ -30,6 +29,7 @@ import TextAd from 'ui/shared/ad/TextAd';
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet'; import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import EntityTags from 'ui/shared/EntityTags'; import EntityTags from 'ui/shared/EntityTags';
import IconSvg from 'ui/shared/IconSvg';
import NetworkExplorers from 'ui/shared/NetworkExplorers'; import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs'; import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
...@@ -127,7 +127,7 @@ const AddressPageContent = () => { ...@@ -127,7 +127,7 @@ const AddressPageContent = () => {
return ( return (
<> <>
<span>Contract</span> <span>Contract</span>
<Icon as={ iconSuccess } boxSize="14px" color="green.500" ml={ 1 }/> <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/>
</> </>
); );
} }
......
import { Box, Flex, Icon, Tooltip } from '@chakra-ui/react'; import { Box, Flex, Tooltip } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
...@@ -9,8 +9,6 @@ import type { PaginationParams } from 'ui/shared/pagination/types'; ...@@ -9,8 +9,6 @@ import type { PaginationParams } from 'ui/shared/pagination/types';
import type { RoutedTab } from 'ui/shared/Tabs/types'; import type { RoutedTab } from 'ui/shared/Tabs/types';
import config from 'configs/app'; import config from 'configs/app';
import iconSuccess from 'icons/status/success.svg';
import iconVerifiedToken from 'icons/verified_token.svg';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import useContractTabs from 'lib/hooks/useContractTabs'; import useContractTabs from 'lib/hooks/useContractTabs';
...@@ -30,6 +28,7 @@ import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet'; ...@@ -30,6 +28,7 @@ import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import EntityTags from 'ui/shared/EntityTags'; import EntityTags from 'ui/shared/EntityTags';
import IconSvg from 'ui/shared/IconSvg';
import NetworkExplorers from 'ui/shared/NetworkExplorers'; import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/pagination/Pagination'; import Pagination from 'ui/shared/pagination/Pagination';
...@@ -189,7 +188,7 @@ const TokenPageContent = () => { ...@@ -189,7 +188,7 @@ const TokenPageContent = () => {
return ( return (
<> <>
<span>Contract</span> <span>Contract</span>
<Icon as={ iconSuccess } boxSize="14px" color="green.500" ml={ 1 }/> <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/>
</> </>
); );
} }
...@@ -250,7 +249,7 @@ const TokenPageContent = () => { ...@@ -250,7 +249,7 @@ const TokenPageContent = () => {
{ verifiedInfoQuery.data?.tokenAddress && ( { verifiedInfoQuery.data?.tokenAddress && (
<Tooltip label={ `Information on this token has been verified by ${ config.chain.name }` }> <Tooltip label={ `Information on this token has been verified by ${ config.chain.name }` }>
<Box boxSize={ 6 }> <Box boxSize={ 6 }>
<Icon as={ iconVerifiedToken } color="green.500" boxSize={ 6 } cursor="pointer"/> <IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer"/>
</Box> </Box>
</Tooltip> </Tooltip>
) } ) }
......
import { Box, Text, Button, Heading, Icon, chakra } from '@chakra-ui/react'; import { Box, Text, Button, Heading, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconEmailSent from 'icons/email-sent.svg';
import useApiFetch from 'lib/api/useApiFetch'; import useApiFetch from 'lib/api/useApiFetch';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import getErrorObjPayload from 'lib/errors/getErrorObjPayload'; import getErrorObjPayload from 'lib/errors/getErrorObjPayload';
import getErrorObjStatusCode from 'lib/errors/getErrorObjStatusCode'; import getErrorObjStatusCode from 'lib/errors/getErrorObjStatusCode';
import useToast from 'lib/hooks/useToast'; import useToast from 'lib/hooks/useToast';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
email?: string; // TODO: obtain email from API email?: string; // TODO: obtain email from API
...@@ -77,7 +77,7 @@ const UnverifiedEmail = ({ email }: Props) => { ...@@ -77,7 +77,7 @@ const UnverifiedEmail = ({ email }: Props) => {
return ( return (
<Box> <Box>
<Icon as={ iconEmailSent } width="180px" height="auto" mt="52px"/> <IconSvg name="email-sent" width="180px" height="auto" mt="52px"/>
<Heading mt={ 6 } size="2xl">Verify your email address</Heading> <Heading mt={ 6 } size="2xl">Verify your email address</Heading>
<Text variant="secondary" mt={ 3 }> <Text variant="secondary" mt={ 3 }>
<span>Please confirm your email address to use the My Account feature. A confirmation email was sent to </span> <span>Please confirm your email address to use the My Account feature. A confirmation email was sent to </span>
......
import type { InputProps } from '@chakra-ui/react'; import type { InputProps } from '@chakra-ui/react';
import { IconButton, Icon, Flex } from '@chakra-ui/react'; import { IconButton, Flex } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { ControllerRenderProps, Control, FieldError } from 'react-hook-form'; import type { ControllerRenderProps, Control, FieldError } from 'react-hook-form';
import { Controller } from 'react-hook-form'; import { Controller } from 'react-hook-form';
import MinusIcon from 'icons/minus.svg';
import PlusIcon from 'icons/plus.svg';
import { ADDRESS_REGEXP } from 'lib/validations/address'; import { ADDRESS_REGEXP } from 'lib/validations/address';
import AddressInput from 'ui/shared/AddressInput'; import AddressInput from 'ui/shared/AddressInput';
import IconSvg from 'ui/shared/IconSvg';
import type { Inputs } from './PublicTagsForm'; import type { Inputs } from './PublicTagsForm';
...@@ -60,7 +59,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro ...@@ -60,7 +59,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro
w="30px" w="30px"
h="30px" h="30px"
onClick={ onRemoveFieldClick(index) } onClick={ onRemoveFieldClick(index) }
icon={ <Icon as={ MinusIcon } w="20px" h="20px"/> } icon={ <IconSvg name="minus" w="20px" h="20px"/> }
/> />
) } ) }
{ index === fieldsLength - 1 && fieldsLength < MAX_INPUTS_NUM && ( { index === fieldsLength - 1 && fieldsLength < MAX_INPUTS_NUM && (
...@@ -70,7 +69,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro ...@@ -70,7 +69,7 @@ export default function PublicTagFormAction({ control, index, fieldsLength, erro
w="30px" w="30px"
h="30px" h="30px"
onClick={ onAddFieldClick } onClick={ onAddFieldClick }
icon={ <Icon as={ PlusIcon } w="20px" h="20px"/> } icon={ <IconSvg name="plus" w="20px" h="20px"/> }
/> />
) } ) }
</Flex> </Flex>
......
import { Flex, Grid, Icon, Image, Box, Text, Skeleton, useColorMode, Tag } from '@chakra-ui/react'; import { Flex, Grid, Image, Box, Text, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import xss from 'xss'; import xss from 'xss';
...@@ -6,9 +6,6 @@ import type { SearchResultItem } from 'types/api/search'; ...@@ -6,9 +6,6 @@ import type { SearchResultItem } from 'types/api/search';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import labelIcon from 'icons/publictags_slim.svg';
import iconSuccess from 'icons/status/success.svg';
import verifiedToken from 'icons/verified_token.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import highlightText from 'lib/highlightText'; import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
...@@ -18,6 +15,7 @@ import * as BlockEntity from 'ui/shared/entities/block/BlockEntity'; ...@@ -18,6 +15,7 @@ import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import * as TxEntity from 'ui/shared/entities/tx/TxEntity'; import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal'; import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
...@@ -68,7 +66,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -68,7 +66,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
textOverflow="ellipsis" textOverflow="ellipsis"
/> />
</LinkInternal> </LinkInternal>
{ data.is_verified_via_admin_panel && <Icon as={ verifiedToken } boxSize={ 4 } ml={ 1 } color="green.500"/> } { data.is_verified_via_admin_panel && <IconSvg name="verified_token" boxSize={ 4 } ml={ 1 } color="green.500"/> }
</Flex> </Flex>
); );
} }
...@@ -107,7 +105,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -107,7 +105,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
case 'label': { case 'label': {
return ( return (
<Flex alignItems="center"> <Flex alignItems="center">
<Icon as={ labelIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <IconSvg name="publictags_slim" boxSize={ 6 } mr={ 2 } color="gray.500"/>
<LinkInternal <LinkInternal
href={ route({ pathname: '/address/[hash]', query: { hash: data.address } }) } href={ route({ pathname: '/address/[hash]', query: { hash: data.address } }) }
fontWeight={ 700 } fontWeight={ 700 }
...@@ -214,12 +212,12 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -214,12 +212,12 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
<Text whiteSpace="nowrap" overflow="hidden"> <Text whiteSpace="nowrap" overflow="hidden">
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.address } isTooltipDisabled/>
</Text> </Text>
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Skeleton> </Skeleton>
<Text overflow="hidden" whiteSpace="nowrap" textOverflow="ellipsis" fontWeight={ 700 }> <Skeleton isLoaded={ !isLoading } overflow="hidden" whiteSpace="nowrap" textOverflow="ellipsis" fontWeight={ 700 }>
{ data.token_type === 'ERC-20' && data.exchange_rate && `$${ Number(data.exchange_rate).toLocaleString() }` } { data.token_type === 'ERC-20' && data.exchange_rate && `$${ Number(data.exchange_rate).toLocaleString() }` }
{ data.token_type !== 'ERC-20' && data.total_supply && `Items ${ Number(data.total_supply).toLocaleString() }` } { data.token_type !== 'ERC-20' && data.total_supply && `Items ${ Number(data.total_supply).toLocaleString() }` }
</Text> </Skeleton>
</Grid> </Grid>
); );
} }
...@@ -245,7 +243,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -245,7 +243,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
<Box overflow="hidden"> <Box overflow="hidden">
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Flex> </Flex>
); );
} }
......
import { Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode, Tag } from '@chakra-ui/react'; import { Tr, Td, Text, Flex, Image, Box, Skeleton, useColorMode, Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import xss from 'xss'; import xss from 'xss';
...@@ -6,9 +6,6 @@ import type { SearchResultItem } from 'types/api/search'; ...@@ -6,9 +6,6 @@ import type { SearchResultItem } from 'types/api/search';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import labelIcon from 'icons/publictags_slim.svg';
import iconSuccess from 'icons/status/success.svg';
import verifiedToken from 'icons/verified_token.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import highlightText from 'lib/highlightText'; import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
...@@ -18,6 +15,7 @@ import * as BlockEntity from 'ui/shared/entities/block/BlockEntity'; ...@@ -18,6 +15,7 @@ import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import * as TxEntity from 'ui/shared/entities/tx/TxEntity'; import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal'; import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import type { SearchResultAppItem } from 'ui/shared/search/utils'; import type { SearchResultAppItem } from 'ui/shared/search/utils';
...@@ -68,7 +66,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -68,7 +66,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }} dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}
/> />
</LinkInternal> </LinkInternal>
{ data.is_verified_via_admin_panel && <Icon as={ verifiedToken } boxSize={ 4 } ml={ 1 } color="green.500"/> } { data.is_verified_via_admin_panel && <IconSvg name="verified_token" boxSize={ 4 } ml={ 1 } color="green.500"/> }
</Flex> </Flex>
</Td> </Td>
<Td fontSize="sm" verticalAlign="middle"> <Td fontSize="sm" verticalAlign="middle">
...@@ -76,7 +74,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -76,7 +74,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }> <Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Skeleton> </Skeleton>
</Td> </Td>
<Td fontSize="sm" verticalAlign="middle" isNumeric> <Td fontSize="sm" verticalAlign="middle" isNumeric>
...@@ -165,7 +163,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -165,7 +163,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
<> <>
<Td fontSize="sm"> <Td fontSize="sm">
<Flex alignItems="center"> <Flex alignItems="center">
<Icon as={ labelIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <IconSvg name="publictags_slim" boxSize={ 6 } mr={ 2 } color="gray.500"/>
<LinkInternal <LinkInternal
href={ route({ pathname: '/address/[hash]', query: { hash: data.address } }) } href={ route({ pathname: '/address/[hash]', query: { hash: data.address } }) }
fontWeight={ 700 } fontWeight={ 700 }
...@@ -182,7 +180,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => { ...@@ -182,7 +180,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
<Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }> <Box overflow="hidden" whiteSpace="nowrap" w={ data.is_smart_contract_verified ? 'calc(100%-28px)' : 'unset' }>
<HashStringShortenDynamic hash={ data.address }/> <HashStringShortenDynamic hash={ data.address }/>
</Box> </Box>
{ data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/> } { data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/> }
</Flex> </Flex>
</Td> </Td>
<Td></Td> <Td></Td>
......
import { Button, Menu, MenuButton, MenuList, Icon, Flex, Skeleton, chakra } from '@chakra-ui/react'; import { Button, Menu, MenuButton, MenuList, Flex, Skeleton, chakra } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import iconArrow from 'icons/arrows/east-mini.svg';
import useIsAccountActionAllowed from 'lib/hooks/useIsAccountActionAllowed'; import useIsAccountActionAllowed from 'lib/hooks/useIsAccountActionAllowed';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import IconSvg from 'ui/shared/IconSvg';
import PrivateTagMenuItem from './items/PrivateTagMenuItem'; import PrivateTagMenuItem from './items/PrivateTagMenuItem';
import PublicTagMenuItem from './items/PublicTagMenuItem'; import PublicTagMenuItem from './items/PublicTagMenuItem';
...@@ -44,7 +44,7 @@ const AccountActionsMenu = ({ isLoading, className }: Props) => { ...@@ -44,7 +44,7 @@ const AccountActionsMenu = ({ isLoading, className }: Props) => {
> >
<Flex alignItems="center"> <Flex alignItems="center">
<span>More</span> <span>More</span>
<Icon as={ iconArrow } transform="rotate(-90deg)" boxSize={ 5 } ml={ 1 }/> <IconSvg name="arrows/east-mini" transform="rotate(-90deg)" boxSize={ 5 } ml={ 1 }/>
</Flex> </Flex>
</MenuButton> </MenuButton>
</Skeleton> </Skeleton>
......
import { MenuItem, Icon, chakra, useDisclosure } from '@chakra-ui/react'; import { MenuItem, chakra, useDisclosure } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -6,11 +6,11 @@ import React from 'react'; ...@@ -6,11 +6,11 @@ import React from 'react';
import type { Address } from 'types/api/address'; import type { Address } from 'types/api/address';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import iconPrivateTags from 'icons/privattags.svg';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import getPageType from 'lib/mixpanel/getPageType'; import getPageType from 'lib/mixpanel/getPageType';
import AddressModal from 'ui/privateTags/AddressModal/AddressModal'; import AddressModal from 'ui/privateTags/AddressModal/AddressModal';
import TransactionModal from 'ui/privateTags/TransactionModal/TransactionModal'; import TransactionModal from 'ui/privateTags/TransactionModal/TransactionModal';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -61,7 +61,7 @@ const PrivateTagMenuItem = ({ className, hash, onBeforeClick, type = 'address' } ...@@ -61,7 +61,7 @@ const PrivateTagMenuItem = ({ className, hash, onBeforeClick, type = 'address' }
return ( return (
<> <>
<MenuItem className={ className } onClick={ handleClick }> <MenuItem className={ className } onClick={ handleClick }>
<Icon as={ iconPrivateTags } boxSize={ 6 } mr={ 2 }/> <IconSvg name="privattags" boxSize={ 6 } mr={ 2 }/>
<span>Add private tag</span> <span>Add private tag</span>
</MenuItem> </MenuItem>
{ type === 'tx' ? { type === 'tx' ?
......
import { MenuItem, Icon, chakra } from '@chakra-ui/react'; import { MenuItem, chakra } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import iconPublicTags from 'icons/publictags.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -23,7 +23,7 @@ const PublicTagMenuItem = ({ className, hash, onBeforeClick }: Props) => { ...@@ -23,7 +23,7 @@ const PublicTagMenuItem = ({ className, hash, onBeforeClick }: Props) => {
return ( return (
<MenuItem className={ className }onClick={ handleClick }> <MenuItem className={ className }onClick={ handleClick }>
<Icon as={ iconPublicTags } boxSize={ 6 } mr={ 2 }/> <IconSvg name="publictags" boxSize={ 6 } mr={ 2 }/>
<span>Add public tag</span> <span>Add public tag</span>
</MenuItem> </MenuItem>
); );
......
import { MenuItem, Icon, chakra, useDisclosure } from '@chakra-ui/react'; import { MenuItem, chakra, useDisclosure } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Route } from 'nextjs-routes'; import type { Route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import iconEdit from 'icons/edit.svg';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import useHasAccount from 'lib/hooks/useHasAccount'; import useHasAccount from 'lib/hooks/useHasAccount';
import { PAGE_TYPE_DICT } from 'lib/mixpanel/getPageType'; import { PAGE_TYPE_DICT } from 'lib/mixpanel/getPageType';
import AddressVerificationModal from 'ui/addressVerification/AddressVerificationModal'; import AddressVerificationModal from 'ui/addressVerification/AddressVerificationModal';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -61,7 +61,7 @@ const TokenInfoMenuItem = ({ className, hash, onBeforeClick }: Props) => { ...@@ -61,7 +61,7 @@ const TokenInfoMenuItem = ({ className, hash, onBeforeClick }: Props) => {
router.push({ pathname: '/account/verified-addresses' }); router.push({ pathname: '/account/verified-addresses' });
}, [ router ]); }, [ router ]);
const icon = <Icon as={ iconEdit } boxSize={ 6 } mr={ 2 } p={ 1 }/>; const icon = <IconSvg name="edit" boxSize={ 6 } mr={ 2 } p={ 1 }/>;
const content = (() => { const content = (() => {
if (!verifiedAddressesQuery.data?.verifiedAddresses.find(({ contractAddress }) => contractAddress.toLowerCase() === hash.toLowerCase())) { if (!verifiedAddressesQuery.data?.verifiedAddresses.find(({ contractAddress }) => contractAddress.toLowerCase() === hash.toLowerCase())) {
......
import { import {
Icon,
useColorModeValue, useColorModeValue,
chakra, chakra,
Button, Button,
...@@ -7,7 +6,7 @@ import { ...@@ -7,7 +6,7 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import infoIcon from 'icons/info.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
isOpen?: boolean; isOpen?: boolean;
...@@ -39,8 +38,8 @@ const AdditionalInfoButton = ({ isOpen, onClick, className, isLoading }: Props, ...@@ -39,8 +38,8 @@ const AdditionalInfoButton = ({ isOpen, onClick, className, isLoading }: Props,
cursor="pointer" cursor="pointer"
flexShrink={ 0 } flexShrink={ 0 }
> >
<Icon <IconSvg
as={ infoIcon } name="info"
boxSize={ 5 } boxSize={ 5 }
color="link" color="link"
_hover={{ color: 'link_hovered' }} _hover={{ color: 'link_hovered' }}
......
import { Box, HStack, Flex, Skeleton, useColorModeValue } from '@chakra-ui/react'; import { Box, HStack, Flex, Skeleton, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import keyIcon from 'icons/key.svg';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
apiKey: string; apiKey: string;
...@@ -14,7 +13,7 @@ interface Props { ...@@ -14,7 +13,7 @@ interface Props {
const ApiKeySnippet = ({ apiKey, name, isLoading }: Props) => { const ApiKeySnippet = ({ apiKey, name, isLoading }: Props) => {
return ( return (
<HStack spacing={ 2 } alignItems="start"> <HStack spacing={ 2 } alignItems="start">
<Icon as={ keyIcon } boxSize={ 6 } color={ useColorModeValue('gray.500', 'gray.400') } isLoading={ isLoading }/> <IconSvg name="key" boxSize={ 6 } color={ useColorModeValue('gray.500', 'gray.400') } isLoading={ isLoading }/>
<Box> <Box>
<Flex alignItems={{ base: 'flex-start', lg: 'center' }}> <Flex alignItems={{ base: 'flex-start', lg: 'center' }}>
<Skeleton isLoaded={ !isLoading } display="inline-block" fontWeight={ 600 } mr={ 1 }> <Skeleton isLoaded={ !isLoading } display="inline-block" fontWeight={ 600 } mr={ 1 }>
......
import { Icon } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import icon404 from 'icons/error-pages/404.svg'; import type { IconName } from 'ui/shared/IconSvg';
import icon422 from 'icons/error-pages/422.svg'; import IconSvg from 'ui/shared/IconSvg';
import icon429 from 'icons/error-pages/429.svg';
import icon500 from 'icons/error-pages/500.svg';
const ICONS: Record<string, React.FunctionComponent<React.SVGAttributes<SVGElement>> > = { const ICONS: Record<string, IconName> = {
'404': icon404, '404': 'error-pages/404',
'422': icon422, '422': 'error-pages/422',
'429': icon429, '429': 'error-pages/429',
'500': icon500, '500': 'error-pages/500',
}; };
interface Props { interface Props {
...@@ -18,7 +15,7 @@ interface Props { ...@@ -18,7 +15,7 @@ interface Props {
} }
const AppErrorIcon = ({ statusCode }: Props) => { const AppErrorIcon = ({ statusCode }: Props) => {
return <Icon as={ ICONS[String(statusCode)] || ICONS['500'] } width="200px" height="auto" color="text"/>; return <IconSvg name={ ICONS[String(statusCode)] || ICONS['500'] } width="200px" height="100px" color="text"/>;
}; };
export default AppErrorIcon; export default AppErrorIcon;
/* eslint-disable max-len */ /* eslint-disable max-len */
import { Box, OrderedList, ListItem, Icon, useColorModeValue, Flex } from '@chakra-ui/react'; import { Box, OrderedList, ListItem, useColorModeValue, Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import txIcon from 'icons/transactions.svg'; import IconSvg from 'ui/shared/IconSvg';
import AppErrorTitle from '../AppErrorTitle'; import AppErrorTitle from '../AppErrorTitle';
...@@ -18,7 +18,7 @@ const AppErrorInvalidTxHash = () => { ...@@ -18,7 +18,7 @@ const AppErrorInvalidTxHash = () => {
<> <>
<Box p={ 4 } borderColor={ snippet.borderColor } borderRadius="md" w="230px" borderWidth="1px"> <Box p={ 4 } borderColor={ snippet.borderColor } borderRadius="md" w="230px" borderWidth="1px">
<Flex alignItems="center" pb={ 4 } borderBottomWidth="1px" borderColor={ snippet.borderColor }> <Flex alignItems="center" pb={ 4 } borderBottomWidth="1px" borderColor={ snippet.borderColor }>
<Icon as={ txIcon } boxSize={ 8 } color={ snippet.iconColor } bgColor={ snippet.iconBg } p={ 1 } borderRadius="md"/> <IconSvg name="transactions" boxSize={ 8 } color={ snippet.iconColor } bgColor={ snippet.iconBg } p={ 1 } borderRadius="md"/>
<Box ml={ 2 }> <Box ml={ 2 }>
<Box w="125px" h="8px" borderRadius="full" bgColor={ snippet.iconBg }/> <Box w="125px" h="8px" borderRadius="full" bgColor={ snippet.iconBg }/>
<Box w="30px" h="8px" borderRadius="full" bgColor={ snippet.borderColor } mt={ 1.5 }/> <Box w="30px" h="8px" borderRadius="full" bgColor={ snippet.borderColor } mt={ 1.5 }/>
......
import { chakra, Icon, IconButton, useColorModeValue } from '@chakra-ui/react'; import { chakra, IconButton, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import errorIcon from 'icons/status/error.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
onClick: (e: React.SyntheticEvent) => void; onClick: (e: React.SyntheticEvent) => void;
...@@ -21,7 +21,7 @@ const ClearButton = ({ onClick, isDisabled, className }: Props) => { ...@@ -21,7 +21,7 @@ const ClearButton = ({ onClick, isDisabled, className }: Props) => {
aria-label="Clear input" aria-label="Clear input"
title="Clear input" title="Clear input"
boxSize={ 6 } boxSize={ 6 }
icon={ <Icon as={ errorIcon } boxSize={ 3 } color={ iconColor } focusable={ false } _hover={{ color: iconColorHover }}/> } icon={ <IconSvg name="status/error" boxSize={ 3 } color={ iconColor } _hover={{ color: iconColorHover }}/> }
size="sm" size="sm"
onClick={ onClick } onClick={ onClick }
/> />
......
import { IconButton, Tooltip, useClipboard, chakra, useDisclosure, Skeleton } from '@chakra-ui/react'; import { IconButton, Tooltip, useClipboard, chakra, useDisclosure, Skeleton } from '@chakra-ui/react';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import CopyIcon from 'icons/copy.svg'; import IconSvg from 'ui/shared/IconSvg';
export interface Props { export interface Props {
text: string; text: string;
...@@ -31,7 +31,7 @@ const CopyToClipboard = ({ text, className, isLoading }: Props) => { ...@@ -31,7 +31,7 @@ const CopyToClipboard = ({ text, className, isLoading }: Props) => {
<Tooltip label={ copied ? 'Copied' : 'Copy to clipboard' } isOpen={ isOpen || copied }> <Tooltip label={ copied ? 'Copied' : 'Copy to clipboard' } isOpen={ isOpen || copied }>
<IconButton <IconButton
aria-label="copy" aria-label="copy"
icon={ <CopyIcon/> } icon={ <IconSvg name="copy" boxSize={ 5 }/> }
w="20px" w="20px"
h="20px" h="20px"
color="gray.400" color="gray.400"
......
import { Box, Heading, Icon, Text } from '@chakra-ui/react'; import { Box, Heading, Text } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import emptyIcon from 'icons/empty_search_result.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
text: string; text: string;
...@@ -14,8 +14,8 @@ const EmptySearchResult = ({ text }: Props) => { ...@@ -14,8 +14,8 @@ const EmptySearchResult = ({ text }: Props) => {
flexDirection="column" flexDirection="column"
alignItems="center" alignItems="center"
> >
<Icon <IconSvg
as={ emptyIcon } name="empty_search_result"
boxSize={ 60 } boxSize={ 60 }
display="block" display="block"
/> />
......
...@@ -2,7 +2,7 @@ import type { TooltipProps } from '@chakra-ui/react'; ...@@ -2,7 +2,7 @@ import type { TooltipProps } from '@chakra-ui/react';
import { chakra, IconButton, Tooltip, useDisclosure, Skeleton } from '@chakra-ui/react'; import { chakra, IconButton, Tooltip, useDisclosure, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import InfoIcon from 'icons/info.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
label: string | React.ReactNode; label: string | React.ReactNode;
...@@ -21,7 +21,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => { ...@@ -21,7 +21,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => {
}, [ onToggle ]); }, [ onToggle ]);
if (isLoading) { if (isLoading) {
return <Skeleton boxSize={ 5 } borderRadius="sm"/>; return <Skeleton className={ className } boxSize={ 5 } borderRadius="sm"/>;
} }
return ( return (
...@@ -35,7 +35,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => { ...@@ -35,7 +35,7 @@ const Hint = ({ label, className, tooltipProps, isLoading }: Props) => {
<IconButton <IconButton
colorScheme="none" colorScheme="none"
aria-label="hint" aria-label="hint"
icon={ <InfoIcon/> } icon={ <IconSvg name="info" w="100%" h="100%"/> }
boxSize={ 5 } boxSize={ 5 }
variant="simple" variant="simple"
display="inline-block" display="inline-block"
......
import type { HTMLChakraProps } from '@chakra-ui/react';
import { Skeleton, chakra } from '@chakra-ui/react';
import { type IconName } from 'public/icons/name';
import React from 'react';
export const href = '/icons/sprite.svg';
export { IconName };
interface Props extends HTMLChakraProps<'div'> {
name: IconName;
isLoading?: boolean;
}
const IconSvg = ({ name, isLoading, ...props }: Props) => {
return (
<Skeleton isLoaded={ !isLoading } display="inline-block" { ...props }>
<chakra.svg w="100%" h="100%">
<use href={ `${ href }#${ name }` }/>
</chakra.svg>
</Skeleton>
);
};
export default IconSvg;
import type { ChakraProps } from '@chakra-ui/react'; import type { ChakraProps } from '@chakra-ui/react';
import { Link, Icon, chakra, Box, Skeleton, useColorModeValue } from '@chakra-ui/react'; import { Link, chakra, Box, Skeleton, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import arrowIcon from 'icons/arrows/north-east.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
href: string; href: string;
...@@ -59,7 +59,7 @@ const LinkExternal = ({ href, children, className, isLoading, variant }: Props) ...@@ -59,7 +59,7 @@ const LinkExternal = ({ href, children, className, isLoading, variant }: Props)
return ( return (
<Link className={ className } { ...styleProps } target="_blank" href={ href }> <Link className={ className } { ...styleProps } target="_blank" href={ href }>
{ children } { children }
<Icon as={ arrowIcon } boxSize={ 4 } verticalAlign="middle" color="gray.400"/> <IconSvg name="arrows/north-east" boxSize={ 4 } verticalAlign="middle" color="gray.400" flexShrink={ 0 }/>
</Link> </Link>
); );
}; };
......
import { Button, Icon } from '@chakra-ui/react'; import { Button } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
...@@ -7,6 +7,7 @@ import * as mixpanel from 'lib/mixpanel/index'; ...@@ -7,6 +7,7 @@ import * as mixpanel from 'lib/mixpanel/index';
import useAddOrSwitchChain from 'lib/web3/useAddOrSwitchChain'; import useAddOrSwitchChain from 'lib/web3/useAddOrSwitchChain';
import useProvider from 'lib/web3/useProvider'; import useProvider from 'lib/web3/useProvider';
import { WALLETS_INFO } from 'lib/web3/wallets'; import { WALLETS_INFO } from 'lib/web3/wallets';
import IconSvg from 'ui/shared/IconSvg';
const feature = config.features.web3Wallet; const feature = config.features.web3Wallet;
...@@ -55,7 +56,7 @@ const NetworkAddToWallet = () => { ...@@ -55,7 +56,7 @@ const NetworkAddToWallet = () => {
return ( return (
<Button variant="outline" size="sm" onClick={ handleClick }> <Button variant="outline" size="sm" onClick={ handleClick }>
<Icon as={ WALLETS_INFO[wallet].icon } boxSize={ 5 } mr={ 2 }/> <IconSvg name={ WALLETS_INFO[wallet].icon } boxSize={ 5 } mr={ 2 }/>
Add { config.chain.name } Add { config.chain.name }
</Button> </Button>
); );
......
import { Flex, Button, Icon, chakra, Popover, PopoverTrigger, PopoverBody, PopoverContent, useDisclosure } from '@chakra-ui/react'; import { Flex, Button, chakra, Popover, PopoverTrigger, PopoverBody, PopoverContent, useDisclosure } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { NetworkExplorer as TNetworkExplorer } from 'types/networks'; import type { NetworkExplorer as TNetworkExplorer } from 'types/networks';
import config from 'configs/app'; import config from 'configs/app';
import arrowIcon from 'icons/arrows/east-mini.svg';
import explorerIcon from 'icons/explorer.svg';
import stripTrailingSlash from 'lib/stripTrailingSlash'; import stripTrailingSlash from 'lib/stripTrailingSlash';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal'; import LinkExternal from 'ui/shared/LinkExternal';
interface Props { interface Props {
...@@ -46,8 +45,8 @@ const NetworkExplorers = ({ className, type, pathParam }: Props) => { ...@@ -46,8 +45,8 @@ const NetworkExplorers = ({ className, type, pathParam }: Props) => {
h="32px" h="32px"
flexShrink={ 0 } flexShrink={ 0 }
> >
<Icon as={ explorerIcon } boxSize={ 5 }/> <IconSvg name="explorer" boxSize={ 5 }/>
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 }/> <IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 }/>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent w="240px"> <PopoverContent w="240px">
......
import { Heading, Flex, Tooltip, Icon, Link, chakra, Skeleton, useDisclosure } from '@chakra-ui/react'; import { Heading, Flex, Tooltip, Link, chakra, Skeleton, useDisclosure } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import _debounce from 'lodash/debounce';
import React from 'react'; import React from 'react';
import eastArrowIcon from 'icons/arrows/east.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import TextAd from 'ui/shared/ad/TextAd'; import TextAd from 'ui/shared/ad/TextAd';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
type BackLinkProp = { label: string; url: string } | { label: string; onClick: () => void }; type BackLinkProp = { label: string; url: string } | { label: string; onClick: () => void };
...@@ -32,7 +32,7 @@ const BackLink = (props: BackLinkProp & { isLoading?: boolean }) => { ...@@ -32,7 +32,7 @@ const BackLink = (props: BackLinkProp & { isLoading?: boolean }) => {
return <Skeleton boxSize={ 6 } display="inline-block" borderRadius="base" mr={ 3 } my={ 2 } verticalAlign="text-bottom" isLoaded={ !props.isLoading }/>; return <Skeleton boxSize={ 6 } display="inline-block" borderRadius="base" mr={ 3 } my={ 2 } verticalAlign="text-bottom" isLoaded={ !props.isLoading }/>;
} }
const icon = <Icon as={ eastArrowIcon } boxSize={ 6 } transform="rotate(180deg)" margin="auto" color="gray.400"/>; const icon = <IconSvg name="arrows/east" boxSize={ 6 } transform="rotate(180deg)" margin="auto" color="gray.400"/>;
if ('url' in props) { if ('url' in props) {
return ( return (
......
import { Icon } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
import iconVerifiedToken from 'icons/verified_token.svg';
import * as addressMock from 'mocks/address/address'; import * as addressMock from 'mocks/address/address';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import EntityTags from 'ui/shared/EntityTags'; import EntityTags from 'ui/shared/EntityTags';
import IconSvg from 'ui/shared/IconSvg';
import NetworkExplorers from 'ui/shared/NetworkExplorers'; import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from '../PageTitle'; import PageTitle from '../PageTitle';
...@@ -33,7 +32,7 @@ const DefaultView = () => { ...@@ -33,7 +32,7 @@ const DefaultView = () => {
const contentAfter = ( const contentAfter = (
<> <>
<Icon as={ iconVerifiedToken } color="green.500" boxSize={ 6 } cursor="pointer"/> <IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer"/>
<EntityTags <EntityTags
tagsBefore={ [ tagsBefore={ [
{ label: 'example', display_name: 'Example label' }, { label: 'example', display_name: 'Example label' },
......
/* eslint-disable max-len */ /* eslint-disable max-len */
import { Icon } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
import iconVerifiedToken from 'icons/verified_token.svg';
import { publicTag, privateTag, watchlistName } from 'mocks/address/tag'; import { publicTag, privateTag, watchlistName } from 'mocks/address/tag';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import EntityTags from 'ui/shared/EntityTags'; import EntityTags from 'ui/shared/EntityTags';
import IconSvg from 'ui/shared/IconSvg';
import NetworkExplorers from 'ui/shared/NetworkExplorers'; import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from '../PageTitle'; import PageTitle from '../PageTitle';
...@@ -28,7 +27,7 @@ const LongNameAndManyTags = () => { ...@@ -28,7 +27,7 @@ const LongNameAndManyTags = () => {
const contentAfter = ( const contentAfter = (
<> <>
<Icon as={ iconVerifiedToken } color="green.500" boxSize={ 6 } cursor="pointer"/> <IconSvg name="verified_token" color="green.500" boxSize={ 6 } cursor="pointer" flexShrink={ 0 }/>
<EntityTags <EntityTags
data={{ data={{
private_tags: [ privateTag ], private_tags: [ privateTag ],
......
import { Box, Icon, IconButton, chakra, Tooltip, Flex, Skeleton } from '@chakra-ui/react'; import { Box, IconButton, chakra, Tooltip, Flex, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import eastArrow from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -36,7 +36,7 @@ const PrevNext = ({ className, onClick, prevLabel, nextLabel, isPrevDisabled, is ...@@ -36,7 +36,7 @@ const PrevNext = ({ className, onClick, prevLabel, nextLabel, isPrevDisabled, is
<Tooltip label={ prevLabel }> <Tooltip label={ prevLabel }>
<IconButton <IconButton
aria-label="prev" aria-label="prev"
icon={ <Icon as={ eastArrow } boxSize={ 6 }/> } icon={ <IconSvg name="arrows/east-mini" boxSize={ 6 }/> }
h={ 6 } h={ 6 }
borderRadius="sm" borderRadius="sm"
variant="subtle" variant="subtle"
...@@ -48,7 +48,7 @@ const PrevNext = ({ className, onClick, prevLabel, nextLabel, isPrevDisabled, is ...@@ -48,7 +48,7 @@ const PrevNext = ({ className, onClick, prevLabel, nextLabel, isPrevDisabled, is
<Tooltip label={ nextLabel }> <Tooltip label={ nextLabel }>
<IconButton <IconButton
aria-label="next" aria-label="next"
icon={ <Icon as={ eastArrow }boxSize={ 6 } transform="rotate(180deg)"/> } icon={ <IconSvg name="arrows/east-mini" boxSize={ 6 } transform="rotate(180deg)"/> }
h={ 6 } h={ 6 }
borderRadius="sm" borderRadius="sm"
variant="subtle" variant="subtle"
......
import { Tooltip, Flex, Icon, useColorModeValue } from '@chakra-ui/react'; import { Tooltip, Flex, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import crossIcon from 'icons/cross.svg'; import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
onClick: () => void; onClick: () => void;
...@@ -14,8 +14,8 @@ const ResetIconButton = ({ onClick }: Props) => { ...@@ -14,8 +14,8 @@ const ResetIconButton = ({ onClick }: Props) => {
return ( return (
<Tooltip label="Reset filter"> <Tooltip label="Reset filter">
<Flex> <Flex>
<Icon <IconSvg
as={ crossIcon } name="cross"
boxSize={ 5 } boxSize={ 5 }
ml={ 1 } ml={ 1 }
color={ resetTokenIconColor } color={ resetTokenIconColor }
......
import { Tooltip, IconButton, HStack, Skeleton } from '@chakra-ui/react'; import { Tooltip, IconButton, HStack, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import DeleteIcon from 'icons/delete.svg';
import EditIcon from 'icons/edit.svg';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing'; import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
onEditClick: () => void; onEditClick: () => void;
...@@ -31,7 +30,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props ...@@ -31,7 +30,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props
variant="simple" variant="simple"
boxSize={ 5 } boxSize={ 5 }
onClick={ onEditClick } onClick={ onEditClick }
icon={ <EditIcon/> } icon={ <IconSvg name="edit" boxSize={ 5 }/> }
onFocusCapture={ onFocusCapture } onFocusCapture={ onFocusCapture }
display="inline-block" display="inline-block"
flexShrink={ 0 } flexShrink={ 0 }
...@@ -44,7 +43,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props ...@@ -44,7 +43,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props
variant="simple" variant="simple"
boxSize={ 5 } boxSize={ 5 }
onClick={ onDeleteClick } onClick={ onDeleteClick }
icon={ <DeleteIcon/> } icon={ <IconSvg name="delete" boxSize={ 5 }/> }
onFocusCapture={ onFocusCapture } onFocusCapture={ onFocusCapture }
display="inline-block" display="inline-block"
flexShrink={ 0 } flexShrink={ 0 }
......
import { chakra, Icon, useColorModeValue } from '@chakra-ui/react'; import { chakra, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import tokenPlaceholderIcon from 'icons/token-placeholder.svg'; import IconSvg from 'ui/shared/IconSvg';
const TokenLogoPlaceholder = ({ className }: { className?: string }) => { const TokenLogoPlaceholder = ({ className }: { className?: string }) => {
const bgColor = useColorModeValue('gray.200', 'gray.600'); const bgColor = useColorModeValue('gray.200', 'gray.600');
const color = useColorModeValue('gray.400', 'gray.200'); const color = useColorModeValue('gray.400', 'gray.200');
return ( return (
<Icon <IconSvg
className={ className } className={ className }
fontWeight={ 600 } fontWeight={ 600 }
bgColor={ bgColor } bgColor={ bgColor }
color={ color } color={ color }
borderRadius="base" borderRadius="base"
as={ tokenPlaceholderIcon } name="token-placeholder"
transitionProperty="background-color,color" transitionProperty="background-color,color"
transitionDuration="normal" transitionDuration="normal"
transitionTimingFunction="ease" transitionTimingFunction="ease"
......
...@@ -3,15 +3,14 @@ import React from 'react'; ...@@ -3,15 +3,14 @@ import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer'; import type { TokenTransfer } from 'types/api/tokenTransfer';
import eastArrowIcon from 'icons/arrows/east.svg';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import NftEntity from 'ui/shared/entities/nft/NftEntity'; import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import { getTokenTransferTypeText } from 'ui/shared/TokenTransfer/helpers'; import { getTokenTransferTypeText } from 'ui/shared/TokenTransfer/helpers';
...@@ -100,7 +99,7 @@ const TokenTransferListItem = ({ ...@@ -100,7 +99,7 @@ const TokenTransferListItem = ({
flexShrink={ 0 } flexShrink={ 0 }
/> />
) : ) :
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading } flexShrink={ 0 }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading } flexShrink={ 0 }/>
} }
<AddressEntity <AddressEntity
address={ to } address={ to }
......
import { SkeletonCircle, Image, Icon } from '@chakra-ui/react'; import { SkeletonCircle, Image } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import profileIcon from 'icons/profile.svg';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo'; import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
size: number; size: number;
...@@ -34,7 +34,7 @@ const UserAvatar = ({ size }: Props) => { ...@@ -34,7 +34,7 @@ const UserAvatar = ({ size }: Props) => {
boxSize={ `${ size }px` } boxSize={ `${ size }px` }
borderRadius="full" borderRadius="full"
overflow="hidden" overflow="hidden"
fallback={ isImageLoadError || !data?.avatar ? <Icon as={ profileIcon } boxSize={ 5 }/> : undefined } fallback={ isImageLoadError || !data?.avatar ? <IconSvg name="profile" boxSize={ 5 }/> : undefined }
onError={ handleImageLoadError } onError={ handleImageLoadError }
/> />
); );
......
import { Box, chakra, Icon, IconButton, Skeleton, Tooltip } from '@chakra-ui/react'; import { Box, chakra, IconButton, Skeleton, Tooltip } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
...@@ -9,6 +9,7 @@ import * as mixpanel from 'lib/mixpanel/index'; ...@@ -9,6 +9,7 @@ import * as mixpanel from 'lib/mixpanel/index';
import useAddOrSwitchChain from 'lib/web3/useAddOrSwitchChain'; import useAddOrSwitchChain from 'lib/web3/useAddOrSwitchChain';
import useProvider from 'lib/web3/useProvider'; import useProvider from 'lib/web3/useProvider';
import { WALLETS_INFO } from 'lib/web3/wallets'; import { WALLETS_INFO } from 'lib/web3/wallets';
import IconSvg from 'ui/shared/IconSvg';
const feature = config.features.web3Wallet; const feature = config.features.web3Wallet;
...@@ -97,7 +98,7 @@ const AddressAddToWallet = ({ className, token, isLoading, variant = 'icon', ico ...@@ -97,7 +98,7 @@ const AddressAddToWallet = ({ className, token, isLoading, variant = 'icon', ico
size="sm" size="sm"
px="6px" px="6px"
onClick={ handleClick } onClick={ handleClick }
icon={ <Icon as={ WALLETS_INFO[wallet].icon } boxSize={ 6 }/> } icon={ <IconSvg name={ WALLETS_INFO[wallet].icon } boxSize={ 6 }/> }
flexShrink={ 0 } flexShrink={ 0 }
/> />
</Tooltip> </Tooltip>
...@@ -106,8 +107,8 @@ const AddressAddToWallet = ({ className, token, isLoading, variant = 'icon', ico ...@@ -106,8 +107,8 @@ const AddressAddToWallet = ({ className, token, isLoading, variant = 'icon', ico
return ( return (
<Tooltip label={ `Add token to ${ WALLETS_INFO[wallet].name }` }> <Tooltip label={ `Add token to ${ WALLETS_INFO[wallet].name }` }>
<Box className={ className } display="inline-flex" cursor="pointer" onClick={ handleClick } flexShrink={ 0 }> <Box className={ className } display="inline-flex" cursor="pointer" onClick={ handleClick } flexShrink={ 0 } aria-label="Add token to wallet">
<Icon as={ WALLETS_INFO[wallet].icon } boxSize={ iconSize }/> <IconSvg name={ WALLETS_INFO[wallet].icon } boxSize={ iconSize }/>
</Box> </Box>
</Tooltip> </Tooltip>
); );
......
import { Skeleton, Icon as ChakraIcon } from '@chakra-ui/react';
import type { IconProps, As } from '@chakra-ui/react';
import React from 'react';
interface Props extends IconProps {
isLoading?: boolean;
as: As;
}
const Icon = ({ isLoading, ...props }: Props, ref: React.LegacyRef<SVGSVGElement>) => {
return (
<Skeleton isLoaded={ !isLoading } boxSize={ props.boxSize } w={ props.w } h={ props.h } borderRadius={ props.borderRadius }>
<ChakraIcon { ...props } ref={ ref }/>
</Skeleton>
);
};
export default React.memo(React.forwardRef(Icon));
...@@ -3,7 +3,6 @@ import { ...@@ -3,7 +3,6 @@ import {
Center, Center,
chakra, chakra,
Flex, Flex,
Icon,
IconButton, Link, IconButton, Link,
Menu, Menu,
MenuButton, MenuButton,
...@@ -20,14 +19,10 @@ import React, { useRef, useCallback, useState } from 'react'; ...@@ -20,14 +19,10 @@ import React, { useRef, useCallback, useState } from 'react';
import type { TimeChartItem } from './types'; import type { TimeChartItem } from './types';
import svgFileIcon from 'icons/files/csv.svg';
import imageIcon from 'icons/files/image.svg';
import repeatArrowIcon from 'icons/repeat_arrow.svg';
import scopeIcon from 'icons/scope.svg';
import dotsIcon from 'icons/vertical_dots.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import { apos } from 'lib/html-entities'; import { apos } from 'lib/html-entities';
import saveAsCSV from 'lib/saveAsCSV'; import saveAsCSV from 'lib/saveAsCSV';
import IconSvg from 'ui/shared/IconSvg';
import ChartWidgetGraph from './ChartWidgetGraph'; import ChartWidgetGraph from './ChartWidgetGraph';
import FullscreenChartModal from './FullscreenChartModal'; import FullscreenChartModal from './FullscreenChartModal';
...@@ -202,7 +197,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError, ...@@ -202,7 +197,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError,
size="sm" size="sm"
variant="outline" variant="outline"
onClick={ handleZoomResetClick } onClick={ handleZoomResetClick }
icon={ <Icon as={ repeatArrowIcon } w={ 4 } h={ 4 }/> } icon={ <IconSvg name="repeat_arrow" w={ 4 } h={ 4 }/> }
/> />
</Tooltip> </Tooltip>
...@@ -212,7 +207,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError, ...@@ -212,7 +207,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError,
<MenuButton <MenuButton
w="36px" w="36px"
h="32px" h="32px"
icon={ <Icon as={ dotsIcon } w={ 4 } h={ 4 }/> } icon={ <IconSvg name="vertical_dots" w={ 4 } h={ 4 }/> }
colorScheme="gray" colorScheme="gray"
variant="ghost" variant="ghost"
as={ IconButton } as={ IconButton }
...@@ -228,7 +223,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError, ...@@ -228,7 +223,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError,
alignItems="center" alignItems="center"
onClick={ showChartFullscreen } onClick={ showChartFullscreen }
> >
<Icon as={ scopeIcon } boxSize={ 5 } mr={ 3 }/> <IconSvg name="scope" boxSize={ 5 } mr={ 3 }/>
View fullscreen View fullscreen
</MenuItem> </MenuItem>
...@@ -237,7 +232,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError, ...@@ -237,7 +232,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError,
alignItems="center" alignItems="center"
onClick={ handleFileSaveClick } onClick={ handleFileSaveClick }
> >
<Icon as={ imageIcon } boxSize={ 5 } mr={ 3 }/> <IconSvg name="files/image" boxSize={ 5 } mr={ 3 }/>
Save as PNG Save as PNG
</MenuItem> </MenuItem>
...@@ -246,7 +241,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError, ...@@ -246,7 +241,7 @@ const ChartWidget = ({ items, title, description, isLoading, className, isError,
alignItems="center" alignItems="center"
onClick={ handleSVGSavingClick } onClick={ handleSVGSavingClick }
> >
<Icon as={ svgFileIcon } boxSize={ 5 } mr={ 3 }/> <IconSvg name="files/csv" boxSize={ 5 } mr={ 3 }/>
Save as CSV Save as CSV
</MenuItem> </MenuItem>
</MenuList> </MenuList>
......
import { Box, Button, Grid, Heading, Icon, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay, Text } from '@chakra-ui/react'; import { Box, Button, Grid, Heading, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay, Text } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { TimeChartItem } from './types'; import type { TimeChartItem } from './types';
import repeatArrow from 'icons/repeat_arrow.svg'; import IconSvg from 'ui/shared/IconSvg';
import ChartWidgetGraph from './ChartWidgetGraph'; import ChartWidgetGraph from './ChartWidgetGraph';
...@@ -71,7 +71,7 @@ const FullscreenChartModal = ({ ...@@ -71,7 +71,7 @@ const FullscreenChartModal = ({
{ !isZoomResetInitial && ( { !isZoomResetInitial && (
<Button <Button
leftIcon={ <Icon as={ repeatArrow } w={ 4 } h={ 4 }/> } leftIcon={ <IconSvg name="repeat_arrow" w={ 4 } h={ 4 }/> }
colorScheme="blue" colorScheme="blue"
gridColumn={ 2 } gridColumn={ 2 }
justifySelf="end" justifySelf="end"
......
...@@ -7,9 +7,6 @@ import type { AddressParam } from 'types/api/addressParams'; ...@@ -7,9 +7,6 @@ import type { AddressParam } from 'types/api/addressParams';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import iconSafe from 'icons/brands/safe.svg';
import iconContractVerified from 'icons/contract_verified.svg';
import iconContract from 'icons/contract.svg';
import { useAddressHighlightContext } from 'lib/contexts/addressHighlight'; import { useAddressHighlightContext } from 'lib/contexts/addressHighlight';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
...@@ -54,7 +51,7 @@ const Icon = (props: IconProps) => { ...@@ -54,7 +51,7 @@ const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
asProp={ iconSafe } name="brands/safe"
/> />
); );
} }
...@@ -65,7 +62,7 @@ const Icon = (props: IconProps) => { ...@@ -65,7 +62,7 @@ const Icon = (props: IconProps) => {
<span> <span>
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
asProp={ iconContractVerified } name="contract_verified"
color="green.500" color="green.500"
borderRadius={ 0 } borderRadius={ 0 }
/> />
...@@ -79,7 +76,7 @@ const Icon = (props: IconProps) => { ...@@ -79,7 +76,7 @@ const Icon = (props: IconProps) => {
<span> <span>
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
asProp={ iconContract } name="contract"
borderRadius={ 0 } borderRadius={ 0 }
/> />
</span> </span>
......
import { Box, chakra, Flex, Skeleton, useColorModeValue } from '@chakra-ui/react'; import { chakra, Flex, Skeleton, useColorModeValue } from '@chakra-ui/react';
import type { As, IconProps } from '@chakra-ui/react'; import type { As, IconProps } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import IconBase from 'ui/shared/chakra/Icon';
import type { Props as CopyToClipboardProps } from 'ui/shared/CopyToClipboard'; import type { Props as CopyToClipboardProps } from 'ui/shared/CopyToClipboard';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import HashStringShorten from 'ui/shared/HashStringShorten'; import HashStringShorten from 'ui/shared/HashStringShorten';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal'; import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
...@@ -79,12 +80,12 @@ const Link = chakra(({ isLoading, children, isExternal, onClick, href, noLink }: ...@@ -79,12 +80,12 @@ const Link = chakra(({ isLoading, children, isExternal, onClick, href, noLink }:
}); });
export interface IconBaseProps extends Pick<EntityBaseProps, 'isLoading' | 'iconSize' | 'noIcon'> { export interface IconBaseProps extends Pick<EntityBaseProps, 'isLoading' | 'iconSize' | 'noIcon'> {
asProp: As; name: IconName;
color?: IconProps['color']; color?: IconProps['color'];
borderRadius?: IconProps['borderRadius']; borderRadius?: IconProps['borderRadius'];
} }
const Icon = ({ isLoading, iconSize, noIcon, asProp, color, borderRadius }: IconBaseProps) => { const Icon = ({ isLoading, iconSize, noIcon, name, color, borderRadius }: IconBaseProps) => {
const defaultColor = useColorModeValue('gray.500', 'gray.400'); const defaultColor = useColorModeValue('gray.500', 'gray.400');
if (noIcon) { if (noIcon) {
...@@ -93,14 +94,17 @@ const Icon = ({ isLoading, iconSize, noIcon, asProp, color, borderRadius }: Icon ...@@ -93,14 +94,17 @@ const Icon = ({ isLoading, iconSize, noIcon, asProp, color, borderRadius }: Icon
const styles = getIconProps(iconSize); const styles = getIconProps(iconSize);
return ( return (
<Box mr={ 2 } color={ color ?? defaultColor }> <IconSvg
<IconBase name={ name }
as={ asProp }
boxSize={ styles.boxSize } boxSize={ styles.boxSize }
isLoading={ isLoading } isLoading={ isLoading }
borderRadius={ borderRadius ?? 'base' } borderRadius={ borderRadius ?? 'base' }
display="block"
mr={ 2 }
color={ color ?? defaultColor }
minW={ 0 }
flexShrink={ 0 }
/> />
</Box>
); );
}; };
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit'; import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import blockIcon from 'icons/block_slim.svg';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash' | 'number'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash' | 'number'>;
...@@ -24,15 +22,15 @@ const Link = chakra((props: LinkProps) => { ...@@ -24,15 +22,15 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'asProp'> & { type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & {
asProp?: As; name?: EntityBase.IconBaseProps['name'];
}; };
const Icon = (props: IconProps) => { const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
asProp={ props.asProp ?? blockIcon } name={ props.name ?? 'block_slim' }
/> />
); );
}; };
......
...@@ -3,7 +3,6 @@ import _omit from 'lodash/omit'; ...@@ -3,7 +3,6 @@ import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import txBatchIcon from 'icons/txn_batches_slim.svg';
import * as BlockEntity from './BlockEntity'; import * as BlockEntity from './BlockEntity';
...@@ -19,7 +18,7 @@ const BlockEntityL2 = (props: BlockEntity.EntityProps) => { ...@@ -19,7 +18,7 @@ const BlockEntityL2 = (props: BlockEntity.EntityProps) => {
return ( return (
<BlockEntity.Container className={ props.className }> <BlockEntity.Container className={ props.className }>
<BlockEntity.Icon { ...partsProps } asProp={ txBatchIcon }/> <BlockEntity.Icon { ...partsProps } name="txn_batches_slim"/>
<BlockEntity.Link { ...linkProps }> <BlockEntity.Link { ...linkProps }>
<BlockEntity.Content { ...partsProps }/> <BlockEntity.Content { ...partsProps }/>
</BlockEntity.Link> </BlockEntity.Link>
......
...@@ -5,7 +5,6 @@ import React from 'react'; ...@@ -5,7 +5,6 @@ import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import txBatchIcon from 'icons/txn_batches_slim.svg';
import * as BlockEntity from './BlockEntity'; import * as BlockEntity from './BlockEntity';
...@@ -21,7 +20,7 @@ const ZkEvmBatchEntityL2 = (props: BlockEntity.EntityProps) => { ...@@ -21,7 +20,7 @@ const ZkEvmBatchEntityL2 = (props: BlockEntity.EntityProps) => {
return ( return (
<BlockEntity.Container className={ props.className }> <BlockEntity.Container className={ props.className }>
<BlockEntity.Icon { ...partsProps } asProp={ txBatchIcon }/> <BlockEntity.Icon { ...partsProps } name="txn_batches_slim"/>
<BlockEntity.Link <BlockEntity.Link
{ ...linkProps } { ...linkProps }
href={ route({ pathname: '/zkevm-l2-txn-batch/[number]', query: { number: props.number.toString() } }) } href={ route({ pathname: '/zkevm-l2-txn-batch/[number]', query: { number: props.number.toString() } }) }
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit'; import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import nftPlaceholder from 'icons/nft_shield.svg';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
const Container = EntityBase.Container; const Container = EntityBase.Container;
type IconProps = Pick<EntityProps, 'isLoading' | 'noIcon' | 'iconSize'> & { type IconProps = Pick<EntityProps, 'isLoading' | 'noIcon' | 'iconSize'> & {
asProp?: As; name?: EntityBase.IconBaseProps['name'];
}; };
const Icon = (props: IconProps) => { const Icon = (props: IconProps) => {
...@@ -24,7 +22,7 @@ const Icon = (props: IconProps) => { ...@@ -24,7 +22,7 @@ const Icon = (props: IconProps) => {
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
iconSize={ props.iconSize ?? 'lg' } iconSize={ props.iconSize ?? 'lg' }
asProp={ props.asProp ?? nftPlaceholder } name={ props.name ?? 'nft_shield' }
/> />
); );
}; };
......
import type { As, ChakraProps } from '@chakra-ui/react'; import type { ChakraProps } from '@chakra-ui/react';
import { Image, Skeleton, chakra } from '@chakra-ui/react'; import { Image, Skeleton, chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit'; import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
...@@ -29,7 +29,6 @@ const Link = chakra((props: LinkProps) => { ...@@ -29,7 +29,6 @@ const Link = chakra((props: LinkProps) => {
}); });
type IconProps = Pick<EntityProps, 'token' | 'isLoading' | 'iconSize' | 'noIcon' | 'className'> & { type IconProps = Pick<EntityProps, 'token' | 'isLoading' | 'iconSize' | 'noIcon' | 'className'> & {
asProp?: As;
marginRight?: ChakraProps['marginRight']; marginRight?: ChakraProps['marginRight'];
boxSize?: ChakraProps['boxSize']; boxSize?: ChakraProps['boxSize'];
}; };
...@@ -43,10 +42,11 @@ const Icon = (props: IconProps) => { ...@@ -43,10 +42,11 @@ const Icon = (props: IconProps) => {
marginRight: props.marginRight ?? 2, marginRight: props.marginRight ?? 2,
boxSize: props.boxSize ?? getIconProps(props.iconSize).boxSize, boxSize: props.boxSize ?? getIconProps(props.iconSize).boxSize,
borderRadius: 'base', borderRadius: 'base',
flexShrink: 0,
}; };
if (props.isLoading) { if (props.isLoading) {
return <Skeleton { ...styles } className={ props.className } flexShrink={ 0 }/>; return <Skeleton { ...styles } className={ props.className }/>;
} }
return ( return (
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit'; import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import transactionIcon from 'icons/transactions_slim.svg';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>;
...@@ -23,15 +21,15 @@ const Link = chakra((props: LinkProps) => { ...@@ -23,15 +21,15 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'asProp'> & { type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & {
asProp?: As; name?: EntityBase.IconBaseProps['name'];
}; };
const Icon = (props: IconProps) => { const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
asProp={ props.asProp ?? transactionIcon } name={ props.name ?? 'transactions_slim' }
/> />
); );
}; };
......
import type { As } from '@chakra-ui/react'; import type { As } from '@chakra-ui/react';
import { Skeleton, Box, Button, Circle, Icon, useColorModeValue } from '@chakra-ui/react'; import { Skeleton, Box, Button, Circle, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import filterIcon from 'icons/filter.svg'; import IconSvg from 'ui/shared/IconSvg';
const FilterIcon = <Icon as={ filterIcon } boxSize={ 5 } mr={{ base: 0, lg: 2 }}/>; const FilterIcon = <IconSvg name="filter" boxSize={ 5 } mr={{ base: 0, lg: 2 }}/>;
interface Props { interface Props {
isActive?: boolean; isActive?: boolean;
......
import { chakra, Icon, Input, InputGroup, InputLeftElement, InputRightElement, Skeleton, useColorModeValue } from '@chakra-ui/react'; import { chakra, Input, InputGroup, InputLeftElement, InputRightElement, Skeleton, useColorModeValue } from '@chakra-ui/react';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import searchIcon from 'icons/search.svg';
import ClearButton from 'ui/shared/ClearButton'; import ClearButton from 'ui/shared/ClearButton';
import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
onChange: (searchTerm: string) => void; onChange: (searchTerm: string) => void;
...@@ -44,7 +44,7 @@ const FilterInput = ({ onChange, className, size = 'sm', placeholder, initialVal ...@@ -44,7 +44,7 @@ const FilterInput = ({ onChange, className, size = 'sm', placeholder, initialVal
<InputLeftElement <InputLeftElement
pointerEvents="none" pointerEvents="none"
> >
<Icon as={ searchIcon } color={ iconColor }/> <IconSvg name="search" color={ iconColor } boxSize={ 4 }/>
</InputLeftElement> </InputLeftElement>
<Input <Input
......
import { Box, Flex, Icon, Text, useColorModeValue, IconButton, chakra, Tooltip } from '@chakra-ui/react'; import { Box, Flex, Text, useColorModeValue, IconButton, chakra, Tooltip } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import CrossIcon from 'icons/cross.svg'; import type { IconName } from 'ui/shared/IconSvg';
import jsonIcon from 'icons/files/json.svg'; import IconSvg from 'ui/shared/IconSvg';
import placeholderIcon from 'icons/files/placeholder.svg';
import solIcon from 'icons/files/sol.svg';
import yulIcon from 'icons/files/yul.svg';
import infoIcon from 'icons/info.svg';
const FILE_ICONS: Record<string, React.FunctionComponent<React.SVGAttributes<SVGElement>>> = { const FILE_ICONS: Record<string, IconName> = {
'.json': jsonIcon, '.json': 'files/json',
'.sol': solIcon, '.sol': 'files/sol',
'.yul': yulIcon, '.yul': 'files/yul',
}; };
function getFileExtension(fileName: string) { function getFileExtension(fileName: string) {
...@@ -44,7 +40,7 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr ...@@ -44,7 +40,7 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
}, []); }, []);
const fileExtension = getFileExtension(file.name); const fileExtension = getFileExtension(file.name);
const fileIcon = FILE_ICONS[fileExtension] || placeholderIcon; const fileIcon = FILE_ICONS[fileExtension] || 'files/placeholder';
const iconColor = useColorModeValue('gray.600', 'gray.400'); const iconColor = useColorModeValue('gray.600', 'gray.400');
return ( return (
...@@ -55,8 +51,8 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr ...@@ -55,8 +51,8 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
alignItems="center" alignItems="center"
textAlign="left" textAlign="left"
> >
<Icon <IconSvg
as={ fileIcon } name={ fileIcon }
boxSize="74px" boxSize="74px"
color={ error ? 'error' : iconColor } color={ error ? 'error' : iconColor }
mr={ 2 } mr={ 2 }
...@@ -83,13 +79,13 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr ...@@ -83,13 +79,13 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
maxW="320px" maxW="320px"
> >
<Box cursor="pointer" display="inherit" onClick={ handleErrorHintIconClick } ml={ 1 }> <Box cursor="pointer" display="inherit" onClick={ handleErrorHintIconClick } ml={ 1 }>
<Icon as={ infoIcon } boxSize={ 5 } color="error"/> <IconSvg name="info" boxSize={ 5 } color="error"/>
</Box> </Box>
</Tooltip> </Tooltip>
) } ) }
<IconButton <IconButton
aria-label="remove" aria-label="remove"
icon={ <CrossIcon/> } icon={ <IconSvg name="cross" boxSize={ 6 }/> }
boxSize={ 6 } boxSize={ 6 }
variant="simple" variant="simple"
display="inline-block" display="inline-block"
......
import { Icon, chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconFile from './icons/file.svg'; import type { IconName } from 'ui/shared/IconSvg';
import iconSolidity from './icons/solidity.svg'; import IconSvg from 'ui/shared/IconSvg';
import iconVyper from './icons/vyper.svg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -11,19 +10,19 @@ interface Props { ...@@ -11,19 +10,19 @@ interface Props {
} }
const CodeEditorFileIcon = ({ className, fileName }: Props) => { const CodeEditorFileIcon = ({ className, fileName }: Props) => {
const as = (() => { const name: IconName = (() => {
if (/.vy$/.test(fileName)) { if (/.vy$/.test(fileName)) {
return iconVyper; return 'monaco/vyper';
} }
if (/.sol|.yul$/.test(fileName)) { if (/.sol|.yul$/.test(fileName)) {
return iconSolidity; return 'monaco/solidity';
} }
return iconFile; return 'monaco/file';
})(); })();
return <Icon className={ className } as={ as } boxSize="16px"/>; return <IconSvg className={ className } name={ name } boxSize="16px"/>;
}; };
export default React.memo(chakra(CodeEditorFileIcon)); export default React.memo(chakra(CodeEditorFileIcon));
import type { ChakraProps } from '@chakra-ui/react'; import type { ChakraProps } from '@chakra-ui/react';
import { Box, Accordion, AccordionButton, AccordionItem, AccordionPanel, Icon, chakra } from '@chakra-ui/react'; import { Box, Accordion, AccordionButton, AccordionItem, AccordionPanel, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FileTree } from './types'; import type { FileTree } from './types';
import IconSvg from 'ui/shared/IconSvg';
import CodeEditorFileIcon from './CodeEditorFileIcon'; import CodeEditorFileIcon from './CodeEditorFileIcon';
import CodeEditorMainFileIndicator from './CodeEditorMainFileIndicator'; import CodeEditorMainFileIndicator from './CodeEditorMainFileIndicator';
import iconFolderOpen from './icons/folder-open.svg';
import iconFolder from './icons/folder.svg';
import useThemeColors from './utils/useThemeColors'; import useThemeColors from './utils/useThemeColors';
interface Props { interface Props {
...@@ -57,7 +57,7 @@ const CodeEditorFileTree = ({ tree, level = 0, onItemClick, isCollapsed, selecte ...@@ -57,7 +57,7 @@ const CodeEditorFileTree = ({ tree, level = 0, onItemClick, isCollapsed, selecte
boxSize="16px" boxSize="16px"
mr="2px" mr="2px"
/> />
<Icon as={ isExpanded ? iconFolderOpen : iconFolder } boxSize="16px" mr="4px"/> <IconSvg name={ isExpanded ? 'monaco/folder-open' : 'monaco/folder' } boxSize="16px" mr="4px"/>
{ leafName } { leafName }
</AccordionButton> </AccordionButton>
<AccordionPanel p="0"> <AccordionPanel p="0">
......
import { Box, chakra, Icon, Tooltip } from '@chakra-ui/react'; import { Box, chakra, Tooltip } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconStar from 'icons/star_filled.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
className?: string; className?: string;
...@@ -11,7 +11,7 @@ const CodeEditorMainFileIndicator = ({ className }: Props) => { ...@@ -11,7 +11,7 @@ const CodeEditorMainFileIndicator = ({ className }: Props) => {
return ( return (
<Tooltip label="The main file containing verified contract"> <Tooltip label="The main file containing verified contract">
<Box className={ className } > <Box className={ className } >
<Icon as={ iconStar } boxSize={ 3 } display="block" color="green.500"/> <IconSvg name="star_filled" boxSize={ 3 } display="block" color="green.500"/>
</Box> </Box>
</Tooltip> </Tooltip>
); );
......
import { Icon, useColorModeValue, chakra } from '@chakra-ui/react'; import { useColorModeValue, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import nftIcon from 'icons/nft_shield.svg'; import IconSvg from 'ui/shared/IconSvg';
const NftFallback = ({ className }: {className?: string}) => { const NftFallback = ({ className }: {className?: string}) => {
return ( return (
<Icon <IconSvg
className={ className } className={ className }
as={ nftIcon } name="nft_shield"
p="50px" p="50px"
color={ useColorModeValue('blackAlpha.500', 'whiteAlpha.500') } color={ useColorModeValue('blackAlpha.500', 'whiteAlpha.500') }
bgColor={ useColorModeValue('blackAlpha.50', 'whiteAlpha.50') } bgColor={ useColorModeValue('blackAlpha.50', 'whiteAlpha.50') }
......
import { Button, Skeleton, Flex, Icon, IconButton, chakra } from '@chakra-ui/react'; import { Button, Skeleton, Flex, IconButton, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { PaginationParams } from './types'; import type { PaginationParams } from './types';
import arrowIcon from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props extends PaginationParams { interface Props extends PaginationParams {
className?: string; className?: string;
...@@ -40,7 +40,7 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasPage ...@@ -40,7 +40,7 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasPage
size="sm" size="sm"
aria-label="Prev page" aria-label="Prev page"
w="36px" w="36px"
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 }/> } icon={ <IconSvg name="arrows/east-mini" w={ 5 } h={ 5 }/> }
isDisabled={ !canGoBackwards || isLoading } isDisabled={ !canGoBackwards || isLoading }
/> />
</Skeleton> </Skeleton>
...@@ -65,7 +65,7 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasPage ...@@ -65,7 +65,7 @@ const Pagination = ({ page, onNextPageClick, onPrevPageClick, resetPage, hasPage
size="sm" size="sm"
aria-label="Next page" aria-label="Next page"
w="36px" w="36px"
icon={ <Icon as={ arrowIcon } w={ 5 } h={ 5 } transform="rotate(180deg)"/> } icon={ <IconSvg name="arrows/east-mini" w={ 5 } h={ 5 } transform="rotate(180deg)"/> }
isDisabled={ !hasNextPage || isLoading } isDisabled={ !hasNextPage || isLoading }
/> />
</Skeleton> </Skeleton>
......
import { ButtonGroup, Button, Flex, Icon, useRadio, useRadioGroup, useColorModeValue } from '@chakra-ui/react'; import { ButtonGroup, Button, Flex, useRadio, useRadioGroup, useColorModeValue } from '@chakra-ui/react';
import type { UseRadioProps } from '@chakra-ui/react'; import type { UseRadioProps } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
type RadioItemProps = { type RadioItemProps = {
title: string; title: string;
icon?: React.FC<React.SVGAttributes<SVGElement>>; icon?: IconName;
onlyIcon: false | undefined; onlyIcon: false | undefined;
} | { } | {
title: string; title: string;
icon: React.FC<React.SVGAttributes<SVGElement>>; icon: IconName;
onlyIcon: true; onlyIcon: true;
} }
...@@ -50,7 +53,7 @@ const RadioButton = (props: RadioButtonProps) => { ...@@ -50,7 +53,7 @@ const RadioButton = (props: RadioButtonProps) => {
<Flex <Flex
{ ...checkbox } { ...checkbox }
> >
<Icon as={ props.icon } boxSize={ 5 }/> <IconSvg name={ props.icon } boxSize={ 5 }/>
</Flex> </Flex>
</Button> </Button>
); );
...@@ -59,7 +62,7 @@ const RadioButton = (props: RadioButtonProps) => { ...@@ -59,7 +62,7 @@ const RadioButton = (props: RadioButtonProps) => {
return ( return (
<Button <Button
as="label" as="label"
leftIcon={ props.icon ? <Icon as={ props.icon } boxSize={ 5 } mr={ -1 }/> : undefined } leftIcon={ props.icon ? <IconSvg name={ props.icon } boxSize={ 5 } mr={ -1 }/> : undefined }
{ ...styleProps } { ...styleProps }
> >
<input { ...input }/> <input { ...input }/>
......
...@@ -2,15 +2,6 @@ import React from 'react'; ...@@ -2,15 +2,6 @@ import React from 'react';
import RadioButtonGroup from '../RadioButtonGroup'; import RadioButtonGroup from '../RadioButtonGroup';
const TestIcon = ({ className }: {className?: string}) => {
return (
<svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg" className={ className }>
{ /* eslint-disable-next-line max-len */ }
<path fillRule="evenodd" clipRule="evenodd" d="M3.5 11a7.5 7.5 0 1 1 15 0 7.5 7.5 0 0 1-15 0ZM11 1C5.477 1 1 5.477 1 11s4.477 10 10 10 10-4.477 10-10S16.523 1 11 1Zm1.25 5a1.25 1.25 0 1 0-2.5 0v5c0 .69.56 1.25 1.25 1.25h5a1.25 1.25 0 1 0 0-2.5h-3.75V6Z" fill="currentColor" stroke="transparent" strokeWidth=".6" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
);
};
type Test = 'v1' | 'v2' | 'v3'; type Test = 'v1' | 'v2' | 'v3';
const RadioButtonGroupTest = () => { const RadioButtonGroupTest = () => {
...@@ -21,9 +12,9 @@ const RadioButtonGroupTest = () => { ...@@ -21,9 +12,9 @@ const RadioButtonGroupTest = () => {
defaultValue="v1" defaultValue="v1"
name="test" name="test"
options={ [ options={ [
{ value: 'v1', title: 'test option 1', icon: TestIcon, onlyIcon: false }, { value: 'v1', title: 'test option 1', icon: 'clock', onlyIcon: false },
{ value: 'v2', title: 'test 2', onlyIcon: false }, { value: 'v2', title: 'test 2', onlyIcon: false },
{ value: 'v2', title: 'test 2', icon: TestIcon, onlyIcon: true }, { value: 'v2', title: 'test 2', icon: 'clock', onlyIcon: true },
] } ] }
/> />
); );
......
import { Icon, IconButton, chakra, Skeleton } from '@chakra-ui/react'; import { IconButton, chakra, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import upDownArrow from 'icons/arrows/up-down.svg'; import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
onClick: () => void; onClick: () => void;
...@@ -17,7 +17,7 @@ const SortButton = ({ onClick, isActive, className, isLoading }: Props) => { ...@@ -17,7 +17,7 @@ const SortButton = ({ onClick, isActive, className, isLoading }: Props) => {
return ( return (
<IconButton <IconButton
icon={ <Icon as={ upDownArrow } boxSize={ 5 }/> } icon={ <IconSvg name="arrows/up-down" boxSize={ 5 }/> }
aria-label="sort" aria-label="sort"
size="sm" size="sm"
variant="outline" variant="outline"
......
import { TagLabel, TagLeftIcon, Tooltip } from '@chakra-ui/react'; import { TagLabel, Tooltip } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import errorIcon from 'icons/status/error.svg';
import pendingIcon from 'icons/status/pending.svg';
import successIcon from 'icons/status/success.svg';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
export type StatusTagType = 'ok' | 'error' | 'pending'; export type StatusTagType = 'ok' | 'error' | 'pending';
...@@ -16,20 +15,20 @@ export interface Props { ...@@ -16,20 +15,20 @@ export interface Props {
} }
const StatusTag = ({ type, text, errorText, isLoading }: Props) => { const StatusTag = ({ type, text, errorText, isLoading }: Props) => {
let icon; let icon: IconName;
let colorScheme; let colorScheme;
switch (type) { switch (type) {
case 'ok': case 'ok':
icon = successIcon; icon = 'status/success';
colorScheme = 'green'; colorScheme = 'green';
break; break;
case 'error': case 'error':
icon = errorIcon; icon = 'status/error';
colorScheme = 'red'; colorScheme = 'red';
break; break;
case 'pending': case 'pending':
icon = pendingIcon; icon = 'status/pending';
// FIXME: it's not gray on mockups // FIXME: it's not gray on mockups
// need to implement new color scheme or redefine colors here // need to implement new color scheme or redefine colors here
colorScheme = 'gray'; colorScheme = 'gray';
...@@ -39,7 +38,7 @@ const StatusTag = ({ type, text, errorText, isLoading }: Props) => { ...@@ -39,7 +38,7 @@ const StatusTag = ({ type, text, errorText, isLoading }: Props) => {
return ( return (
<Tooltip label={ errorText }> <Tooltip label={ errorText }>
<Tag colorScheme={ colorScheme } display="inline-flex" isLoading={ isLoading }> <Tag colorScheme={ colorScheme } display="inline-flex" isLoading={ isLoading }>
<TagLeftIcon boxSize={ 2.5 } as={ icon }/> <IconSvg boxSize={ 2.5 } name={ icon } mr={ 2 }/>
<TagLabel>{ text }</TagLabel> <TagLabel>{ text }</TagLabel>
</Tag> </Tag>
</Tooltip> </Tooltip>
......
import { Text, Icon, HStack } from '@chakra-ui/react'; import { Text, HStack } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { Step } from './types'; import type { Step } from './types';
import arrowIcon from 'icons/arrows/east.svg'; import IconSvg from 'ui/shared/IconSvg';
import finalizedIcon from 'icons/finalized.svg';
import unfinalizedIcon from 'icons/unfinalized.svg';
type Props = { type Props = {
step: Step; step: Step;
...@@ -18,9 +16,9 @@ const VerificationStep = ({ step, isLast, isPassed }: Props) => { ...@@ -18,9 +16,9 @@ const VerificationStep = ({ step, isLast, isPassed }: Props) => {
return ( return (
<HStack gap={ 2 } color={ stepColor }> <HStack gap={ 2 } color={ stepColor }>
<Icon as={ isPassed ? finalizedIcon : unfinalizedIcon } boxSize={ 5 }/> <IconSvg name={ isPassed ? 'finalized' : 'unfinalized' } boxSize={ 5 }/>
<Text color={ stepColor }>{ typeof step === 'string' ? step : step.content }</Text> <Text color={ stepColor }>{ typeof step === 'string' ? step : step.content }</Text>
{ !isLast && <Icon as={ arrowIcon } boxSize={ 5 }/> } { !isLast && <IconSvg name="arrows/east" boxSize={ 5 }/> }
</HStack> </HStack>
); );
}; };
......
...@@ -6,13 +6,6 @@ import React from 'react'; ...@@ -6,13 +6,6 @@ import React from 'react';
import type { CustomLinksGroup } from 'types/footerLinks'; import type { CustomLinksGroup } from 'types/footerLinks';
import config from 'configs/app'; import config from 'configs/app';
import discussionsIcon from 'icons/discussions.svg';
import donateIcon from 'icons/donate.svg';
import editIcon from 'icons/edit.svg';
import cannyIcon from 'icons/social/canny.svg';
import discordIcon from 'icons/social/discord.svg';
import gitIcon from 'icons/social/git.svg';
import twitterIcon from 'icons/social/tweet.svg';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
...@@ -39,43 +32,43 @@ const Footer = () => { ...@@ -39,43 +32,43 @@ const Footer = () => {
const issueUrl = useIssueUrl(backendVersionData?.backend_version); const issueUrl = useIssueUrl(backendVersionData?.backend_version);
const BLOCKSCOUT_LINKS = [ const BLOCKSCOUT_LINKS = [
{ {
icon: editIcon, icon: 'edit' as const,
iconSize: '16px', iconSize: '16px',
text: 'Submit an issue', text: 'Submit an issue',
url: issueUrl, url: issueUrl,
}, },
{ {
icon: cannyIcon, icon: 'social/canny' as const,
iconSize: '20px', iconSize: '20px',
text: 'Feature request', text: 'Feature request',
url: 'https://blockscout.canny.io/feature-requests', url: 'https://blockscout.canny.io/feature-requests',
}, },
{ {
icon: gitIcon, icon: 'social/git' as const,
iconSize: '18px', iconSize: '18px',
text: 'Contribute', text: 'Contribute',
url: 'https://github.com/blockscout/blockscout', url: 'https://github.com/blockscout/blockscout',
}, },
{ {
icon: twitterIcon, icon: 'social/tweet' as const,
iconSize: '18px', iconSize: '18px',
text: 'Twitter', text: 'Twitter',
url: 'https://www.twitter.com/blockscoutcom', url: 'https://www.twitter.com/blockscoutcom',
}, },
{ {
icon: discordIcon, icon: 'social/discord' as const,
iconSize: '24px', iconSize: '24px',
text: 'Discord', text: 'Discord',
url: 'https://discord.gg/blockscout', url: 'https://discord.gg/blockscout',
}, },
{ {
icon: discussionsIcon, icon: 'discussions' as const,
iconSize: '20px', iconSize: '20px',
text: 'Discussions', text: 'Discussions',
url: 'https://github.com/orgs/blockscout/discussions', url: 'https://github.com/orgs/blockscout/discussions',
}, },
{ {
icon: donateIcon, icon: 'donate' as const,
iconSize: '20px', iconSize: '20px',
text: 'Donate', text: 'Donate',
url: 'https://github.com/sponsors/blockscout', url: 'https://github.com/sponsors/blockscout',
......
import { Center, Icon, Link, Skeleton } from '@chakra-ui/react'; import { Center, Link, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
icon?: React.FC<React.SVGAttributes<SVGElement>>; icon?: IconName;
iconSize?: string; iconSize?: string;
text: string; text: string;
url: string; url: string;
...@@ -18,7 +21,7 @@ const FooterLinkItem = ({ icon, iconSize, text, url, isLoading }: Props) => { ...@@ -18,7 +21,7 @@ const FooterLinkItem = ({ icon, iconSize, text, url, isLoading }: Props) => {
<Link href={ url } display="flex" alignItems="center" h="30px" variant="secondary" target="_blank" fontSize="xs"> <Link href={ url } display="flex" alignItems="center" h="30px" variant="secondary" target="_blank" fontSize="xs">
{ icon && ( { icon && (
<Center minW={ 6 } mr={ 2 }> <Center minW={ 6 } mr={ 2 }>
<Icon boxSize={ iconSize || 5 } as={ icon }/> <IconSvg boxSize={ iconSize || 5 } name={ icon }/>
</Center> </Center>
) } ) }
{ text } { text }
......
import { IconButton, Icon, Popover, PopoverTrigger, PopoverContent, PopoverBody, Flex, Text, useColorModeValue } from '@chakra-ui/react'; import { IconButton, Popover, PopoverTrigger, PopoverContent, PopoverBody, Flex, Text, useColorModeValue } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { IndexingStatus } from 'types/api/indexingStatus'; import type { IndexingStatus } from 'types/api/indexingStatus';
import infoIcon from 'icons/info.svg';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import { apos, nbsp, ndash } from 'lib/html-entities'; import { apos, nbsp, ndash } from 'lib/html-entities';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import IconSvg from 'ui/shared/IconSvg';
const IntTxsIndexingStatus = () => { const IntTxsIndexingStatus = () => {
...@@ -72,7 +72,7 @@ const IntTxsIndexingStatus = () => { ...@@ -72,7 +72,7 @@ const IntTxsIndexingStatus = () => {
<IconButton <IconButton
colorScheme="none" colorScheme="none"
aria-label="hint" aria-label="hint"
icon={ <Icon as={ infoIcon } boxSize={ 5 }/> } icon={ <IconSvg name="info" boxSize={ 5 }/> }
boxSize={ 6 } boxSize={ 6 }
variant="simple" variant="simple"
/> />
......
...@@ -50,7 +50,7 @@ test('base view', async({ mount, page }) => { ...@@ -50,7 +50,7 @@ test('base view', async({ mount, page }) => {
{ hooksConfig }, { hooksConfig },
); );
await component.locator('svg[aria-label="Menu button"]').click(); await component.locator('div[aria-label="Menu button"]').click();
await expect(page.locator('.chakra-modal__content-container')).toHaveScreenshot(); await expect(page.locator('.chakra-modal__content-container')).toHaveScreenshot();
await page.locator('button[aria-label="Network menu"]').click(); await page.locator('button[aria-label="Network menu"]').click();
...@@ -80,7 +80,7 @@ test.describe('dark mode', () => { ...@@ -80,7 +80,7 @@ test.describe('dark mode', () => {
{ hooksConfig }, { hooksConfig },
); );
await component.locator('svg[aria-label="Menu button"]').click(); await component.locator('div[aria-label="Menu button"]').click();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot();
await page.locator('button[aria-label="Network menu"]').click(); await page.locator('button[aria-label="Network menu"]').click();
...@@ -96,7 +96,7 @@ test('submenu', async({ mount, page }) => { ...@@ -96,7 +96,7 @@ test('submenu', async({ mount, page }) => {
{ hooksConfig }, { hooksConfig },
); );
await component.locator('svg[aria-label="Menu button"]').click(); await component.locator('div[aria-label="Menu button"]').click();
await page.locator('div[aria-label="Blockchain link group"]').click(); await page.locator('div[aria-label="Blockchain link group"]').click();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot();
}); });
...@@ -122,7 +122,7 @@ test.describe('auth', () => { ...@@ -122,7 +122,7 @@ test.describe('auth', () => {
{ hooksConfig }, { hooksConfig },
); );
await component.locator('svg[aria-label="Menu button"]').click(); await component.locator('div[aria-label="Menu button"]').click();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot();
}); });
}); });
import { Icon, Box, Flex, Drawer, DrawerOverlay, DrawerContent, DrawerBody, useColorModeValue, useDisclosure } from '@chakra-ui/react'; import { Box, Flex, Drawer, DrawerOverlay, DrawerContent, DrawerBody, useColorModeValue, useDisclosure } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import burgerIcon from 'icons/burger.svg'; import IconSvg from 'ui/shared/IconSvg';
import testnetIcon from 'icons/testnet.svg';
import NavigationMobile from 'ui/snippets/navigation/NavigationMobile'; import NavigationMobile from 'ui/snippets/navigation/NavigationMobile';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo'; import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkMenuButton from 'ui/snippets/networkMenu/NetworkMenuButton'; import NetworkMenuButton from 'ui/snippets/networkMenu/NetworkMenuButton';
...@@ -31,8 +30,8 @@ const Burger = ({ isMarketplaceAppPage }: Props) => { ...@@ -31,8 +30,8 @@ const Burger = ({ isMarketplaceAppPage }: Props) => {
return ( return (
<> <>
<Box padding={ 2 } onClick={ onOpen } cursor="pointer"> <Box padding={ 2 } onClick={ onOpen } cursor="pointer">
<Icon <IconSvg
as={ burgerIcon } name="burger"
boxSize={ 6 } boxSize={ 6 }
display="block" display="block"
color={ iconColor } color={ iconColor }
...@@ -48,7 +47,7 @@ const Burger = ({ isMarketplaceAppPage }: Props) => { ...@@ -48,7 +47,7 @@ const Burger = ({ isMarketplaceAppPage }: Props) => {
<DrawerOverlay/> <DrawerOverlay/>
<DrawerContent maxWidth="260px"> <DrawerContent maxWidth="260px">
<DrawerBody p={ 6 } display="flex" flexDirection="column"> <DrawerBody p={ 6 } display="flex" flexDirection="column">
{ config.chain.isTestnet && <Icon as={ testnetIcon } h="14px" w="auto" color="red.400" alignSelf="flex-start"/> } { config.chain.isTestnet && <IconSvg name="testnet" h="14px" w="37px" color="red.400" alignSelf="flex-start"/> }
<Flex alignItems="center" justifyContent="space-between"> <Flex alignItems="center" justifyContent="space-between">
<NetworkLogo onClick={ handleNetworkLogoClick }/> <NetworkLogo onClick={ handleNetworkLogoClick }/>
{ config.UI.sidebar.featuredNetworks ? ( { config.UI.sidebar.featuredNetworks ? (
......
import { Link, Text, HStack, Tooltip, Box, useBreakpointValue, chakra, shouldForwardProp, Icon } from '@chakra-ui/react'; import { Link, Text, HStack, Tooltip, Box, useBreakpointValue, chakra, shouldForwardProp } from '@chakra-ui/react';
import NextLink from 'next/link'; import NextLink from 'next/link';
import React from 'react'; import React from 'react';
...@@ -6,9 +6,9 @@ import type { NavItem } from 'types/client/navigation-items'; ...@@ -6,9 +6,9 @@ import type { NavItem } from 'types/client/navigation-items';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import arrowIcon from 'icons/arrows/north-east.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import { isInternalItem } from 'lib/hooks/useNavItems'; import { isInternalItem } from 'lib/hooks/useNavItems';
import IconSvg from 'ui/shared/IconSvg';
import NavLinkIcon from './NavLinkIcon'; import NavLinkIcon from './NavLinkIcon';
import useColors from './useColors'; import useColors from './useColors';
...@@ -63,7 +63,7 @@ const NavLink = ({ item, isCollapsed, px, className, onClick }: Props) => { ...@@ -63,7 +63,7 @@ const NavLink = ({ item, isCollapsed, px, className, onClick }: Props) => {
<NavLinkIcon item={ item }/> <NavLinkIcon item={ item }/>
<Text { ...styleProps.textProps }> <Text { ...styleProps.textProps }>
<span>{ item.text }</span> <span>{ item.text }</span>
{ !isInternalLink && <Icon as={ arrowIcon } boxSize={ 4 } color="text_secondary" verticalAlign="middle"/> } { !isInternalLink && <IconSvg name="arrows/north-east" boxSize={ 4 } color="text_secondary" verticalAlign="middle"/> }
</Text> </Text>
</HStack> </HStack>
</Tooltip> </Tooltip>
......
import { import {
Icon,
Text, Text,
HStack, HStack,
Box, Box,
...@@ -14,7 +13,7 @@ import React from 'react'; ...@@ -14,7 +13,7 @@ import React from 'react';
import type { NavGroupItem } from 'types/client/navigation-items'; import type { NavGroupItem } from 'types/client/navigation-items';
import chevronIcon from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
import NavLink from './NavLink'; import NavLink from './NavLink';
import NavLinkIcon from './NavLinkIcon'; import NavLinkIcon from './NavLinkIcon';
...@@ -53,8 +52,8 @@ const NavLinkGroupDesktop = ({ item, isCollapsed }: Props) => { ...@@ -53,8 +52,8 @@ const NavLinkGroupDesktop = ({ item, isCollapsed }: Props) => {
> >
{ item.text } { item.text }
</Text> </Text>
<Icon <IconSvg
as={ chevronIcon } name="arrows/east-mini"
position="absolute" position="absolute"
right="7px" right="7px"
transform="rotate(180deg)" transform="rotate(180deg)"
......
import { import {
Icon,
Text, Text,
HStack, HStack,
Flex, Flex,
...@@ -9,7 +8,7 @@ import React from 'react'; ...@@ -9,7 +8,7 @@ import React from 'react';
import type { NavGroupItem } from 'types/client/navigation-items'; import type { NavGroupItem } from 'types/client/navigation-items';
import chevronIcon from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
import NavLinkIcon from './NavLinkIcon'; import NavLinkIcon from './NavLinkIcon';
import useNavLinkStyleProps from './useNavLinkStyleProps'; import useNavLinkStyleProps from './useNavLinkStyleProps';
...@@ -40,7 +39,7 @@ const NavLinkGroup = ({ item, onClick, isExpanded }: Props) => { ...@@ -40,7 +39,7 @@ const NavLinkGroup = ({ item, onClick, isExpanded }: Props) => {
{ item.text } { item.text }
</Text> </Text>
</HStack> </HStack>
<Icon as={ chevronIcon } transform="rotate(180deg)" boxSize={ 6 }/> <IconSvg name="arrows/east-mini" transform="rotate(180deg)" boxSize={ 6 }/>
</Flex> </Flex>
</Box> </Box>
</Box> </Box>
......
import { Icon } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { NavItem, NavGroupItem } from 'types/client/navigation-items'; import type { NavItem, NavGroupItem } from 'types/client/navigation-items';
import IconSvg from 'ui/shared/IconSvg';
const NavLinkIcon = ({ item }: { item: NavItem | NavGroupItem}) => { const NavLinkIcon = ({ item }: { item: NavItem | NavGroupItem}) => {
if ('icon' in item) { if ('icon' in item && item.icon) {
return <Icon as={ item.icon } boxSize="30px"/>; return <IconSvg name={ item.icon } boxSize="30px" flexShrink={ 0 }/>;
} }
if ('iconComponent' in item && item.iconComponent) { if ('iconComponent' in item && item.iconComponent) {
const IconComponent = item.iconComponent; const IconComponent = item.iconComponent;
......
...@@ -111,7 +111,7 @@ test.describe('with tooltips', () => { ...@@ -111,7 +111,7 @@ test.describe('with tooltips', () => {
); );
await component.locator('header').hover(); await component.locator('header').hover();
await page.locator('svg[aria-label="Expand/Collapse menu"]').click(); await page.locator('div[aria-label="Expand/Collapse menu"]').click();
await page.locator('a[aria-label="Tokens link"]').hover(); await page.locator('a[aria-label="Tokens link"]').hover();
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
......
import { Flex, Box, VStack, Icon, useColorModeValue } from '@chakra-ui/react'; import { Flex, Box, VStack, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import chevronIcon from 'icons/arrows/east-mini.svg';
import testnetIcon from 'icons/testnet.svg';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
import useHasAccount from 'lib/hooks/useHasAccount'; import useHasAccount from 'lib/hooks/useHasAccount';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems'; import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps'; import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps';
import IconSvg from 'ui/shared/IconSvg';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo'; import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkMenu from 'ui/snippets/networkMenu/NetworkMenu'; import NetworkMenu from 'ui/snippets/networkMenu/NetworkMenu';
...@@ -65,7 +64,7 @@ const NavigationDesktop = () => { ...@@ -65,7 +64,7 @@ const NavigationDesktop = () => {
}, },
}} }}
> >
{ config.chain.isTestnet && <Icon as={ testnetIcon } h="14px" w="auto" color="red.400" position="absolute" pl={ 3 } top="34px"/> } { config.chain.isTestnet && <IconSvg name="testnet" h="14px" w="49px" color="red.400" position="absolute" pl={ 3 } top="34px"/> }
<Box <Box
as="header" as="header"
display="flex" display="flex"
...@@ -101,8 +100,8 @@ const NavigationDesktop = () => { ...@@ -101,8 +100,8 @@ const NavigationDesktop = () => {
</VStack> </VStack>
</Box> </Box>
) } ) }
<Icon <IconSvg
as={ chevronIcon } name="arrows/east-mini"
width={ 6 } width={ 6 }
height={ 6 } height={ 6 }
border="1px" border="1px"
......
import { Box, Flex, Text, Icon, VStack, useColorModeValue } from '@chakra-ui/react'; import { Box, Flex, Text, VStack, useColorModeValue } from '@chakra-ui/react';
import { animate, motion, useMotionValue } from 'framer-motion'; import { animate, motion, useMotionValue } from 'framer-motion';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import chevronIcon from 'icons/arrows/east-mini.svg';
import useHasAccount from 'lib/hooks/useHasAccount'; import useHasAccount from 'lib/hooks/useHasAccount';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems'; import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import IconSvg from 'ui/shared/IconSvg';
import NavLink from 'ui/snippets/navigation/NavLink'; import NavLink from 'ui/snippets/navigation/NavLink';
import NavLinkGroupMobile from './NavLinkGroupMobile'; import NavLinkGroupMobile from './NavLinkGroupMobile';
...@@ -96,7 +96,7 @@ const NavigationMobile = ({ onNavLinkClick, isMarketplaceAppPage }: Props) => { ...@@ -96,7 +96,7 @@ const NavigationMobile = ({ onNavLinkClick, isMarketplaceAppPage }: Props) => {
key="sub" key="sub"
> >
<Flex alignItems="center" px={ 3 } py={ 2.5 } w="100%" h="50px" onClick={ onGroupItemClose } mb={ 1 }> <Flex alignItems="center" px={ 3 } py={ 2.5 } w="100%" h="50px" onClick={ onGroupItemClose } mb={ 1 }>
<Icon as={ chevronIcon } boxSize={ 6 } mr={ 2 } color={ iconColor }/> <IconSvg name="arrows/east-mini" boxSize={ 6 } mr={ 2 } color={ iconColor }/>
<Text variant="secondary" fontSize="sm">{ mainNavItems[openedGroupIndex].text }</Text> <Text variant="secondary" fontSize="sm">{ mainNavItems[openedGroupIndex].text }</Text>
</Flex> </Flex>
<Box <Box
......
import { Icon, Box, Image, useColorModeValue, Skeleton } from '@chakra-ui/react'; import { Box, Image, useColorModeValue, Skeleton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import iconPlaceholder from 'icons/networks/icon-placeholder.svg'; import IconSvg from 'ui/shared/IconSvg';
import logoPlaceholder from 'icons/networks/logo-placeholder.svg';
interface Props { interface Props {
isCollapsed?: boolean; isCollapsed?: boolean;
...@@ -31,8 +30,8 @@ const LogoFallback = ({ isCollapsed, isSmall }: { isCollapsed?: boolean; isSmall ...@@ -31,8 +30,8 @@ const LogoFallback = ({ isCollapsed, isSmall }: { isCollapsed?: boolean; isSmall
} }
return ( return (
<Icon <IconSvg
as={ isSmall ? iconPlaceholder : logoPlaceholder } name={ isSmall ? 'networks/icon-placeholder' : 'networks/logo-placeholder' }
width="auto" width="auto"
height="100%" height="100%"
color={ logoColor } color={ logoColor }
...@@ -50,11 +49,10 @@ const NetworkLogo = ({ isCollapsed, onClick }: Props) => { ...@@ -50,11 +49,10 @@ const NetworkLogo = ({ isCollapsed, onClick }: Props) => {
const iconStyle = useColorModeValue({}, !config.UI.sidebar.icon.dark ? darkModeFilter : {}); const iconStyle = useColorModeValue({}, !config.UI.sidebar.icon.dark ? darkModeFilter : {});
return ( return (
// TODO switch to <NextLink href={ href } passHref> when main page for network will be ready
<Box <Box
as="a" as="a"
href={ route({ pathname: '/' }) } href={ route({ pathname: '/' }) }
width={{ base: 'auto', lg: isCollapsed === false ? '120px' : '30px', xl: isCollapsed ? '30px' : '120px' }} width={{ base: '120px', lg: isCollapsed === false ? '120px' : '30px', xl: isCollapsed ? '30px' : '120px' }}
height={{ base: '24px', lg: isCollapsed === false ? '24px' : '30px', xl: isCollapsed ? '30px' : '24px' }} height={{ base: '24px', lg: isCollapsed === false ? '24px' : '30px', xl: isCollapsed ? '30px' : '24px' }}
display="inline-flex" display="inline-flex"
overflow="hidden" overflow="hidden"
......
import { Icon, useColorModeValue, Button, forwardRef, chakra } from '@chakra-ui/react'; import { useColorModeValue, Button, forwardRef, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import networksIcon from 'icons/networks.svg';
import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps'; import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
isMobile?: boolean; isMobile?: boolean;
...@@ -30,8 +30,8 @@ const NetworkMenuButton = ({ isMobile, isActive, onClick, className }: Props, re ...@@ -30,8 +30,8 @@ const NetworkMenuButton = ({ isMobile, isActive, onClick, className }: Props, re
aria-label="Network menu" aria-label="Network menu"
aria-roledescription="menu" aria-roledescription="menu"
> >
<Icon <IconSvg
as={ networksIcon } name="networks"
width="36px" width="36px"
height="36px" height="36px"
padding="10px" padding="10px"
......
import { Box, Flex, Icon, Text, Image, useColorModeValue } from '@chakra-ui/react'; import { Box, Flex, Text, Image, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FeaturedNetwork } from 'types/networks'; import type { FeaturedNetwork } from 'types/networks';
import checkIcon from 'icons/check.svg'; import IconSvg from 'ui/shared/IconSvg';
import placeholderIcon from 'icons/networks/icon-placeholder.svg';
import useColors from './useColors'; import useColors from './useColors';
...@@ -21,8 +20,8 @@ const NetworkMenuLink = ({ title, icon, isActive, isMobile, url, invertIconInDar ...@@ -21,8 +20,8 @@ const NetworkMenuLink = ({ title, icon, isActive, isMobile, url, invertIconInDar
const iconEl = icon ? ( const iconEl = icon ? (
<Image w="30px" h="30px" src={ icon } alt={ `${ title } network icon` } style={ style }/> <Image w="30px" h="30px" src={ icon } alt={ `${ title } network icon` } style={ style }/>
) : ( ) : (
<Icon <IconSvg
as={ placeholderIcon } name="networks/icon-placeholder"
boxSize="30px" boxSize="30px"
color={ colors.iconPlaceholder.default } color={ colors.iconPlaceholder.default }
/> />
...@@ -54,8 +53,8 @@ const NetworkMenuLink = ({ title, icon, isActive, isMobile, url, invertIconInDar ...@@ -54,8 +53,8 @@ const NetworkMenuLink = ({ title, icon, isActive, isMobile, url, invertIconInDar
{ title } { title }
</Text> </Text>
{ isActive && ( { isActive && (
<Icon <IconSvg
as={ checkIcon } name="check"
boxSize="24px" boxSize="24px"
marginLeft="auto" marginLeft="auto"
/> />
......
import { Box, Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure, PopoverFooter } from '@chakra-ui/react'; import { Box, Portal, Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure, PopoverFooter, useOutsideClick } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import _debounce from 'lodash/debounce';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import type { FormEvent, FocusEvent } from 'react'; import type { FormEvent } from 'react';
import React from 'react'; import React from 'react';
import { Element } from 'react-scroll'; import { Element } from 'react-scroll';
...@@ -59,13 +59,15 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -59,13 +59,15 @@ const SearchBar = ({ isHomepage }: Props) => {
inputRef.current?.querySelector('input')?.blur(); inputRef.current?.querySelector('input')?.blur();
}, [ onClose ]); }, [ onClose ]);
const handleBlur = React.useCallback((event: FocusEvent<HTMLFormElement>) => { const handleOutsideClick = React.useCallback((event: Event) => {
const isFocusInMenu = menuRef.current?.contains(event.relatedTarget); const isFocusInInput = inputRef.current?.contains(event.target as Node);
const isFocusInInput = inputRef.current?.contains(event.relatedTarget);
if (!isFocusInMenu && !isFocusInInput) { if (!isFocusInInput) {
onClose(); handelHide();
} }
}, [ onClose ]); }, [ handelHide ]);
useOutsideClick({ ref: menuRef, handler: handleOutsideClick });
const handleClear = React.useCallback(() => { const handleClear = React.useCallback(() => {
handleSearchTermChange(''); handleSearchTermChange('');
...@@ -118,13 +120,13 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -118,13 +120,13 @@ const SearchBar = ({ isHomepage }: Props) => {
onChange={ handleSearchTermChange } onChange={ handleSearchTermChange }
onSubmit={ handleSubmit } onSubmit={ handleSubmit }
onFocus={ handleFocus } onFocus={ handleFocus }
onBlur={ handleBlur }
onHide={ handelHide } onHide={ handelHide }
onClear={ handleClear } onClear={ handleClear }
isHomepage={ isHomepage } isHomepage={ isHomepage }
value={ searchTerm } value={ searchTerm }
/> />
</PopoverTrigger> </PopoverTrigger>
<Portal>
<PopoverContent <PopoverContent
w={ `${ menuWidth.current }px` } w={ `${ menuWidth.current }px` }
ref={ menuRef } ref={ menuRef }
...@@ -165,6 +167,7 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -165,6 +167,7 @@ const SearchBar = ({ isHomepage }: Props) => {
</PopoverFooter> </PopoverFooter>
) } ) }
</PopoverContent> </PopoverContent>
</Portal>
</Popover> </Popover>
); );
}; };
......
import { InputGroup, Input, InputLeftElement, Icon, chakra, useColorModeValue, forwardRef, InputRightElement } from '@chakra-ui/react'; import { InputGroup, Input, InputLeftElement, chakra, useColorModeValue, forwardRef, InputRightElement } from '@chakra-ui/react';
import throttle from 'lodash/throttle'; import throttle from 'lodash/throttle';
import React from 'react'; import React from 'react';
import type { ChangeEvent, FormEvent, FocusEvent } from 'react'; import type { ChangeEvent, FormEvent, FocusEvent } from 'react';
import searchIcon from 'icons/search.svg';
import { useScrollDirection } from 'lib/contexts/scrollDirection'; import { useScrollDirection } from 'lib/contexts/scrollDirection';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import ClearButton from 'ui/shared/ClearButton'; import ClearButton from 'ui/shared/ClearButton';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
onChange: (value: string) => void; onChange: (value: string) => void;
...@@ -20,25 +20,33 @@ interface Props { ...@@ -20,25 +20,33 @@ interface Props {
} }
const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHide, onClear, value }: Props, ref: React.ForwardedRef<HTMLFormElement>) => { const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHide, onClear, value }: Props, ref: React.ForwardedRef<HTMLFormElement>) => {
const innerRef = React.useRef<HTMLFormElement>(null);
React.useImperativeHandle(ref, () => innerRef.current as HTMLFormElement, []);
const [ isSticky, setIsSticky ] = React.useState(false); const [ isSticky, setIsSticky ] = React.useState(false);
const scrollDirection = useScrollDirection(); const scrollDirection = useScrollDirection();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const handleScroll = React.useCallback(() => { const handleScroll = React.useCallback(() => {
const TOP_BAR_HEIGHT = 36; const TOP_BAR_HEIGHT = 36;
if (window.pageYOffset >= TOP_BAR_HEIGHT) { if (!isHomepage) {
if (window.scrollY >= TOP_BAR_HEIGHT) {
setIsSticky(true); setIsSticky(true);
} else { } else {
setIsSticky(false); setIsSticky(false);
} }
}, [ ]); }
const clientRect = isMobile && innerRef?.current?.getBoundingClientRect();
if (clientRect && clientRect.y < TOP_BAR_HEIGHT) {
onHide?.();
}
}, [ isMobile, onHide, isHomepage ]);
const handleChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => { const handleChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
onChange(event.target.value); onChange(event.target.value);
}, [ onChange ]); }, [ onChange ]);
React.useEffect(() => { React.useEffect(() => {
if (!isMobile || isHomepage) { if (!isMobile) {
return; return;
} }
const throttledHandleScroll = throttle(handleScroll, 300); const throttledHandleScroll = throttle(handleScroll, 300);
...@@ -48,22 +56,14 @@ const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHid ...@@ -48,22 +56,14 @@ const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHid
return () => { return () => {
window.removeEventListener('scroll', throttledHandleScroll); window.removeEventListener('scroll', throttledHandleScroll);
}; };
// replicate componentDidMount }, [ isMobile, handleScroll ]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ isMobile ]);
const bgColor = useColorModeValue('white', 'black'); const bgColor = useColorModeValue('white', 'black');
const transformMobile = scrollDirection !== 'down' ? 'translateY(0)' : 'translateY(-100%)'; const transformMobile = scrollDirection !== 'down' ? 'translateY(0)' : 'translateY(-100%)';
React.useEffect(() => {
if (isMobile && scrollDirection === 'down') {
onHide?.();
}
}, [ scrollDirection, onHide, isMobile ]);
return ( return (
<chakra.form <chakra.form
ref={ ref } ref={ innerRef }
noValidate noValidate
onSubmit={ onSubmit } onSubmit={ onSubmit }
onBlur={ onBlur } onBlur={ onBlur }
...@@ -86,7 +86,7 @@ const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHid ...@@ -86,7 +86,7 @@ const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHid
> >
<InputGroup size={{ base: isHomepage ? 'md' : 'sm', lg: 'md' }}> <InputGroup size={{ base: isHomepage ? 'md' : 'sm', lg: 'md' }}>
<InputLeftElement w={{ base: isHomepage ? 6 : 4, lg: 6 }} ml={{ base: isHomepage ? 4 : 3, lg: 4 }} h="100%"> <InputLeftElement w={{ base: isHomepage ? 6 : 4, lg: 6 }} ml={{ base: isHomepage ? 4 : 3, lg: 4 }} h="100%">
<Icon as={ searchIcon } boxSize={{ base: isHomepage ? 6 : 4, lg: 6 }} color={ useColorModeValue('blackAlpha.600', 'whiteAlpha.600') }/> <IconSvg name="search" boxSize={{ base: isHomepage ? 6 : 4, lg: 6 }} color={ useColorModeValue('blackAlpha.600', 'whiteAlpha.600') }/>
</InputLeftElement> </InputLeftElement>
<Input <Input
pl={{ base: isHomepage ? '50px' : '38px', lg: '50px' }} pl={{ base: isHomepage ? '50px' : '38px', lg: '50px' }}
......
import { Icon, Image, Flex, Text, useColorModeValue } from '@chakra-ui/react'; import { Image, Flex, Text, useColorModeValue } from '@chakra-ui/react';
import NextLink from 'next/link'; import NextLink from 'next/link';
import React from 'react'; import React from 'react';
import type { MarketplaceAppOverview } from 'types/client/marketplace'; import type { MarketplaceAppOverview } from 'types/client/marketplace';
import arrowIcon from 'icons/arrows/north-east.svg';
import highlightText from 'lib/highlightText'; import highlightText from 'lib/highlightText';
import IconSvg from 'ui/shared/IconSvg';
import SearchBarSuggestItemLink from './SearchBarSuggestItemLink'; import SearchBarSuggestItemLink from './SearchBarSuggestItemLink';
...@@ -42,7 +42,7 @@ const SearchBarSuggestApp = ({ data, isMobile, searchTerm, onClick }: Props) => ...@@ -42,7 +42,7 @@ const SearchBarSuggestApp = ({ data, isMobile, searchTerm, onClick }: Props) =>
> >
<span dangerouslySetInnerHTML={{ __html: highlightText(data.title, searchTerm) }}/> <span dangerouslySetInnerHTML={{ __html: highlightText(data.title, searchTerm) }}/>
</Text> </Text>
{ data.external && <Icon as={ arrowIcon } boxSize={ 4 } verticalAlign="middle"/> } { data.external && <IconSvg name="arrows/north-east" boxSize={ 4 } verticalAlign="middle" flexShrink={ 0 }/> }
</Flex> </Flex>
<Text <Text
variant="secondary" variant="secondary"
...@@ -81,7 +81,7 @@ const SearchBarSuggestApp = ({ data, isMobile, searchTerm, onClick }: Props) => ...@@ -81,7 +81,7 @@ const SearchBarSuggestApp = ({ data, isMobile, searchTerm, onClick }: Props) =>
> >
{ data.description } { data.description }
</Text> </Text>
{ data.external && <Icon as={ arrowIcon } boxSize={ 4 } verticalAlign="middle" color="text_secondary"/> } { data.external && <IconSvg name="arrows/north-east" boxSize={ 4 } verticalAlign="middle" color="text_secondary" flexShrink={ 0 }/> }
</Flex> </Flex>
); );
})(); })();
......
import { Grid, Text, Flex, Icon } from '@chakra-ui/react'; import { Grid, Text, Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { SearchResultLabel } from 'types/api/search'; import type { SearchResultLabel } from 'types/api/search';
import labelIcon from 'icons/publictags_slim.svg';
import iconSuccess from 'icons/status/success.svg';
import highlightText from 'lib/highlightText'; import highlightText from 'lib/highlightText';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
data: SearchResultLabel; data: SearchResultLabel;
...@@ -15,7 +14,7 @@ interface Props { ...@@ -15,7 +14,7 @@ interface Props {
} }
const SearchBarSuggestLabel = ({ data, isMobile, searchTerm }: Props) => { const SearchBarSuggestLabel = ({ data, isMobile, searchTerm }: Props) => {
const icon = <Icon as={ labelIcon } boxSize={ 5 } color="gray.500"/>; const icon = <IconSvg name="publictags_slim" boxSize={ 5 } color="gray.500"/>;
const name = ( const name = (
<Text <Text
...@@ -38,7 +37,7 @@ const SearchBarSuggestLabel = ({ data, isMobile, searchTerm }: Props) => { ...@@ -38,7 +37,7 @@ const SearchBarSuggestLabel = ({ data, isMobile, searchTerm }: Props) => {
</Text> </Text>
); );
const isContractVerified = data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500"/>; const isContractVerified = data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" flexShrink={ 0 }/>;
if (isMobile) { if (isMobile) {
return ( return (
......
import { Grid, Text, Flex, Icon } from '@chakra-ui/react'; import { Grid, Text, Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { SearchResultToken } from 'types/api/search'; import type { SearchResultToken } from 'types/api/search';
import iconSuccess from 'icons/status/success.svg';
import verifiedToken from 'icons/verified_token.svg';
import highlightText from 'lib/highlightText'; import highlightText from 'lib/highlightText';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
data: SearchResultToken; data: SearchResultToken;
...@@ -17,7 +16,7 @@ interface Props { ...@@ -17,7 +16,7 @@ interface Props {
const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => { const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => {
const icon = <TokenEntity.Icon token={{ ...data, type: data.token_type }}/>; const icon = <TokenEntity.Icon token={{ ...data, type: data.token_type }}/>;
const verifiedIcon = <Icon as={ verifiedToken } boxSize={ 4 } color="green.500" ml={ 1 }/>; const verifiedIcon = <IconSvg name="verified_token" boxSize={ 4 } color="green.500" ml={ 1 }/>;
const name = ( const name = (
<Text <Text
fontWeight={ 700 } fontWeight={ 700 }
...@@ -35,7 +34,7 @@ const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => { ...@@ -35,7 +34,7 @@ const SearchBarSuggestToken = ({ data, isMobile, searchTerm }: Props) => {
</Text> </Text>
); );
const contractVerifiedIcon = data.is_smart_contract_verified && <Icon as={ iconSuccess } color="green.500" ml={ 1 }/>; const contractVerifiedIcon = data.is_smart_contract_verified && <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 } flexShrink={ 0 }/>;
const additionalInfo = ( const additionalInfo = (
<Text overflow="hidden" whiteSpace="nowrap" fontWeight={ 700 }> <Text overflow="hidden" whiteSpace="nowrap" fontWeight={ 700 }>
{ data.token_type === 'ERC-20' && data.exchange_rate && `$${ Number(data.exchange_rate).toLocaleString() }` } { data.token_type === 'ERC-20' && data.exchange_rate && `$${ Number(data.exchange_rate).toLocaleString() }` }
......
import { import {
IconButton, IconButton,
Icon,
Popover, Popover,
PopoverTrigger, PopoverTrigger,
PopoverContent, PopoverContent,
...@@ -12,6 +11,7 @@ import { ...@@ -12,6 +11,7 @@ import {
import React from 'react'; import React from 'react';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
import IconSvg from 'ui/shared/IconSvg';
import ColorModeSwitchTheme from './ColorModeSwitchTheme'; import ColorModeSwitchTheme from './ColorModeSwitchTheme';
import { COLOR_THEMES } from './utils'; import { COLOR_THEMES } from './utils';
...@@ -79,7 +79,7 @@ const ColorModeSwitch = () => { ...@@ -79,7 +79,7 @@ const ColorModeSwitch = () => {
variant="simple" variant="simple"
colorScheme="blue" colorScheme="blue"
aria-label="color mode switch" aria-label="color mode switch"
icon={ <Icon as={ activeTheme.icon } boxSize={ 5 }/> } icon={ <IconSvg name={ activeTheme.icon } boxSize={ 5 }/> }
boxSize={ 5 } boxSize={ 5 }
onClick={ onToggle } onClick={ onToggle }
/> />
......
import { import {
Icon,
Flex, Flex,
useColorModeValue, useColorModeValue,
useToken, useToken,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import IconSvg from 'ui/shared/IconSvg';
import ColorModeSwitchSample from './ColorModeSwitchSample'; import ColorModeSwitchSample from './ColorModeSwitchSample';
import type { ColorTheme } from './utils'; import type { ColorTheme } from './utils';
...@@ -43,7 +44,7 @@ const ColorModeSwitchTheme = ({ icon, name, colors, onClick, activeHex }: Props) ...@@ -43,7 +44,7 @@ const ColorModeSwitchTheme = ({ icon, name, colors, onClick, activeHex }: Props)
fontWeight={ 500 } fontWeight={ 500 }
borderRadius="base" borderRadius="base"
> >
<Icon as={ icon } boxSize={ 5 } mr={ 2 }/> <IconSvg name={ icon } boxSize={ 5 } mr={ 2 }/>
<span>{ name }</span> <span>{ name }</span>
<Flex columnGap={ 2 } ml="auto" alignItems="center"> <Flex columnGap={ 2 } ml="auto" alignItems="center">
{ colors.map((sample) => <ColorModeSwitchSample key={ sample.hex } { ...sample } onClick={ onClick } isActive={ activeHex === sample.hex }/>) } { colors.map((sample) => <ColorModeSwitchSample key={ sample.hex } { ...sample } onClick={ onClick } isActive={ activeHex === sample.hex }/>) }
......
import moonWithStarIcon from 'icons/moon-with-star.svg'; import type { IconName } from 'ui/shared/IconSvg';
import moonIcon from 'icons/moon.svg';
import sunIcon from 'icons/sun.svg';
export const COLOR_THEMES = [ export const COLOR_THEMES = [
{ {
name: 'Light', name: 'Light',
colorMode: 'light', colorMode: 'light',
icon: sunIcon, icon: 'sun' as IconName,
colors: [ colors: [
{ hex: '#FFFFFF', sampleBg: 'linear-gradient(154deg, #EFEFEF 50%, rgba(255, 255, 255, 0.00) 330.86%)' }, { hex: '#FFFFFF', sampleBg: 'linear-gradient(154deg, #EFEFEF 50%, rgba(255, 255, 255, 0.00) 330.86%)' },
], ],
...@@ -14,7 +12,7 @@ export const COLOR_THEMES = [ ...@@ -14,7 +12,7 @@ export const COLOR_THEMES = [
{ {
name: 'Dim', name: 'Dim',
colorMode: 'dark', colorMode: 'dark',
icon: moonWithStarIcon, icon: 'moon-with-star' as IconName,
colors: [ colors: [
{ hex: '#232B37', sampleBg: 'linear-gradient(152deg, #232B37 50%, rgba(255, 255, 255, 0.00) 290.71%)' }, { hex: '#232B37', sampleBg: 'linear-gradient(152deg, #232B37 50%, rgba(255, 255, 255, 0.00) 290.71%)' },
{ hex: '#1B2E48', sampleBg: 'linear-gradient(150deg, #1B2E48 50%, rgba(255, 255, 255, 0.00) 312.75%)' }, { hex: '#1B2E48', sampleBg: 'linear-gradient(150deg, #1B2E48 50%, rgba(255, 255, 255, 0.00) 312.75%)' },
...@@ -23,7 +21,7 @@ export const COLOR_THEMES = [ ...@@ -23,7 +21,7 @@ export const COLOR_THEMES = [
{ {
name: 'Dark', name: 'Dark',
colorMode: 'dark', colorMode: 'dark',
icon: moonIcon, icon: 'moon' as IconName,
colors: [ colors: [
{ hex: '#101112', sampleBg: 'linear-gradient(161deg, #000 9.37%, #383838 92.52%)' }, { hex: '#101112', sampleBg: 'linear-gradient(161deg, #000 9.37%, #383838 92.52%)' },
], ],
......
import { Drawer, DrawerOverlay, DrawerContent, DrawerBody, useDisclosure, IconButton, Icon } from '@chakra-ui/react'; import { Drawer, DrawerOverlay, DrawerContent, DrawerBody, useDisclosure, IconButton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import walletIcon from 'icons/wallet.svg';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import AddressIdenticon from 'ui/shared/entities/address/AddressIdenticon'; import AddressIdenticon from 'ui/shared/entities/address/AddressIdenticon';
import IconSvg from 'ui/shared/IconSvg';
import useWallet from 'ui/snippets/walletMenu/useWallet'; import useWallet from 'ui/snippets/walletMenu/useWallet';
import WalletMenuContent from 'ui/snippets/walletMenu/WalletMenuContent'; import WalletMenuContent from 'ui/snippets/walletMenu/WalletMenuContent';
...@@ -23,7 +23,7 @@ const WalletMenuMobile = () => { ...@@ -23,7 +23,7 @@ const WalletMenuMobile = () => {
aria-label="wallet menu" aria-label="wallet menu"
icon={ isWalletConnected ? icon={ isWalletConnected ?
<AddressIdenticon size={ 20 } hash={ address }/> : <AddressIdenticon size={ 20 } hash={ address }/> :
<Icon as={ walletIcon } boxSize={ 6 }/> <IconSvg name="wallet" boxSize={ 6 }/>
} }
variant={ isWalletConnected ? 'subtle' : 'outline' } variant={ isWalletConnected ? 'subtle' : 'outline' }
colorScheme="gray" colorScheme="gray"
......
import { Box, Button, Icon, Menu, MenuButton, MenuItemOption, MenuList, MenuOptionGroup, Text } from '@chakra-ui/react'; import { Box, Button, Menu, MenuButton, MenuItemOption, MenuList, MenuOptionGroup, Text } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import eastMiniArrowIcon from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
type Props<T extends string> = { type Props<T extends string> = {
items: Array<{id: T; title: string}>; items: Array<{id: T; title: string}>;
...@@ -39,7 +39,7 @@ export function StatsDropdownMenu<T extends string>({ items, selectedId, onSelec ...@@ -39,7 +39,7 @@ export function StatsDropdownMenu<T extends string>({ items, selectedId, onSelec
> >
{ selectedCategory?.title } { selectedCategory?.title }
</Text> </Text>
<Icon transform="rotate(-90deg)" ml="auto" as={ eastMiniArrowIcon } w={ 5 } h={ 5 }/> <IconSvg transform="rotate(-90deg)" ml="auto" name="arrows/east-mini" w={ 5 } h={ 5 }/>
</Box> </Box>
</MenuButton> </MenuButton>
......
...@@ -3,20 +3,6 @@ import React from 'react'; ...@@ -3,20 +3,6 @@ import React from 'react';
import type { TokenVerifiedInfo } from 'types/api/token'; import type { TokenVerifiedInfo } from 'types/api/token';
import iconCoinGecko from 'icons/social/coingecko.svg';
import iconCoinMarketCap from 'icons/social/coinmarketcap.svg';
import iconDefiLlama from 'icons/social/defi_llama.svg';
import iconDiscord from 'icons/social/discord_filled.svg';
import iconFacebook from 'icons/social/facebook_filled.svg';
import iconGithub from 'icons/social/github_filled.svg';
import iconLinkedIn from 'icons/social/linkedin_filled.svg';
import iconMedium from 'icons/social/medium_filled.svg';
import iconOpenSea from 'icons/social/opensea_filled.svg';
import iconReddit from 'icons/social/reddit_filled.svg';
import iconSlack from 'icons/social/slack_filled.svg';
import iconTelegram from 'icons/social/telegram_filled.svg';
import iconTwitter from 'icons/social/twitter_filled.svg';
import DocsLink from './DocsLink'; import DocsLink from './DocsLink';
import type { Props as ServiceLinkProps } from './ServiceLink'; import type { Props as ServiceLinkProps } from './ServiceLink';
import ServiceLink from './ServiceLink'; import ServiceLink from './ServiceLink';
...@@ -27,22 +13,22 @@ interface Props { ...@@ -27,22 +13,22 @@ interface Props {
} }
const SOCIAL_LINKS: Array<Omit<ServiceLinkProps, 'href'>> = [ const SOCIAL_LINKS: Array<Omit<ServiceLinkProps, 'href'>> = [
{ field: 'github', icon: iconGithub, title: 'Github' }, { field: 'github', icon: 'social/github_filled', title: 'Github' },
{ field: 'twitter', icon: iconTwitter, title: 'Twitter' }, { field: 'twitter', icon: 'social/twitter_filled', title: 'Twitter' },
{ field: 'telegram', icon: iconTelegram, title: 'Telegram' }, { field: 'telegram', icon: 'social/telegram_filled', title: 'Telegram' },
{ field: 'openSea', icon: iconOpenSea, title: 'OpenSea' }, { field: 'openSea', icon: 'social/opensea_filled', title: 'OpenSea' },
{ field: 'linkedin', icon: iconLinkedIn, title: 'LinkedIn' }, { field: 'linkedin', icon: 'social/linkedin_filled', title: 'LinkedIn' },
{ field: 'facebook', icon: iconFacebook, title: 'Facebook' }, { field: 'facebook', icon: 'social/facebook_filled', title: 'Facebook' },
{ field: 'discord', icon: iconDiscord, title: 'Discord' }, { field: 'discord', icon: 'social/discord_filled', title: 'Discord' },
{ field: 'medium', icon: iconMedium, title: 'Medium' }, { field: 'medium', icon: 'social/medium_filled', title: 'Medium' },
{ field: 'slack', icon: iconSlack, title: 'Slack' }, { field: 'slack', icon: 'social/slack_filled', title: 'Slack' },
{ field: 'reddit', icon: iconReddit, title: 'Reddit' }, { field: 'reddit', icon: 'social/reddit_filled', title: 'Reddit' },
]; ];
const PRICE_TICKERS: Array<Omit<ServiceLinkProps, 'href'>> = [ const PRICE_TICKERS: Array<Omit<ServiceLinkProps, 'href'>> = [
{ field: 'coinGeckoTicker', icon: iconCoinGecko, title: 'CoinGecko' }, { field: 'coinGeckoTicker', icon: 'social/coingecko', title: 'CoinGecko' },
{ field: 'coinMarketCapTicker', icon: iconCoinMarketCap, title: 'CoinMarketCap' }, { field: 'coinMarketCapTicker', icon: 'social/coinmarketcap', title: 'CoinMarketCap' },
{ field: 'defiLlamaTicker', icon: iconDefiLlama, title: 'DefiLlama' }, { field: 'defiLlamaTicker', icon: 'social/defi_llama', title: 'DefiLlama' },
]; ];
export function hasContent(data: TokenVerifiedInfo): boolean { export function hasContent(data: TokenVerifiedInfo): boolean {
......
import { Icon, Link } from '@chakra-ui/react'; import { Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconDocs from 'icons/docs.svg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
href: string; href: string;
...@@ -16,7 +16,7 @@ const DocsLink = ({ href }: Props) => { ...@@ -16,7 +16,7 @@ const DocsLink = ({ href }: Props) => {
alignItems="center" alignItems="center"
columnGap={ 1 } columnGap={ 1 }
> >
<Icon as={ iconDocs } boxSize={ 6 } color="text_secondary"/> <IconSvg name="docs" boxSize={ 6 } color="text_secondary"/>
<span>Documentation</span> <span>Documentation</span>
</Link> </Link>
); );
......
import { Link, Icon } from '@chakra-ui/react'; import { Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenVerifiedInfo } from 'types/api/token'; import type { TokenVerifiedInfo } from 'types/api/token';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
export interface Props { export interface Props {
field: keyof TokenVerifiedInfo; field: keyof TokenVerifiedInfo;
icon: React.FunctionComponent<React.SVGAttributes<SVGElement>>; icon: IconName;
title: string; title: string;
href?: string; href?: string;
} }
...@@ -20,7 +23,7 @@ const ServiceLink = ({ href, title, icon }: Props) => { ...@@ -20,7 +23,7 @@ const ServiceLink = ({ href, title, icon }: Props) => {
display="inline-flex" display="inline-flex"
alignItems="center" alignItems="center"
> >
<Icon as={ icon } boxSize={ 5 } mr={ 2 } color="text_secondary"/> <IconSvg name={ icon } boxSize={ 5 } mr={ 2 } color="text_secondary"/>
<span>{ title }</span> <span>{ title }</span>
</Link> </Link>
); );
......
import { Icon, Link } from '@chakra-ui/react'; import { Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconEmail from 'icons/email.svg'; import IconSvg from 'ui/shared/IconSvg';
import iconLink from 'icons/link.svg';
interface Props { interface Props {
url: string; url: string;
...@@ -11,7 +10,6 @@ interface Props { ...@@ -11,7 +10,6 @@ interface Props {
const SupportLink = ({ url }: Props) => { const SupportLink = ({ url }: Props) => {
const isEmail = url.includes('@'); const isEmail = url.includes('@');
const href = isEmail ? `mailto:${ url }` : url; const href = isEmail ? `mailto:${ url }` : url;
const icon = isEmail ? iconEmail : iconLink;
return ( return (
<Link <Link
...@@ -21,7 +19,7 @@ const SupportLink = ({ url }: Props) => { ...@@ -21,7 +19,7 @@ const SupportLink = ({ url }: Props) => {
alignItems="center" alignItems="center"
columnGap={ 1 } columnGap={ 1 }
> >
<Icon as={ icon } boxSize={ 6 } color="text_secondary"/> <IconSvg name={ isEmail ? 'email' : 'link' } boxSize={ 6 } color="text_secondary"/>
<span>{ url }</span> <span>{ url }</span>
</Link> </Link>
); );
......
import { Button, Icon } from '@chakra-ui/react'; import { Button } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import arrowIcon from 'icons/arrows/east-mini.svg'; import IconSvg from 'ui/shared/IconSvg';
import rocketIcon from 'icons/rocket.svg';
interface Props { interface Props {
onClick: () => void; onClick: () => void;
...@@ -22,9 +21,9 @@ const TriggerButton = ({ isOpen, onClick }: Props, ref: React.ForwardedRef<HTMLB ...@@ -22,9 +21,9 @@ const TriggerButton = ({ isOpen, onClick }: Props, ref: React.ForwardedRef<HTMLB
px={ 2 } px={ 2 }
h="32px" h="32px"
> >
<Icon as={ rocketIcon } boxSize={ 5 } mr={ 1 }/> <IconSvg name="rocket" boxSize={ 5 } mr={ 1 }/>
<span>Info</span> <span>Info</span>
<Icon as={ arrowIcon } transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 1 }/> <IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 1 }/>
</Button> </Button>
); );
}; };
......
...@@ -3,14 +3,13 @@ import React from 'react'; ...@@ -3,14 +3,13 @@ import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer'; import type { TokenTransfer } from 'types/api/tokenTransfer';
import eastArrowIcon from 'icons/arrows/east.svg';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntityWithTokenFilter from 'ui/shared/entities/address/AddressEntityWithTokenFilter'; import AddressEntityWithTokenFilter from 'ui/shared/entities/address/AddressEntityWithTokenFilter';
import NftEntity from 'ui/shared/entities/nft/NftEntity'; import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
...@@ -62,7 +61,7 @@ const TokenTransferListItem = ({ ...@@ -62,7 +61,7 @@ const TokenTransferListItem = ({
width="50%" width="50%"
fontWeight="500" fontWeight="500"
/> />
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" flexShrink={ 0 } isLoading={ isLoading }/>
<AddressEntityWithTokenFilter <AddressEntityWithTokenFilter
address={ to } address={ to }
isLoading={ isLoading } isLoading={ isLoading }
......
...@@ -3,14 +3,13 @@ import React from 'react'; ...@@ -3,14 +3,13 @@ import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer'; import type { TokenTransfer } from 'types/api/tokenTransfer';
import eastArrowIcon from 'icons/arrows/east.svg';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntityWithTokenFilter from 'ui/shared/entities/address/AddressEntityWithTokenFilter'; import AddressEntityWithTokenFilter from 'ui/shared/entities/address/AddressEntityWithTokenFilter';
import NftEntity from 'ui/shared/entities/nft/NftEntity'; import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
type Props = TokenTransfer & { tokenId?: string; isLoading?: boolean } type Props = TokenTransfer & { tokenId?: string; isLoading?: boolean }
...@@ -71,9 +70,7 @@ const TokenTransferTableItem = ({ ...@@ -71,9 +70,7 @@ const TokenTransferTableItem = ({
/> />
</Td> </Td>
<Td px={ 0 }> <Td px={ 0 }>
<Box my="3px"> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" mt="3px" isLoading={ isLoading }/>
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
</Box>
</Td> </Td>
<Td> <Td>
<AddressEntityWithTokenFilter <AddressEntityWithTokenFilter
......
import { FormControl, Icon, Input, InputRightElement, InputGroup } from '@chakra-ui/react'; import { FormControl, Input, InputRightElement, InputGroup } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { Control, ControllerProps } from 'react-hook-form'; import type { Control, ControllerProps } from 'react-hook-form';
import { Controller } from 'react-hook-form'; import { Controller } from 'react-hook-form';
import type { Fields, SocialLinkFields } from '../types'; import type { Fields, SocialLinkFields } from '../types';
import iconDiscord from 'icons/social/discord_filled.svg';
import iconFacebook from 'icons/social/facebook_filled.svg';
import iconGithub from 'icons/social/github_filled.svg';
import iconLinkedIn from 'icons/social/linkedin_filled.svg';
import iconMedium from 'icons/social/medium_filled.svg';
import iconOpenSea from 'icons/social/opensea_filled.svg';
import iconReddit from 'icons/social/reddit_filled.svg';
import iconSlack from 'icons/social/slack_filled.svg';
import iconTelegram from 'icons/social/telegram_filled.svg';
import iconTwitter from 'icons/social/twitter_filled.svg';
import { validator } from 'lib/validations/url'; import { validator } from 'lib/validations/url';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
import InputPlaceholder from 'ui/shared/InputPlaceholder'; import InputPlaceholder from 'ui/shared/InputPlaceholder';
interface Item { interface Item {
icon: React.FunctionComponent<React.SVGAttributes<SVGElement>>; icon: IconName;
label: string; label: string;
color: string; color: string;
} }
const SETTINGS: Record<keyof SocialLinkFields, Item> = { const SETTINGS: Record<keyof SocialLinkFields, Item> = {
github: { label: 'GitHub', icon: iconGithub, color: 'inherit' }, github: { label: 'GitHub', icon: 'social/github_filled', color: 'inherit' },
telegram: { label: 'Telegram', icon: iconTelegram, color: 'telegram' }, telegram: { label: 'Telegram', icon: 'social/telegram_filled', color: 'telegram' },
linkedin: { label: 'LinkedIn', icon: iconLinkedIn, color: 'linkedin' }, linkedin: { label: 'LinkedIn', icon: 'social/linkedin_filled', color: 'linkedin' },
discord: { label: 'Discord', icon: iconDiscord, color: 'discord' }, discord: { label: 'Discord', icon: 'social/discord_filled', color: 'discord' },
slack: { label: 'Slack', icon: iconSlack, color: 'slack' }, slack: { label: 'Slack', icon: 'social/slack_filled', color: 'slack' },
twitter: { label: 'Twitter', icon: iconTwitter, color: 'twitter' }, twitter: { label: 'Twitter', icon: 'social/twitter_filled', color: 'twitter' },
opensea: { label: 'OpenSea', icon: iconOpenSea, color: 'opensea' }, opensea: { label: 'OpenSea', icon: 'social/opensea_filled', color: 'opensea' },
facebook: { label: 'Facebook', icon: iconFacebook, color: 'facebook' }, facebook: { label: 'Facebook', icon: 'social/facebook_filled', color: 'facebook' },
medium: { label: 'Medium', icon: iconMedium, color: 'inherit' }, medium: { label: 'Medium', icon: 'social/medium_filled', color: 'inherit' },
reddit: { label: 'Reddit', icon: iconReddit, color: 'reddit' }, reddit: { label: 'Reddit', icon: 'social/reddit_filled', color: 'reddit' },
}; };
interface Props { interface Props {
...@@ -55,7 +47,7 @@ const TokenInfoFieldSocialLink = ({ control, isReadOnly, name }: Props) => { ...@@ -55,7 +47,7 @@ const TokenInfoFieldSocialLink = ({ control, isReadOnly, name }: Props) => {
/> />
<InputPlaceholder text={ SETTINGS[name].label } error={ fieldState.error }/> <InputPlaceholder text={ SETTINGS[name].label } error={ fieldState.error }/>
<InputRightElement h="100%"> <InputRightElement h="100%">
<Icon as={ SETTINGS[name].icon } boxSize={ 6 } color={ field.value ? SETTINGS[name].color : '#718096' }/> <IconSvg name={ SETTINGS[name].icon } boxSize={ 6 } color={ field.value ? SETTINGS[name].color : '#718096' }/>
</InputRightElement> </InputRightElement>
</InputGroup> </InputGroup>
</FormControl> </FormControl>
......
import { Icon, Link, Table, Tbody, Th, Tr } from '@chakra-ui/react'; import { Link, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
import type { TokensSortingField, TokensSortingValue } from 'types/api/tokens'; import type { TokensSortingField, TokensSortingValue } from 'types/api/tokens';
import rightArrowIcon from 'icons/arrows/east.svg'; import IconSvg from 'ui/shared/IconSvg';
import { default as getNextSortValueShared } from 'ui/shared/sort/getNextSortValue'; import { default as getNextSortValueShared } from 'ui/shared/sort/getNextSortValue';
import { default as Thead } from 'ui/shared/TheadSticky'; import { default as Thead } from 'ui/shared/TheadSticky';
...@@ -41,19 +41,19 @@ const TokensTable = ({ items, page, isLoading, sorting, setSorting }: Props) => ...@@ -41,19 +41,19 @@ const TokensTable = ({ items, page, isLoading, sorting, setSorting }: Props) =>
<Th w="50%">Token</Th> <Th w="50%">Token</Th>
<Th isNumeric w="15%"> <Th isNumeric w="15%">
<Link onClick={ sort('fiat_value') } display="flex" justifyContent="end"> <Link onClick={ sort('fiat_value') } display="flex" justifyContent="end">
{ sorting?.includes('fiat_value') && <Icon as={ rightArrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sorting?.includes('fiat_value') && <IconSvg name="arrows/east-mini" boxSize={ 4 } transform={ sortIconTransform }/> }
Price Price
</Link> </Link>
</Th> </Th>
<Th isNumeric w="20%"> <Th isNumeric w="20%">
<Link onClick={ sort('circulating_market_cap') } display="flex" justifyContent="end"> <Link onClick={ sort('circulating_market_cap') } display="flex" justifyContent="end">
{ sorting?.includes('circulating_market_cap') && <Icon as={ rightArrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sorting?.includes('circulating_market_cap') && <IconSvg name="arrows/east-mini" boxSize={ 4 } transform={ sortIconTransform }/> }
On-chain market cap On-chain market cap
</Link> </Link>
</Th> </Th>
<Th isNumeric w="15%"> <Th isNumeric w="15%">
<Link onClick={ sort('holder_count') } display="flex" justifyContent="end"> <Link onClick={ sort('holder_count') } display="flex" justifyContent="end">
{ sorting?.includes('holder_count') && <Icon as={ rightArrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sorting?.includes('holder_count') && <IconSvg name="arrows/east-mini" boxSize={ 4 } transform={ sortIconTransform }/> }
Holders Holders
</Link> </Link>
</Th> </Th>
......
...@@ -51,7 +51,13 @@ const TokensTableItem = ({ ...@@ -51,7 +51,13 @@ const TokensTableItem = ({
}; };
return ( return (
<Tr> <Tr
sx={{
'&:hover [aria-label="Add token to wallet"]': {
opacity: 1,
},
}}
>
<Td> <Td>
<Flex alignItems="flex-start"> <Flex alignItems="flex-start">
<Skeleton <Skeleton
...@@ -81,7 +87,12 @@ const TokensTableItem = ({ ...@@ -81,7 +87,12 @@ const TokensTableItem = ({
fontSize="sm" fontSize="sm"
fontWeight={ 500 } fontWeight={ 500 }
/> />
<AddressAddToWallet token={ token } isLoading={ isLoading } iconSize={ 5 }/> <AddressAddToWallet
token={ token }
isLoading={ isLoading }
iconSize={ 5 }
opacity={ 0 }
/>
</Flex> </Flex>
<Flex columnGap={ 1 }> <Flex columnGap={ 1 }>
<Tag isLoading={ isLoading }>{ type }</Tag> <Tag isLoading={ isLoading }>{ type }</Tag>
......
...@@ -3,7 +3,6 @@ import { ...@@ -3,7 +3,6 @@ import {
GridItem, GridItem,
Text, Text,
Box, Box,
Icon as ChakraIcon,
Link, Link,
Spinner, Spinner,
Flex, Flex,
...@@ -22,15 +21,10 @@ import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction'; ...@@ -22,15 +21,10 @@ import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import clockIcon from 'icons/clock.svg';
import flameIcon from 'icons/flame.svg';
import errorIcon from 'icons/status/error.svg';
import successIcon from 'icons/status/success.svg';
import { WEI, WEI_IN_GWEI } from 'lib/consts'; import { WEI, WEI_IN_GWEI } from 'lib/consts';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import getConfirmationDuration from 'lib/tx/getConfirmationDuration'; import getConfirmationDuration from 'lib/tx/getConfirmationDuration';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import CurrencyValue from 'ui/shared/CurrencyValue'; import CurrencyValue from 'ui/shared/CurrencyValue';
...@@ -42,6 +36,7 @@ import AddressEntity from 'ui/shared/entities/address/AddressEntity'; ...@@ -42,6 +36,7 @@ import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import ZkEvmBatchEntityL2 from 'ui/shared/entities/block/ZkEvmBatchEntityL2'; import ZkEvmBatchEntityL2 from 'ui/shared/entities/block/ZkEvmBatchEntityL2';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LogDecodedInputData from 'ui/shared/logs/LogDecodedInputData'; import LogDecodedInputData from 'ui/shared/logs/LogDecodedInputData';
import RawInputData from 'ui/shared/RawInputData'; import RawInputData from 'ui/shared/RawInputData';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
...@@ -108,14 +103,14 @@ const TxDetails = () => { ...@@ -108,14 +103,14 @@ const TxDetails = () => {
const executionSuccessBadge = toAddress?.is_contract && data.result === 'success' ? ( const executionSuccessBadge = toAddress?.is_contract && data.result === 'success' ? (
<Tooltip label="Contract execution completed"> <Tooltip label="Contract execution completed">
<chakra.span display="inline-flex" ml={ 2 } mr={ 1 }> <chakra.span display="inline-flex" ml={ 2 } mr={ 1 }>
<ChakraIcon as={ successIcon } boxSize={ 4 } color={ executionSuccessIconColor } cursor="pointer"/> <IconSvg name="status/success" boxSize={ 4 } color={ executionSuccessIconColor } cursor="pointer"/>
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
) : null; ) : null;
const executionFailedBadge = toAddress?.is_contract && Boolean(data.status) && data.result !== 'success' ? ( const executionFailedBadge = toAddress?.is_contract && Boolean(data.status) && data.result !== 'success' ? (
<Tooltip label="Error occurred during contract execution"> <Tooltip label="Error occurred during contract execution">
<chakra.span display="inline-flex" ml={ 2 } mr={ 1 }> <chakra.span display="inline-flex" ml={ 2 } mr={ 1 }>
<ChakraIcon as={ errorIcon } boxSize={ 4 } color="error" cursor="pointer"/> <IconSvg name="status/error" boxSize={ 4 } color="error" cursor="pointer"/>
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
) : null; ) : null;
...@@ -218,7 +213,7 @@ const TxDetails = () => { ...@@ -218,7 +213,7 @@ const TxDetails = () => {
hint="Date & time of transaction inclusion, including length of time for confirmation" hint="Date & time of transaction inclusion, including length of time for confirmation"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/> <IconSvg name="clock" boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
<Skeleton isLoaded={ !isPlaceholderData } ml={ 2 }>{ dayjs(data.timestamp).fromNow() }</Skeleton> <Skeleton isLoaded={ !isPlaceholderData } ml={ 2 }>{ dayjs(data.timestamp).fromNow() }</Skeleton>
<TextSeparator/> <TextSeparator/>
<Skeleton isLoaded={ !isPlaceholderData } whiteSpace="normal">{ dayjs(data.timestamp).format('llll') }</Skeleton> <Skeleton isLoaded={ !isPlaceholderData } whiteSpace="normal">{ dayjs(data.timestamp).format('llll') }</Skeleton>
...@@ -434,7 +429,7 @@ const TxDetails = () => { ...@@ -434,7 +429,7 @@ const TxDetails = () => {
title="Burnt fees" title="Burnt fees"
hint={ `Amount of ${ config.chain.currency.symbol } burned for this transaction. Equals Block Base Fee per Gas * Gas Used` } hint={ `Amount of ${ config.chain.currency.symbol } burned for this transaction. Equals Block Base Fee per Gas * Gas Used` }
> >
<Icon as={ flameIcon } boxSize={ 5 } color="gray.500"/> <IconSvg name="flame" boxSize={ 5 } color="gray.500"/>
<CurrencyValue <CurrencyValue
value={ String(data.tx_burnt_fee) } value={ String(data.tx_burnt_fee) }
currency={ config.chain.currency.symbol } currency={ config.chain.currency.symbol }
......
import { Flex, Icon, chakra } from '@chakra-ui/react'; import { Flex, chakra } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { TxAction, TxActionGeneral } from 'types/api/txAction'; import type { TxAction, TxActionGeneral } from 'types/api/txAction';
import config from 'configs/app'; import config from 'configs/app';
import uniswapIcon from 'icons/uniswap.svg';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import NftEntity from 'ui/shared/entities/nft/NftEntity'; import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
action: TxAction; action: TxAction;
...@@ -88,7 +88,7 @@ const TxDetailsAction = ({ action }: Props) => { ...@@ -88,7 +88,7 @@ const TxDetailsAction = ({ action }: Props) => {
<chakra.span color="text_secondary">{ text1 }</chakra.span> <chakra.span color="text_secondary">{ text1 }</chakra.span>
<Flex columnGap={ 2 }> <Flex columnGap={ 2 }>
<Icon as={ uniswapIcon } boxSize={ 5 } color="white" bgColor="#ff007a" borderRadius="full" p="2px"/> <IconSvg name="uniswap" boxSize={ 5 } color="white" bgColor="#ff007a" borderRadius="full" p="2px"/>
<chakra.span>Uniswap V3</chakra.span> <chakra.span>Uniswap V3</chakra.span>
</Flex> </Flex>
</Flex> </Flex>
......
import { Flex, Icon, chakra } from '@chakra-ui/react'; import { Flex, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenTransfer as TTokenTransfer, Erc20TotalPayload, Erc721TotalPayload, Erc1155TotalPayload } from 'types/api/tokenTransfer'; import type { TokenTransfer as TTokenTransfer, Erc20TotalPayload, Erc721TotalPayload, Erc1155TotalPayload } from 'types/api/tokenTransfer';
import rightArrowIcon from 'icons/arrows/east.svg';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
import NftTokenTransferSnippet from 'ui/tx/NftTokenTransferSnippet'; import NftTokenTransferSnippet from 'ui/tx/NftTokenTransferSnippet';
interface Props { interface Props {
...@@ -77,7 +77,7 @@ const TxDetailsTokenTransfer = ({ data }: Props) => { ...@@ -77,7 +77,7 @@ const TxDetailsTokenTransfer = ({ data }: Props) => {
> >
<Flex alignItems="center" fontWeight="500"> <Flex alignItems="center" fontWeight="500">
<AddressEntity address={ data.from } truncation="constant" noIcon maxW="150px"/> <AddressEntity address={ data.from } truncation="constant" noIcon maxW="150px"/>
<Icon as={ rightArrowIcon } boxSize={ 5 } mx={ 2 } color="gray.500"/> <IconSvg name="arrows/east" boxSize={ 5 } mx={ 2 } color="gray.500"/>
<AddressEntity address={ data.to } truncation="constant" noIcon maxW="150px"/> <AddressEntity address={ data.to } truncation="constant" noIcon maxW="150px"/>
</Flex> </Flex>
<Flex flexDir="column" rowGap={ 5 } w="100%" overflow="hidden" fontWeight={ 500 }> <Flex flexDir="column" rowGap={ 5 } w="100%" overflow="hidden" fontWeight={ 500 }>
......
import { Icon, GridItem, Show, Flex } from '@chakra-ui/react'; import { GridItem, Show, Flex } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer'; import type { TokenTransfer } from 'types/api/tokenTransfer';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import tokenIcon from 'icons/token.svg';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import TxDetailsTokenTransfer from './TxDetailsTokenTransfer'; import TxDetailsTokenTransfer from './TxDetailsTokenTransfer';
...@@ -62,7 +62,7 @@ const TxDetailsTokenTransfers = ({ data, txHash, isOverflow }: Props) => { ...@@ -62,7 +62,7 @@ const TxDetailsTokenTransfers = ({ data, txHash, isOverflow }: Props) => {
<> <>
<Show above="lg" ssr={ false }><GridItem></GridItem></Show> <Show above="lg" ssr={ false }><GridItem></GridItem></Show>
<GridItem fontSize="sm" alignItems="center" display="inline-flex" pl={{ base: '28px', lg: 0 }}> <GridItem fontSize="sm" alignItems="center" display="inline-flex" pl={{ base: '28px', lg: 0 }}>
<Icon as={ tokenIcon } boxSize={ 6 }/> <IconSvg name="token" boxSize={ 6 }/>
<LinkInternal href={ viewAllUrl }> <LinkInternal href={ viewAllUrl }>
View all View all
</LinkInternal> </LinkInternal>
......
...@@ -5,10 +5,9 @@ import React from 'react'; ...@@ -5,10 +5,9 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction'; import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app'; import config from 'configs/app';
import eastArrowIcon from 'icons/arrows/east.svg';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import IconSvg from 'ui/shared/IconSvg';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils'; import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
...@@ -31,7 +30,7 @@ const TxInternalsListItem = ({ type, from, to, value, success, error, gas_limit: ...@@ -31,7 +30,7 @@ const TxInternalsListItem = ({ type, from, to, value, success, error, gas_limit:
isLoading={ isLoading } isLoading={ isLoading }
width="calc((100% - 48px) / 2)" width="calc((100% - 48px) / 2)"
/> />
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
{ toData && ( { toData && (
<AddressEntity <AddressEntity
address={ toData } address={ toData }
......
import { Table, Tbody, Tr, Th, Link, Icon } from '@chakra-ui/react'; import { Table, Tbody, Tr, Th, Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction'; import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app'; import config from 'configs/app';
import arrowIcon from 'icons/arrows/east.svg';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight'; import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import IconSvg from 'ui/shared/IconSvg';
import { default as Thead } from 'ui/shared/TheadSticky'; import { default as Thead } from 'ui/shared/TheadSticky';
import TxInternalsTableItem from 'ui/tx/internals/TxInternalsTableItem'; import TxInternalsTableItem from 'ui/tx/internals/TxInternalsTableItem';
import type { Sort, SortField } from 'ui/tx/internals/utils'; import type { Sort, SortField } from 'ui/tx/internals/utils';
...@@ -32,13 +32,13 @@ const TxInternalsTable = ({ data, sort, onSortToggle, top, isLoading }: Props) = ...@@ -32,13 +32,13 @@ const TxInternalsTable = ({ data, sort, onSortToggle, top, isLoading }: Props) =
<Th width="20%">To</Th> <Th width="20%">To</Th>
<Th width="16%" isNumeric> <Th width="16%" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('value') } columnGap={ 1 }> <Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('value') } columnGap={ 1 }>
{ sort?.includes('value') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sort?.includes('value') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Value { config.chain.currency.symbol } Value { config.chain.currency.symbol }
</Link> </Link>
</Th> </Th>
<Th width="16%" isNumeric> <Th width="16%" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('gas-limit') } columnGap={ 1 }> <Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ onSortToggle('gas-limit') } columnGap={ 1 }>
{ sort?.includes('gas-limit') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sort?.includes('gas-limit') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Gas limit { config.chain.currency.symbol } Gas limit { config.chain.currency.symbol }
</Link> </Link>
</Th> </Th>
......
...@@ -5,10 +5,9 @@ import React from 'react'; ...@@ -5,10 +5,9 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction'; import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import IconSvg from 'ui/shared/IconSvg';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils'; import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
...@@ -39,7 +38,7 @@ const TxInternalTableItem = ({ type, from, to, value, success, error, gas_limit: ...@@ -39,7 +38,7 @@ const TxInternalTableItem = ({ type, from, to, value, success, error, gas_limit:
/> />
</Td> </Td>
<Td px={ 0 } verticalAlign="middle"> <Td px={ 0 } verticalAlign="middle">
<Icon as={ rightArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading } display="block"/>
</Td> </Td>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
{ toData && ( { toData && (
......
import { import {
HStack, HStack,
Box,
Flex, Flex,
Skeleton, Skeleton,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
...@@ -9,14 +8,13 @@ import React from 'react'; ...@@ -9,14 +8,13 @@ import React from 'react';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import getValueWithUnit from 'lib/getValueWithUnit'; import getValueWithUnit from 'lib/getValueWithUnit';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import { space } from 'lib/html-entities'; import { space } from 'lib/html-entities';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
...@@ -102,14 +100,14 @@ const TxsListItem = ({ tx, isLoading, showBlockInfo, currentAddress, enableTimeI ...@@ -102,14 +100,14 @@ const TxsListItem = ({ tx, isLoading, showBlockInfo, currentAddress, enableTimeI
/> />
{ (isIn || isOut) ? { (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } width="48px" mx={ 2 } isLoading={ isLoading }/> : ( <InOutTag isIn={ isIn } isOut={ isOut } width="48px" mx={ 2 } isLoading={ isLoading }/> : (
<Box mx={ 2 }> <IconSvg
<Icon name="arrows/east"
as={ rightArrowIcon }
boxSize={ 6 } boxSize={ 6 }
color="gray.500" color="gray.500"
isLoading={ isLoading } isLoading={ isLoading }
mx={ 2 }
flexShrink={ 0 }
/> />
</Box>
) } ) }
{ dataTo ? ( { dataTo ? (
<AddressEntity <AddressEntity
......
import { Link, Table, Tbody, Tr, Th, Icon, Show, Hide } from '@chakra-ui/react'; import { Link, Table, Tbody, Tr, Th, Show, Hide } from '@chakra-ui/react';
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import React from 'react'; import React from 'react';
import type { Transaction, TransactionsSortingField, TransactionsSortingValue } from 'types/api/transaction'; import type { Transaction, TransactionsSortingField, TransactionsSortingValue } from 'types/api/transaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight'; import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import IconSvg from 'ui/shared/IconSvg';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice'; import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import TheadSticky from 'ui/shared/TheadSticky'; import TheadSticky from 'ui/shared/TheadSticky';
...@@ -60,8 +60,8 @@ const TxsTable = ({ ...@@ -60,8 +60,8 @@ const TxsTable = ({
{ !config.UI.views.tx.hiddenFields?.value && ( { !config.UI.views.tx.hiddenFields?.value && (
<Th width="20%" isNumeric> <Th width="20%" isNumeric>
<Link onClick={ sort('value') } display="flex" justifyContent="end"> <Link onClick={ sort('value') } display="flex" justifyContent="end">
{ sorting === 'value-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> } { sorting === 'value-asc' && <IconSvg boxSize={ 5 } name="arrows/east" transform="rotate(-90deg)"/> }
{ sorting === 'value-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> } { sorting === 'value-desc' && <IconSvg boxSize={ 5 } name="arrows/east" transform="rotate(90deg)"/> }
{ `Value ${ config.chain.currency.symbol }` } { `Value ${ config.chain.currency.symbol }` }
</Link> </Link>
</Th> </Th>
...@@ -69,8 +69,8 @@ const TxsTable = ({ ...@@ -69,8 +69,8 @@ const TxsTable = ({
{ !config.UI.views.tx.hiddenFields?.tx_fee && ( { !config.UI.views.tx.hiddenFields?.tx_fee && (
<Th width="20%" isNumeric pr={ 5 }> <Th width="20%" isNumeric pr={ 5 }>
<Link onClick={ sort('fee') } display="flex" justifyContent="end"> <Link onClick={ sort('fee') } display="flex" justifyContent="end">
{ sorting === 'fee-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> } { sorting === 'fee-asc' && <IconSvg boxSize={ 5 } name="arrows/east" transform="rotate(-90deg)"/> }
{ sorting === 'fee-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> } { sorting === 'fee-desc' && <IconSvg boxSize={ 5 } name="arrows/east" transform="rotate(90deg)"/> }
{ `Fee${ config.UI.views.tx.hiddenFields?.fee_currency ? '' : ` ${ config.chain.currency.symbol }` }` } { `Fee${ config.UI.views.tx.hiddenFields?.fee_currency ? '' : ` ${ config.chain.currency.symbol }` }` }
</Link> </Link>
</Th> </Th>
......
...@@ -14,14 +14,13 @@ import React from 'react'; ...@@ -14,14 +14,13 @@ import React from 'react';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import config from 'configs/app'; import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement'; import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag'; import Tag from 'ui/shared/chakra/Tag';
import CurrencyValue from 'ui/shared/CurrencyValue'; import CurrencyValue from 'ui/shared/CurrencyValue';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import IconSvg from 'ui/shared/IconSvg';
import InOutTag from 'ui/shared/InOutTag'; import InOutTag from 'ui/shared/InOutTag';
import TxStatus from 'ui/shared/statusTag/TxStatus'; import TxStatus from 'ui/shared/statusTag/TxStatus';
import TxFeeStability from 'ui/shared/tx/TxFeeStability'; import TxFeeStability from 'ui/shared/tx/TxFeeStability';
...@@ -131,7 +130,7 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement, ...@@ -131,7 +130,7 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
{ (isIn || isOut) ? { (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } width="48px" mr={ 2 } isLoading={ isLoading }/> : ( <InOutTag isIn={ isIn } isOut={ isOut } width="48px" mr={ 2 } isLoading={ isLoading }/> : (
<Box mx="6px"> <Box mx="6px">
<Icon as={ rightArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/> <IconSvg name="arrows/east" boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
</Box> </Box>
) } ) }
</Td> </Td>
...@@ -144,8 +143,8 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement, ...@@ -144,8 +143,8 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement,
<Flex alignItems="center"> <Flex alignItems="center">
{ (isIn || isOut) ? { (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } width="48px" isLoading={ isLoading }/> : ( <InOutTag isIn={ isIn } isOut={ isOut } width="48px" isLoading={ isLoading }/> : (
<Icon <IconSvg
as={ rightArrowIcon } name="arrows/east"
boxSize={ 6 } boxSize={ 6 }
color="gray.500" color="gray.500"
transform="rotate(90deg)" transform="rotate(90deg)"
......
...@@ -3,11 +3,10 @@ import React from 'react'; ...@@ -3,11 +3,10 @@ import React from 'react';
import type { TokenInfoApplication, VerifiedAddress } from 'types/api/account'; import type { TokenInfoApplication, VerifiedAddress } from 'types/api/account';
import editIcon from 'icons/edit.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid'; import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
import VerifiedAddressesStatus from './VerifiedAddressesStatus'; import VerifiedAddressesStatus from './VerifiedAddressesStatus';
...@@ -71,7 +70,7 @@ const VerifiedAddressesListItem = ({ item, application, onAdd, onEdit, isLoading ...@@ -71,7 +70,7 @@ const VerifiedAddressesListItem = ({ item, application, onAdd, onEdit, isLoading
borderRadius="none" borderRadius="none"
flexShrink={ 0 } flexShrink={ 0 }
onClick={ handleEditClick } onClick={ handleEditClick }
icon={ <Icon as={ editIcon }/> } icon={ <IconSvg name="edit" boxSize={ 4 } flexShrink={ 0 }/> }
/> />
</Tooltip> </Tooltip>
</> </>
......
...@@ -3,11 +3,10 @@ import React from 'react'; ...@@ -3,11 +3,10 @@ import React from 'react';
import type { TokenInfoApplication, VerifiedAddress } from 'types/api/account'; import type { TokenInfoApplication, VerifiedAddress } from 'types/api/account';
import editIcon from 'icons/edit.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
import VerifiedAddressesStatus from './VerifiedAddressesStatus'; import VerifiedAddressesStatus from './VerifiedAddressesStatus';
...@@ -87,7 +86,7 @@ const VerifiedAddressesTableItem = ({ item, application, onAdd, onEdit, isLoadin ...@@ -87,7 +86,7 @@ const VerifiedAddressesTableItem = ({ item, application, onAdd, onEdit, isLoadin
borderRadius="none" borderRadius="none"
flexShrink={ 0 } flexShrink={ 0 }
onClick={ handleEditClick } onClick={ handleEditClick }
icon={ <Icon as={ editIcon }/> } icon={ <IconSvg name="edit" boxSize={ 4 } flexShrink={ 0 }/> }
/> />
</Tooltip> </Tooltip>
) : null } ) : null }
......
...@@ -5,14 +5,11 @@ import React from 'react'; ...@@ -5,14 +5,11 @@ import React from 'react';
import type { VerifiedContract } from 'types/api/contracts'; import type { VerifiedContract } from 'types/api/contracts';
import config from 'configs/app'; import config from 'configs/app';
import iconCheck from 'icons/check.svg';
import iconCross from 'icons/cross.svg';
import iconSuccess from 'icons/status/success.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import HashStringShorten from 'ui/shared/HashStringShorten'; import HashStringShorten from 'ui/shared/HashStringShorten';
import IconSvg from 'ui/shared/IconSvg';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
interface Props { interface Props {
...@@ -61,19 +58,19 @@ const VerifiedContractsListItem = ({ data, isLoading }: Props) => { ...@@ -61,19 +58,19 @@ const VerifiedContractsListItem = ({ data, isLoading }: Props) => {
<Flex columnGap={ 3 }> <Flex columnGap={ 3 }>
<Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Optimization</Skeleton> <Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Optimization</Skeleton>
{ data.optimization_enabled ? { data.optimization_enabled ?
<Icon as={ iconCheck } boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> : <IconSvg name="check" boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> :
<Icon as={ iconCross } boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> } <IconSvg name="cross" boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> }
</Flex> </Flex>
<Flex columnGap={ 3 }> <Flex columnGap={ 3 }>
<Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Constructor args</Skeleton> <Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Constructor args</Skeleton>
{ data.has_constructor_args ? { data.has_constructor_args ?
<Icon as={ iconCheck } boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> : <IconSvg name="check" boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> :
<Icon as={ iconCross } boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> } <IconSvg name="cross" boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> }
</Flex> </Flex>
<Flex columnGap={ 3 }> <Flex columnGap={ 3 }>
<Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Verified</Skeleton> <Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Verified</Skeleton>
<Flex alignItems="center" columnGap={ 2 }> <Flex alignItems="center" columnGap={ 2 }>
<Icon as={ iconSuccess } boxSize={ 4 } color="green.500" isLoading={ isLoading }/> <IconSvg name="status/success" boxSize={ 4 } color="green.500" isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } color="text_secondary"> <Skeleton isLoaded={ !isLoading } color="text_secondary">
<span>{ dayjs(data.verified_at).fromNow() }</span> <span>{ dayjs(data.verified_at).fromNow() }</span>
</Skeleton> </Skeleton>
......
import { Table, Tbody, Tr, Th, Link, Icon } from '@chakra-ui/react'; import { Table, Tbody, Tr, Th, Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { VerifiedContract } from 'types/api/contracts'; import type { VerifiedContract } from 'types/api/contracts';
import type { VerifiedContractsSorting, VerifiedContractsSortingField, VerifiedContractsSortingValue } from 'types/api/verifiedContracts'; import type { VerifiedContractsSorting, VerifiedContractsSortingField, VerifiedContractsSortingValue } from 'types/api/verifiedContracts';
import config from 'configs/app'; import config from 'configs/app';
import arrowIcon from 'icons/arrows/east.svg'; import IconSvg from 'ui/shared/IconSvg';
import getNextSortValue from 'ui/shared/sort/getNextSortValue'; import getNextSortValue from 'ui/shared/sort/getNextSortValue';
import { default as Thead } from 'ui/shared/TheadSticky'; import { default as Thead } from 'ui/shared/TheadSticky';
import { SORT_SEQUENCE } from 'ui/verifiedContracts/utils'; import { SORT_SEQUENCE } from 'ui/verifiedContracts/utils';
...@@ -34,13 +34,13 @@ const VerifiedContractsTable = ({ data, sort, setSorting, isLoading }: Props) => ...@@ -34,13 +34,13 @@ const VerifiedContractsTable = ({ data, sort, setSorting, isLoading }: Props) =>
<Th width="50%">Contract</Th> <Th width="50%">Contract</Th>
<Th width="130px" isNumeric> <Th width="130px" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('balance') } columnGap={ 1 }> <Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('balance') } columnGap={ 1 }>
{ sort?.includes('balance') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sort?.includes('balance') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Balance { config.chain.currency.symbol } Balance { config.chain.currency.symbol }
</Link> </Link>
</Th> </Th>
<Th width="130px" isNumeric> <Th width="130px" isNumeric>
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('txs_count') } columnGap={ 1 }> <Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('txs_count') } columnGap={ 1 }>
{ sort?.includes('txs_count') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> } { sort?.includes('txs_count') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Txs Txs
</Link> </Link>
</Th> </Th>
......
...@@ -5,14 +5,11 @@ import React from 'react'; ...@@ -5,14 +5,11 @@ import React from 'react';
import type { VerifiedContract } from 'types/api/contracts'; import type { VerifiedContract } from 'types/api/contracts';
import config from 'configs/app'; import config from 'configs/app';
import iconCheck from 'icons/check.svg';
import iconCross from 'icons/cross.svg';
import iconSuccess from 'icons/status/success.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import HashStringShorten from 'ui/shared/HashStringShorten'; import HashStringShorten from 'ui/shared/HashStringShorten';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
data: VerifiedContract; data: VerifiedContract;
...@@ -63,21 +60,21 @@ const VerifiedContractsTableItem = ({ data, isLoading }: Props) => { ...@@ -63,21 +60,21 @@ const VerifiedContractsTableItem = ({ data, isLoading }: Props) => {
<Tooltip label={ isLoading ? undefined : 'Optimization' }> <Tooltip label={ isLoading ? undefined : 'Optimization' }>
<chakra.span display="inline-block"> <chakra.span display="inline-block">
{ data.optimization_enabled ? { data.optimization_enabled ?
<Icon as={ iconCheck } boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> : <IconSvg name="check" boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> :
<Icon as={ iconCross } boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> } <IconSvg name="cross" boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> }
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
<Tooltip label={ isLoading ? undefined : 'Constructor args' }> <Tooltip label={ isLoading ? undefined : 'Constructor args' }>
<chakra.span display="inline-block" ml={ 2 }> <chakra.span display="inline-block" ml={ 2 }>
{ data.has_constructor_args ? { data.has_constructor_args ?
<Icon as={ iconCheck } boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> : <IconSvg name="check" boxSize={ 6 } color="green.500" cursor="pointer" isLoading={ isLoading }/> :
<Icon as={ iconCross } boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> } <IconSvg name="cross" boxSize={ 6 } color="red.600" cursor="pointer" isLoading={ isLoading }/> }
</chakra.span> </chakra.span>
</Tooltip> </Tooltip>
</Td> </Td>
<Td> <Td>
<Flex alignItems="center" columnGap={ 2 } my={ 1 }> <Flex alignItems="center" columnGap={ 2 } my={ 1 }>
<Icon as={ iconSuccess } boxSize={ 4 } color="green.500" isLoading={ isLoading }/> <IconSvg name="status/success" boxSize={ 4 } color="green.500" isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } color="text_secondary"> <Skeleton isLoaded={ !isLoading } color="text_secondary">
<span>{ dayjs(data.verified_at).fromNow() }</span> <span>{ dayjs(data.verified_at).fromNow() }</span>
</Skeleton> </Skeleton>
......
...@@ -5,14 +5,12 @@ import React from 'react'; ...@@ -5,14 +5,12 @@ import React from 'react';
import type { WatchlistAddress } from 'types/api/account'; import type { WatchlistAddress } from 'types/api/account';
import config from 'configs/app'; import config from 'configs/app';
import TokensIcon from 'icons/tokens.svg';
import WalletIcon from 'icons/wallet.svg';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import { nbsp } from 'lib/html-entities'; import { nbsp } from 'lib/html-entities';
import Icon from 'ui/shared/chakra/Icon';
import CurrencyValue from 'ui/shared/CurrencyValue'; import CurrencyValue from 'ui/shared/CurrencyValue';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity'; import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isLoading?: boolean }) => { const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isLoading?: boolean }) => {
const nativeTokenData = React.useMemo(() => ({ const nativeTokenData = React.useMemo(() => ({
...@@ -51,7 +49,7 @@ const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isL ...@@ -51,7 +49,7 @@ const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isL
</Flex> </Flex>
{ item.tokens_count && ( { item.tokens_count && (
<HStack spacing={ 2 } fontSize="sm" pl={ 7 }> <HStack spacing={ 2 } fontSize="sm" pl={ 7 }>
<Icon as={ TokensIcon } boxSize={ 5 } isLoading={ isLoading } borderRadius="sm"/> <IconSvg name="tokens" boxSize={ 5 } isLoading={ isLoading } borderRadius="sm"/>
<Skeleton isLoaded={ !isLoading } display="inline-flex"> <Skeleton isLoaded={ !isLoading } display="inline-flex">
<span>{ `Tokens:${ nbsp }` + item.tokens_count + (item.tokens_overflow ? '+' : '') }</span> <span>{ `Tokens:${ nbsp }` + item.tokens_count + (item.tokens_overflow ? '+' : '') }</span>
<Text variant="secondary" fontWeight={ 400 }>{ `${ nbsp }($${ BigNumber(item.tokens_fiat_value).toFormat(2) })` }</Text> <Text variant="secondary" fontWeight={ 400 }>{ `${ nbsp }($${ BigNumber(item.tokens_fiat_value).toFormat(2) })` }</Text>
...@@ -60,7 +58,7 @@ const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isL ...@@ -60,7 +58,7 @@ const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isL
) } ) }
{ item.tokens_fiat_value && ( { item.tokens_fiat_value && (
<HStack spacing={ 2 } fontSize="sm" pl={ 7 }> <HStack spacing={ 2 } fontSize="sm" pl={ 7 }>
<Icon boxSize={ 5 } as={ WalletIcon } isLoading={ isLoading }/> <IconSvg boxSize={ 5 } name="wallet" isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } display="inline-flex"> <Skeleton isLoaded={ !isLoading } display="inline-flex">
<Text>{ `Net worth:${ nbsp }` } <Text>{ `Net worth:${ nbsp }` }
{ {
......
...@@ -8,16 +8,15 @@ import type { ZkEvmL2TxnBatch } from 'types/api/zkEvmL2TxnBatches'; ...@@ -8,16 +8,15 @@ import type { ZkEvmL2TxnBatch } from 'types/api/zkEvmL2TxnBatches';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import clockIcon from 'icons/clock.svg';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider'; import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1'; import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import PrevNext from 'ui/shared/PrevNext'; import PrevNext from 'ui/shared/PrevNext';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
...@@ -92,7 +91,7 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -92,7 +91,7 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
title="Timestamp" title="Timestamp"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/> <IconSvg name="clock" boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
<Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }> <Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }>
{ dayjs(data.timestamp).fromNow() } { dayjs(data.timestamp).fromNow() }
</Skeleton> </Skeleton>
......
...@@ -1223,6 +1223,13 @@ ...@@ -1223,6 +1223,13 @@
dependencies: dependencies:
regenerator-runtime "^0.13.11" regenerator-runtime "^0.13.11"
"@babel/runtime@^7.23.5":
version "7.23.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d"
integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.8.4": "@babel/runtime@^7.8.4":
version "7.20.1" version "7.20.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
...@@ -2125,6 +2132,23 @@ ...@@ -2125,6 +2132,23 @@
resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.0.15.tgz#60df64e0ab97d95fee4e6c61ccabd15fd5ace398" resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.0.15.tgz#60df64e0ab97d95fee4e6c61ccabd15fd5ace398"
integrity sha512-WWULIiucYRBIewHKFA7BssQ2ABLHLVd9lrUo3N3SZgR0u4ZRDDVEUNOy+r+9ruDze8+36dGbN9wsN1IdELtdOw== integrity sha512-WWULIiucYRBIewHKFA7BssQ2ABLHLVd9lrUo3N3SZgR0u4ZRDDVEUNOy+r+9ruDze8+36dGbN9wsN1IdELtdOw==
"@clack/core@^0.3.3":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@clack/core/-/core-0.3.3.tgz#233ccebf779aa5a66fc68ee48df5e58cd226fd94"
integrity sha512-5ZGyb75BUBjlll6eOa1m/IZBxwk91dooBWhPSL67sWcLS0zt9SnswRL0l26TVdBhb0wnWORRxUn//uH6n4z7+A==
dependencies:
picocolors "^1.0.0"
sisteransi "^1.0.5"
"@clack/prompts@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@clack/prompts/-/prompts-0.7.0.tgz#6aaef48ea803d91cce12bc80811cfcb8de2e75ea"
integrity sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==
dependencies:
"@clack/core" "^0.3.3"
picocolors "^1.0.0"
sisteransi "^1.0.5"
"@coinbase/wallet-sdk@^3.6.6": "@coinbase/wallet-sdk@^3.6.6":
version "3.6.6" version "3.6.6"
resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.6.6.tgz#4a0758fe0fe0ba3ed7e33b5bb6eb094ff8bd6c98" resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.6.6.tgz#4a0758fe0fe0ba3ed7e33b5bb6eb094ff8bd6c98"
...@@ -2948,6 +2972,18 @@ ...@@ -2948,6 +2972,18 @@
resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11"
integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==
"@isaacs/cliui@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
dependencies:
string-width "^5.1.2"
string-width-cjs "npm:string-width@^4.2.0"
strip-ansi "^7.0.1"
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@istanbuljs/load-nyc-config@^1.0.0": "@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
...@@ -4632,6 +4668,11 @@ ...@@ -4632,6 +4668,11 @@
"@parcel/watcher-win32-ia32" "2.3.0" "@parcel/watcher-win32-ia32" "2.3.0"
"@parcel/watcher-win32-x64" "2.3.0" "@parcel/watcher-win32-x64" "2.3.0"
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@pkgr/utils@^2.3.1": "@pkgr/utils@^2.3.1":
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03"
...@@ -7726,6 +7767,11 @@ ansi-styles@^6.0.0: ...@@ -7726,6 +7767,11 @@ ansi-styles@^6.0.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.1.tgz#63cd61c72283a71cb30bd881dbb60adada74bc70" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.1.tgz#63cd61c72283a71cb30bd881dbb60adada74bc70"
integrity sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg== integrity sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==
ansi-styles@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
any-promise@^1.0.0: any-promise@^1.0.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
...@@ -8414,6 +8460,11 @@ clsx@^1.1.0: ...@@ -8414,6 +8460,11 @@ clsx@^1.1.0:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
clsx@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b"
integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
cluster-key-slot@^1.1.0: cluster-key-slot@^1.1.0:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac"
...@@ -8611,7 +8662,7 @@ cross-fetch@^3.1.4, cross-fetch@^3.1.5: ...@@ -8611,7 +8662,7 @@ cross-fetch@^3.1.4, cross-fetch@^3.1.5:
dependencies: dependencies:
node-fetch "2.6.7" node-fetch "2.6.7"
cross-spawn@^7.0.2, cross-spawn@^7.0.3: cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3" version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
...@@ -8657,6 +8708,17 @@ css-select@^4.1.3: ...@@ -8657,6 +8708,17 @@ css-select@^4.1.3:
domutils "^2.8.0" domutils "^2.8.0"
nth-check "^2.0.1" nth-check "^2.0.1"
css-select@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==
dependencies:
boolbase "^1.0.0"
css-what "^6.1.0"
domhandler "^5.0.2"
domutils "^3.0.1"
nth-check "^2.0.1"
css-tree@^1.1.2, css-tree@^1.1.3: css-tree@^1.1.2, css-tree@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
...@@ -8665,7 +8727,23 @@ css-tree@^1.1.2, css-tree@^1.1.3: ...@@ -8665,7 +8727,23 @@ css-tree@^1.1.2, css-tree@^1.1.3:
mdn-data "2.0.14" mdn-data "2.0.14"
source-map "^0.6.1" source-map "^0.6.1"
css-what@^6.0.1: css-tree@^2.2.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20"
integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==
dependencies:
mdn-data "2.0.30"
source-map-js "^1.0.1"
css-tree@~2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032"
integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==
dependencies:
mdn-data "2.0.28"
source-map-js "^1.0.1"
css-what@^6.0.1, css-what@^6.1.0:
version "6.1.0" version "6.1.0"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
...@@ -8685,6 +8763,13 @@ cssfilter@0.0.10: ...@@ -8685,6 +8763,13 @@ cssfilter@0.0.10:
resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==
csso@5.0.5:
version "5.0.5"
resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6"
integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==
dependencies:
css-tree "~2.2.0"
csso@^4.2.0: csso@^4.2.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
...@@ -9238,12 +9323,21 @@ dom-serializer@^1.0.1: ...@@ -9238,12 +9323,21 @@ dom-serializer@^1.0.1:
domhandler "^4.2.0" domhandler "^4.2.0"
entities "^2.0.0" entities "^2.0.0"
dom-serializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.2"
entities "^4.2.0"
dom-to-image@^2.6.0: dom-to-image@^2.6.0:
version "2.6.0" version "2.6.0"
resolved "https://registry.yarnpkg.com/dom-to-image/-/dom-to-image-2.6.0.tgz#8a503608088c87b1c22f9034ae032e1898955867" resolved "https://registry.yarnpkg.com/dom-to-image/-/dom-to-image-2.6.0.tgz#8a503608088c87b1c22f9034ae032e1898955867"
integrity sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA== integrity sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==
domelementtype@^2.0.1, domelementtype@^2.2.0: domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
...@@ -9262,6 +9356,13 @@ domhandler@^4.2.0, domhandler@^4.3.1: ...@@ -9262,6 +9356,13 @@ domhandler@^4.2.0, domhandler@^4.3.1:
dependencies: dependencies:
domelementtype "^2.2.0" domelementtype "^2.2.0"
domhandler@^5.0.2, domhandler@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
dependencies:
domelementtype "^2.3.0"
dompurify@=3.0.6: dompurify@=3.0.6:
version "3.0.6" version "3.0.6"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.6.tgz#925ebd576d54a9531b5d76f0a5bef32548351dae" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.6.tgz#925ebd576d54a9531b5d76f0a5bef32548351dae"
...@@ -9276,6 +9377,15 @@ domutils@^2.8.0: ...@@ -9276,6 +9377,15 @@ domutils@^2.8.0:
domelementtype "^2.2.0" domelementtype "^2.2.0"
domhandler "^4.2.0" domhandler "^4.2.0"
domutils@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
dependencies:
dom-serializer "^2.0.0"
domelementtype "^2.3.0"
domhandler "^5.0.3"
dotenv-cli@^6.0.0: dotenv-cli@^6.0.0:
version "6.0.0" version "6.0.0"
resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-6.0.0.tgz#8a30cbc59d0a8aaa166b2fee0a9a55e23a1223ab" resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-6.0.0.tgz#8a30cbc59d0a8aaa166b2fee0a9a55e23a1223ab"
...@@ -9379,6 +9489,11 @@ entities@^2.0.0: ...@@ -9379,6 +9489,11 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
entities@^4.2.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
entities@^4.4.0: entities@^4.4.0:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174"
...@@ -10248,6 +10363,14 @@ for-each@^0.3.3: ...@@ -10248,6 +10363,14 @@ for-each@^0.3.3:
dependencies: dependencies:
is-callable "^1.1.3" is-callable "^1.1.3"
foreground-child@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
dependencies:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"
form-data@^4.0.0: form-data@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
...@@ -10479,6 +10602,17 @@ glob@7.1.7: ...@@ -10479,6 +10602,17 @@ glob@7.1.7:
once "^1.3.0" once "^1.3.0"
path-is-absolute "^1.0.0" path-is-absolute "^1.0.0"
glob@^10.3.10:
version "10.3.10"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
dependencies:
foreground-child "^3.1.0"
jackspeak "^2.3.5"
minimatch "^9.0.1"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry "^1.10.1"
glob@^7.1.3, glob@^7.1.4: glob@^7.1.3, glob@^7.1.4:
version "7.2.3" version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
...@@ -10712,6 +10846,11 @@ hastscript@^6.0.0: ...@@ -10712,6 +10846,11 @@ hastscript@^6.0.0:
property-information "^5.0.0" property-information "^5.0.0"
space-separated-tokens "^1.0.0" space-separated-tokens "^1.0.0"
he@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
help-me@^4.0.1: help-me@^4.0.1:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.1.0.tgz#c105e78ba490d6fcaa61a3d0cd06e0054554efab" resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.1.0.tgz#c105e78ba490d6fcaa61a3d0cd06e0054554efab"
...@@ -11310,6 +11449,15 @@ istanbul-reports@^3.1.3: ...@@ -11310,6 +11449,15 @@ istanbul-reports@^3.1.3:
html-escaper "^2.0.0" html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0" istanbul-lib-report "^3.0.0"
jackspeak@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
dependencies:
"@isaacs/cliui" "^8.0.2"
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
jaeger-client@^3.15.0: jaeger-client@^3.15.0:
version "3.19.0" version "3.19.0"
resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.19.0.tgz#9b5bd818ebd24e818616ee0f5cffe1722a53ae6e" resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.19.0.tgz#9b5bd818ebd24e818616ee0f5cffe1722a53ae6e"
...@@ -12223,7 +12371,7 @@ lowlight@^1.17.0: ...@@ -12223,7 +12371,7 @@ lowlight@^1.17.0:
fault "^1.0.0" fault "^1.0.0"
highlight.js "~10.7.0" highlight.js "~10.7.0"
lru-cache@^10.0.2: lru-cache@^10.0.2, "lru-cache@^9.1.1 || ^10.0.0":
version "10.1.0" version "10.1.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484"
integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==
...@@ -12289,6 +12437,16 @@ mdn-data@2.0.14: ...@@ -12289,6 +12437,16 @@ mdn-data@2.0.14:
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
mdn-data@2.0.28:
version "2.0.28"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba"
integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==
mdn-data@2.0.30:
version "2.0.30"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc"
integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==
mdurl@^1.0.1: mdurl@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
...@@ -12402,6 +12560,13 @@ minimatch@^7.4.3: ...@@ -12402,6 +12560,13 @@ minimatch@^7.4.3:
dependencies: dependencies:
brace-expansion "^2.0.1" brace-expansion "^2.0.1"
minimatch@^9.0.1:
version "9.0.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
dependencies:
brace-expansion "^2.0.1"
minimist@^1.1.0, minimist@^1.2.3, minimist@^1.2.6: minimist@^1.1.0, minimist@^1.2.3, minimist@^1.2.6:
version "1.2.8" version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
...@@ -12412,6 +12577,11 @@ minimist@^1.2.0, minimist@^1.2.5: ...@@ -12412,6 +12577,11 @@ minimist@^1.2.0, minimist@^1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0":
version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
mixpanel-browser@^2.47.0: mixpanel-browser@^2.47.0:
version "2.47.0" version "2.47.0"
resolved "https://registry.yarnpkg.com/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz#4e7fd3bb660c6f63443efbd169d1cd327db71ed4" resolved "https://registry.yarnpkg.com/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz#4e7fd3bb660c6f63443efbd169d1cd327db71ed4"
...@@ -12643,6 +12813,14 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: ...@@ -12643,6 +12813,14 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055"
integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==
node-html-parser@^6.1.11:
version "6.1.11"
resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.11.tgz#387378111348c001a5c5fbebb7f478fdf65610aa"
integrity sha512-FAgwwZ6h0DSDWxfD0Iq1tsDcBCxdJB1nXpLPPxX8YyVWzbfCjKWEzaynF4gZZ/8hziUmp7ZSaKylcn0iKhufUQ==
dependencies:
css-select "^5.1.0"
he "1.2.0"
node-int64@^0.4.0: node-int64@^0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
...@@ -13025,6 +13203,14 @@ path-parse@^1.0.7: ...@@ -13025,6 +13203,14 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-scurry@^1.10.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698"
integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==
dependencies:
lru-cache "^9.1.1 || ^10.0.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-to-regexp@^6.2.1: path-to-regexp@^6.2.1:
version "6.2.1" version "6.2.1"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
...@@ -14402,6 +14588,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: ...@@ -14402,6 +14588,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
signal-exit@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
simple-concat@^1.0.0: simple-concat@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
...@@ -14485,7 +14676,7 @@ sonic-boom@^3.0.0, sonic-boom@^3.1.0: ...@@ -14485,7 +14676,7 @@ sonic-boom@^3.0.0, sonic-boom@^3.1.0:
dependencies: dependencies:
atomic-sleep "^1.0.0" atomic-sleep "^1.0.0"
source-map-js@^1.0.2: source-map-js@^1.0.1, source-map-js@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
...@@ -14606,7 +14797,7 @@ string-template@~0.2.1: ...@@ -14606,7 +14797,7 @@ string-template@~0.2.1:
resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
...@@ -14615,7 +14806,7 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: ...@@ -14615,7 +14806,7 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0" is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1" strip-ansi "^6.0.1"
string-width@^5.0.0: string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
...@@ -14702,7 +14893,7 @@ string_decoder@~1.1.1: ...@@ -14702,7 +14893,7 @@ string_decoder@~1.1.1:
dependencies: dependencies:
safe-buffer "~5.1.0" safe-buffer "~5.1.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1: "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
...@@ -14819,6 +15010,20 @@ supports-preserve-symlinks-flag@^1.0.0: ...@@ -14819,6 +15010,20 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
svg-icons-cli@^0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/svg-icons-cli/-/svg-icons-cli-0.0.5.tgz#501c43f80fe23784e826b47c4fe2e71e7ea5fa67"
integrity sha512-6U7RB1n8qroIuJYjMO/HVk/3OXZS0m48Qu+pFXNGp2oRwhTdkTjMJ2PThbzzAwLNzBNmQ5qMfzQq5vqvp4Ocdg==
dependencies:
"@clack/prompts" "^0.7.0"
clsx "^2.0.0"
glob "^10.3.10"
node-html-parser "^6.1.11"
svgo "^3.0.4"
tailwind-merge "^2.0.0"
tiny-parse-argv "^2.2.0"
typescript "^5.2.2"
svg-parser@^2.0.4: svg-parser@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"
...@@ -14837,6 +15042,19 @@ svgo@^2.8.0: ...@@ -14837,6 +15042,19 @@ svgo@^2.8.0:
picocolors "^1.0.0" picocolors "^1.0.0"
stable "^0.1.8" stable "^0.1.8"
svgo@^3.0.4:
version "3.1.0"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.1.0.tgz#7e63855c8da73297d5d5765e968f9679a0f8d24a"
integrity sha512-R5SnNA89w1dYgNv570591F66v34b3eQShpIBcQtZtM5trJwm1VvxbIoMpRYY3ybTAutcKTLEmTsdnaknOHbiQA==
dependencies:
"@trysound/sax" "0.2.0"
commander "^7.2.0"
css-select "^5.1.0"
css-tree "^2.2.1"
css-what "^6.1.0"
csso "5.0.5"
picocolors "^1.0.0"
swagger-client@^3.22.3: swagger-client@^3.22.3:
version "3.23.1" version "3.23.1"
resolved "https://registry.yarnpkg.com/swagger-client/-/swagger-client-3.23.1.tgz#22364b76b6f61b7c69f8846563fad59f28891380" resolved "https://registry.yarnpkg.com/swagger-client/-/swagger-client-3.23.1.tgz#22364b76b6f61b7c69f8846563fad59f28891380"
...@@ -14916,6 +15134,13 @@ tabbable@^4.0.0: ...@@ -14916,6 +15134,13 @@ tabbable@^4.0.0:
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261"
integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ== integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==
tailwind-merge@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.1.0.tgz#541b407e0ec255651e92571d96b685e48f01999c"
integrity sha512-l11VvI4nSwW7MtLSLYT4ldidDEUwQAMWuSHk7l4zcXZDgnCRa0V3OdCwFfM7DCzakVXMNRwAeje9maFFXT71dQ==
dependencies:
"@babel/runtime" "^7.23.5"
tapable@^2.2.0: tapable@^2.2.0:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
...@@ -15016,6 +15241,11 @@ tiny-invariant@^1.0.6: ...@@ -15016,6 +15241,11 @@ tiny-invariant@^1.0.6:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
tiny-parse-argv@^2.2.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tiny-parse-argv/-/tiny-parse-argv-2.4.0.tgz#8612163a88104a5af9a64e4775cd1e091d4fa265"
integrity sha512-WTEsnmeHNr99hLQIDA+gnsS+fDsCDITlqgI+zEhx9M6ErPt0heoNZ1PGvql6wcf95sIx40J0MLYXaPveGwtpoA==
tiny-warning@^1.0.3: tiny-warning@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
...@@ -15252,6 +15482,11 @@ typescript@^5.1.0: ...@@ -15252,6 +15482,11 @@ typescript@^5.1.0:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
typescript@^5.2.2:
version "5.3.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
ua-parser-js@^1.0.33: ua-parser-js@^1.0.33:
version "1.0.35" version "1.0.35"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011"
...@@ -15736,6 +15971,15 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: ...@@ -15736,6 +15971,15 @@ word-wrap@^1.2.3, word-wrap@~1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^6.2.0: wrap-ansi@^6.2.0:
version "6.2.0" version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
...@@ -15745,14 +15989,14 @@ wrap-ansi@^6.2.0: ...@@ -15745,14 +15989,14 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0" string-width "^4.1.0"
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi@^7.0.0: wrap-ansi@^8.1.0:
version "7.0.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
dependencies: dependencies:
ansi-styles "^4.0.0" ansi-styles "^6.1.0"
string-width "^4.1.0" string-width "^5.0.1"
strip-ansi "^6.0.0" strip-ansi "^7.0.1"
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"
......
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