Commit 10881261 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Replace `lodash` with `es-toolkit` (#2503)

* first part of migration

* second part of migration

* bump up es-toolkit version

* bump up `es-toolkit` version and remove `lodash` completely

* update screenshot
parent 2b47bbed
...@@ -30,14 +30,9 @@ const RESTRICTED_MODULES = { ...@@ -30,14 +30,9 @@ const RESTRICTED_MODULES = {
importNames: [ 'Popover', 'Menu', 'PinInput', 'useToast', 'Skeleton' ], importNames: [ 'Popover', 'Menu', 'PinInput', 'useToast', 'Skeleton' ],
message: 'Please use corresponding component or hook from ui/shared/chakra component instead', message: 'Please use corresponding component or hook from ui/shared/chakra component instead',
}, },
{
name: 'lodash',
message: 'Please use `import [package] from \'lodash/[package]\'` instead.',
},
], ],
patterns: [ patterns: [
'icons/*', 'icons/*',
'!lodash/*',
], ],
}; };
......
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.444 18.315a10 10 0 1 0 11.112-16.63 10 10 0 0 0-11.112 16.63ZM5.3 2.965a8.462 8.462 0 1 1 9.402 14.07 8.462 8.462 0 0 1-9.402-14.07Zm8.637 11.978a.768.768 0 0 0 .295.057.769.769 0 0 0 .546-1.315l-4.008-4V3.846a.769.769 0 1 0-1.538 0V10a.77.77 0 0 0 .223.546l4.23 4.23a.77.77 0 0 0 .252.167Z" fill="currentColor"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M4.444 18.315a10 10 0 1 0 11.112-16.63 10 10 0 0 0-11.112 16.63ZM5.3 2.965a8.462 8.462 0 1 1 9.402 14.07A8.462 8.462 0 0 1 5.3 2.965Zm8.637 11.978a.768.768 0 0 0 .295.057.769.769 0 0 0 .546-1.315l-4.008-4V3.846a.769.769 0 1 0-1.538 0V10a.77.77 0 0 0 .223.546l4.23 4.23a.77.77 0 0 0 .252.167Z" fill="currentColor"/>
</svg> </svg>
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import _omit from 'lodash/omit'; import { omit, pickBy } from 'es-toolkit';
import _pickBy from 'lodash/pickBy';
import React from 'react'; import React from 'react';
import type { CsrfData } from 'types/client/account'; import type { CsrfData } from 'types/client/account';
...@@ -38,7 +37,7 @@ export default function useApiFetch() { ...@@ -38,7 +37,7 @@ export default function useApiFetch() {
const resource: ApiResource = RESOURCES[resourceName]; const resource: ApiResource = RESOURCES[resourceName];
const url = buildUrl(resourceName, pathParams, queryParams); const url = buildUrl(resourceName, pathParams, queryParams);
const withBody = isBodyAllowed(fetchParams?.method); const withBody = isBodyAllowed(fetchParams?.method);
const headers = _pickBy({ const headers = pickBy({
'x-endpoint': resource.endpoint && isNeedProxy() ? resource.endpoint : undefined, 'x-endpoint': resource.endpoint && isNeedProxy() ? resource.endpoint : undefined,
Authorization: resource.endpoint && resource.needAuth ? apiToken : undefined, Authorization: resource.endpoint && resource.needAuth ? apiToken : undefined,
'x-csrf-token': withBody && csrfToken ? csrfToken : undefined, 'x-csrf-token': withBody && csrfToken ? csrfToken : undefined,
...@@ -55,7 +54,7 @@ export default function useApiFetch() { ...@@ -55,7 +54,7 @@ export default function useApiFetch() {
// change condition here if something is changed // change condition here if something is changed
credentials: config.features.account.isEnabled ? 'include' : 'same-origin', credentials: config.features.account.isEnabled ? 'include' : 'same-origin',
headers, headers,
..._omit(fetchParams, 'headers'), ...(fetchParams ? omit(fetchParams, [ 'headers' ]) : {}),
}, },
{ {
resource: resource.path, resource: resource.path,
......
import clamp from 'lodash/clamp'; import { throttle, clamp } from 'es-toolkit';
import throttle from 'lodash/throttle';
import React from 'react'; import React from 'react';
const ScrollDirectionContext = React.createContext<'up' | 'down' | null>(null); const ScrollDirectionContext = React.createContext<'up' | 'down' | null>(null);
......
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import type { LegacyRef } from 'react'; import type { LegacyRef } from 'react';
import React from 'react'; import React from 'react';
...@@ -19,7 +19,7 @@ export default function useClientRect<E extends Element>(): [ DOMRect | null, Le ...@@ -19,7 +19,7 @@ export default function useClientRect<E extends Element>(): [ DOMRect | null, Le
return; return;
} }
const resizeHandler = _debounce(() => { const resizeHandler = debounce(() => {
setRect(nodeRef.current?.getBoundingClientRect() ?? null); setRect(nodeRef.current?.getBoundingClientRect() ?? null);
}, 100); }, 100);
......
import throttle from 'lodash/throttle'; import { throttle } from 'es-toolkit';
import React from 'react'; import React from 'react';
export default function useIsSticky(ref: React.RefObject<HTMLDivElement>, offset = 0, isEnabled = true) { export default function useIsSticky(ref: React.RefObject<HTMLDivElement>, offset = 0, isEnabled = true) {
......
import _clamp from 'lodash/clamp'; import { clamp } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { useInView } from 'react-intersection-observer'; import { useInView } from 'react-intersection-observer';
...@@ -15,7 +15,7 @@ export default function useLazyRenderedList(list: Array<unknown>, isEnabled: boo ...@@ -15,7 +15,7 @@ export default function useLazyRenderedList(list: Array<unknown>, isEnabled: boo
React.useEffect(() => { React.useEffect(() => {
if (inView) { if (inView) {
setRenderedItemsNum((prev) => _clamp(prev + STEP, 0, list.length)); setRenderedItemsNum((prev) => clamp(prev + STEP, 0, list.length));
} }
}, [ inView, list.length ]); }, [ inView, list.length ]);
......
import _capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
export default function getTabName(tab: string) { export default function getTabName(tab: string) {
return tab !== '' ? _capitalize(tab.replaceAll('_', ' ')) : 'Default'; return tab !== '' ? capitalize(tab.replaceAll('_', ' ')) : 'Default';
} }
import _capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import type { Config } from 'mixpanel-browser'; import type { Config } from 'mixpanel-browser';
import mixpanel from 'mixpanel-browser'; import mixpanel from 'mixpanel-browser';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
...@@ -40,12 +40,12 @@ export default function useMixpanelInit() { ...@@ -40,12 +40,12 @@ export default function useMixpanelInit() {
'Viewport width': window.innerWidth, 'Viewport width': window.innerWidth,
'Viewport height': window.innerHeight, 'Viewport height': window.innerHeight,
Language: window.navigator.language, Language: window.navigator.language,
'Device type': _capitalize(deviceType), 'Device type': capitalize(deviceType),
'User id': userId, 'User id': userId,
}); });
mixpanel.identify(userId); mixpanel.identify(userId);
userProfile.set({ userProfile.set({
'Device Type': _capitalize(deviceType), 'Device Type': capitalize(deviceType),
...(isAuth ? { 'With Account': true } : {}), ...(isAuth ? { 'With Account': true } : {}),
}); });
userProfile.setOnce({ userProfile.setOnce({
......
import _compose from 'lodash/fp/compose'; import { mapValues } from 'es-toolkit';
import _mapValues from 'lodash/mapValues';
import type { NetworkExplorer } from 'types/networks'; import type { NetworkExplorer } from 'types/networks';
...@@ -32,7 +31,7 @@ const networkExplorers: Array<NetworkExplorer> = (() => { ...@@ -32,7 +31,7 @@ const networkExplorers: Array<NetworkExplorer> = (() => {
return config.UI.explorers.items.map((explorer) => ({ return config.UI.explorers.items.map((explorer) => ({
...explorer, ...explorer,
baseUrl: stripTrailingSlash(explorer.baseUrl), baseUrl: stripTrailingSlash(explorer.baseUrl),
paths: _mapValues(explorer.paths, _compose(stripTrailingSlash, addLeadingSlash)), paths: mapValues(explorer.paths, (value) => value ? stripTrailingSlash(addLeadingSlash(value)) : value),
})); }));
})(); })();
......
import _uniq from 'lodash/uniq'; import { uniq } from 'es-toolkit';
import isBrowser from './isBrowser'; import isBrowser from './isBrowser';
...@@ -27,7 +27,7 @@ export function saveToRecentKeywords(value: string) { ...@@ -27,7 +27,7 @@ export function saveToRecentKeywords(value: string) {
} }
const keywordsArr = getRecentSearchKeywords(); const keywordsArr = getRecentSearchKeywords();
const result = _uniq([ value, ...keywordsArr ]).slice(0, MAX_KEYWORDS_NUMBER - 1); const result = uniq([ value, ...keywordsArr ]).slice(0, MAX_KEYWORDS_NUMBER - 1);
window.localStorage.setItem(RECENT_KEYWORDS_LS_KEY, JSON.stringify(result)); window.localStorage.setItem(RECENT_KEYWORDS_LS_KEY, JSON.stringify(result));
} }
......
import _upperFirst from 'lodash/upperFirst'; import { upperFirst } from 'es-toolkit';
import type { Metadata, MetadataAttributes } from 'types/client/token'; import type { Metadata, MetadataAttributes } from 'types/client/token';
...@@ -72,7 +72,7 @@ export default function attributesParser(attributes: Array<unknown>): Metadata[' ...@@ -72,7 +72,7 @@ export default function attributesParser(attributes: Array<unknown>): Metadata['
return { return {
...formatValue(value, display, trait), ...formatValue(value, display, trait),
trait_type: _upperFirst(trait || 'property'), trait_type: upperFirst(trait || 'property'),
}; };
}) })
.filter((item) => item?.value) .filter((item) => item?.value)
......
import _get from 'lodash/get'; import { get } from 'es-toolkit/compat';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
...@@ -25,7 +25,7 @@ export default function useAddOrSwitchChain() { ...@@ -25,7 +25,7 @@ export default function useAddOrSwitchChain() {
const errorObj = getErrorObj(error); const errorObj = getErrorObj(error);
const code = errorObj && 'code' in errorObj ? errorObj.code : undefined; const code = errorObj && 'code' in errorObj ? errorObj.code : undefined;
const originalErrorCode = _get(errorObj, 'data.originalError.code'); const originalErrorCode = get(errorObj, 'data.originalError.code');
// This error code indicates that the chain has not been added to Wallet. // This error code indicates that the chain has not been added to Wallet.
if (code === 4902 || originalErrorCode === 4902) { if (code === 4902 || originalErrorCode === 4902) {
......
import _padStart from 'lodash/padStart'; import { padStart } from 'es-toolkit/compat';
import type { BlockEpoch, BlockEpochElectionRewardDetails, BlockEpochElectionRewardDetailsResponse } from 'types/api/block'; import type { BlockEpoch, BlockEpochElectionRewardDetails, BlockEpochElectionRewardDetailsResponse } from 'types/api/block';
...@@ -42,11 +42,11 @@ function getRewardDetailsItem(index: number): BlockEpochElectionRewardDetails { ...@@ -42,11 +42,11 @@ function getRewardDetailsItem(index: number): BlockEpochElectionRewardDetails {
amount: `${ 100 - index }210001063118670575`, amount: `${ 100 - index }210001063118670575`,
account: { account: {
...addressMock.withoutName, ...addressMock.withoutName,
hash: `0x30D060F129817c4DE5fBc1366d53e19f43c8c6${ _padStart(String(index), 2, '0') }`, hash: `0x30D060F129817c4DE5fBc1366d53e19f43c8c6${ padStart(String(index), 2, '0') }`,
}, },
associated_account: { associated_account: {
...addressMock.withoutName, ...addressMock.withoutName,
hash: `0x456f41406B32c45D59E539e4BBA3D7898c3584${ _padStart(String(index), 2, '0') }`, hash: `0x456f41406B32c45D59E539e4BBA3D7898c3584${ padStart(String(index), 2, '0') }`,
}, },
}; };
} }
......
import _mapValues from 'lodash/mapValues'; import { mapValues } from 'es-toolkit';
import type { HomeStats } from 'types/api/stats'; import type { HomeStats } from 'types/api/stats';
...@@ -51,17 +51,17 @@ export const withBtcLocked: HomeStats = { ...@@ -51,17 +51,17 @@ export const withBtcLocked: HomeStats = {
export const withoutFiatPrices: HomeStats = { export const withoutFiatPrices: HomeStats = {
...base, ...base,
gas_prices: _mapValues(base.gas_prices, (price) => price ? ({ ...price, fiat_price: null }) : null), gas_prices: base.gas_prices ? mapValues(base.gas_prices, (price) => price ? ({ ...price, fiat_price: null }) : null) : null,
}; };
export const withoutGweiPrices: HomeStats = { export const withoutGweiPrices: HomeStats = {
...base, ...base,
gas_prices: _mapValues(base.gas_prices, (price) => price ? ({ ...price, price: null }) : null), gas_prices: base.gas_prices ? mapValues(base.gas_prices, (price) => price ? ({ ...price, price: null }) : null) : null,
}; };
export const withoutBothPrices: HomeStats = { export const withoutBothPrices: HomeStats = {
...base, ...base,
gas_prices: _mapValues(base.gas_prices, (price) => price ? ({ ...price, price: null, fiat_price: null }) : null), gas_prices: base.gas_prices ? mapValues(base.gas_prices, (price) => price ? ({ ...price, price: null, fiat_price: null }) : null) : null,
}; };
export const withoutGasInfo: HomeStats = { export const withoutGasInfo: HomeStats = {
......
import type CspDev from 'csp-dev'; import type CspDev from 'csp-dev';
import { uniq } from 'es-toolkit';
export const KEY_WORDS = { export const KEY_WORDS = {
BLOB: 'blob:', BLOB: 'blob:',
...@@ -11,17 +12,6 @@ export const KEY_WORDS = { ...@@ -11,17 +12,6 @@ export const KEY_WORDS = {
UNSAFE_EVAL: '\'unsafe-eval\'', UNSAFE_EVAL: '\'unsafe-eval\'',
}; };
// we cannot use lodash/uniq and lodash/mergeWith in middleware code since it calls new Set() and it'is causing an error in Next.js
// "Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime"
export function unique(array: Array<string | undefined>) {
const set: Record<string, boolean> = {};
for (const item of array) {
item && (set[item] = true);
}
return Object.keys(set);
}
export function mergeDescriptors(...descriptors: Array<CspDev.DirectiveDescriptor>) { export function mergeDescriptors(...descriptors: Array<CspDev.DirectiveDescriptor>) {
return descriptors.reduce((result, item) => { return descriptors.reduce((result, item) => {
for (const _key in item) { for (const _key in item) {
...@@ -50,7 +40,7 @@ export function makePolicyString(policyDescriptor: CspDev.DirectiveDescriptor) { ...@@ -50,7 +40,7 @@ export function makePolicyString(policyDescriptor: CspDev.DirectiveDescriptor) {
return; return;
} }
const uniqueValues = unique(value); const uniqueValues = uniq(value);
return [ key, uniqueValues.join(' ') ].join(' '); return [ key, uniqueValues.join(' ') ].join(' ');
}) })
.filter(Boolean) .filter(Boolean)
......
import { pick } from 'es-toolkit';
import type { IncomingMessage } from 'http'; import type { IncomingMessage } from 'http';
import _pick from 'lodash/pick';
import type { NextApiRequest } from 'next'; import type { NextApiRequest } from 'next';
import type { NextApiRequestCookies } from 'next/dist/server/api-utils'; import type { NextApiRequestCookies } from 'next/dist/server/api-utils';
import type { RequestInit, Response } from 'node-fetch'; import type { RequestInit, Response } from 'node-fetch';
...@@ -21,7 +21,7 @@ export default function fetchFactory( ...@@ -21,7 +21,7 @@ export default function fetchFactory(
accept: _req.headers['accept'] || 'application/json', accept: _req.headers['accept'] || 'application/json',
'content-type': _req.headers['content-type'] || 'application/json', 'content-type': _req.headers['content-type'] || 'application/json',
cookie: apiToken ? `${ cookies.NAMES.API_TOKEN }=${ apiToken }` : '', cookie: apiToken ? `${ cookies.NAMES.API_TOKEN }=${ apiToken }` : '',
..._pick(_req.headers, [ ...pick(_req.headers, [
'x-csrf-token', 'x-csrf-token',
'Authorization', // the old value, just in case 'Authorization', // the old value, just in case
'authorization', // Node.js automatically lowercases headers 'authorization', // Node.js automatically lowercases headers
......
import _pick from 'lodash/pick'; import { pick, pickBy } from 'es-toolkit';
import _pickBy from 'lodash/pickBy';
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import fetchFactory from 'nextjs/utils/fetchProxy'; import fetchFactory from 'nextjs/utils/fetchProxy';
...@@ -18,7 +17,7 @@ const handler = async(nextReq: NextApiRequest, nextRes: NextApiResponse) => { ...@@ -18,7 +17,7 @@ const handler = async(nextReq: NextApiRequest, nextRes: NextApiResponse) => {
); );
const apiRes = await fetchFactory(nextReq)( const apiRes = await fetchFactory(nextReq)(
url.toString(), url.toString(),
_pickBy(_pick(nextReq, [ 'body', 'method' ]), Boolean), pickBy(pick(nextReq, [ 'body', 'method' ]), Boolean),
); );
// proxy some headers from API // proxy some headers from API
......
import type { TestFixture, Page } from '@playwright/test'; import type { TestFixture, Page } from '@playwright/test';
import _isEqual from 'lodash/isEqual'; import { isEqual } from 'es-toolkit';
import { encodeFunctionData, encodeFunctionResult, type AbiFunction } from 'viem'; import { encodeFunctionData, encodeFunctionResult, type AbiFunction } from 'viem';
import { getEnvValue } from 'configs/app/utils'; import { getEnvValue } from 'configs/app/utils';
...@@ -43,7 +43,7 @@ const fixture: TestFixture<MockContractReadResponseFixture, { page: Page }> = as ...@@ -43,7 +43,7 @@ const fixture: TestFixture<MockContractReadResponseFixture, { page: Page }> = as
value: params?.value, value: params?.value,
}; };
if (_isEqual(params, callParams) && id) { if (isEqual(params, callParams) && id) {
return route.fulfill({ return route.fulfill({
status: 200, status: 200,
json: { json: {
......
import type { TestFixture, Page } from '@playwright/test'; import type { TestFixture, Page } from '@playwright/test';
import _isEqual from 'lodash/isEqual'; import { isEqual } from 'es-toolkit';
import type { PublicRpcSchema } from 'viem'; import type { PublicRpcSchema } from 'viem';
import { getEnvValue } from 'configs/app/utils'; import { getEnvValue } from 'configs/app/utils';
...@@ -34,7 +34,7 @@ const fixture: TestFixture<MockRpcResponseFixture, { page: Page }> = async({ pag ...@@ -34,7 +34,7 @@ const fixture: TestFixture<MockRpcResponseFixture, { page: Page }> = async({ pag
...(rpcMock.Parameters ? { params: rpcMock.Parameters } : {}), ...(rpcMock.Parameters ? { params: rpcMock.Parameters } : {}),
}; };
if (_isEqual(json, payload) && id !== undefined) { if (isEqual(json, payload) && id !== undefined) {
return route.fulfill({ return route.fulfill({
status: 200, status: 200,
json: { json: {
......
import './fonts.css'; import './fonts.css';
import './index.css'; import './index.css';
import { beforeMount } from '@playwright/experimental-ct-react/hooks'; import { beforeMount } from '@playwright/experimental-ct-react/hooks';
import _defaultsDeep from 'lodash/defaultsDeep';
import MockDate from 'mockdate'; import MockDate from 'mockdate';
import * as router from 'next/router'; import * as router from 'next/router';
...@@ -12,12 +11,15 @@ const NEXT_ROUTER_MOCK = { ...@@ -12,12 +11,15 @@ const NEXT_ROUTER_MOCK = {
replace: () => Promise.resolve(), replace: () => Promise.resolve(),
}; };
beforeMount(async({ hooksConfig }) => { beforeMount(async({ hooksConfig }: { hooksConfig?: { router: typeof router } }) => {
// Before mount, redefine useRouter to return mock value from test. // Before mount, redefine useRouter to return mock value from test.
// @ts-ignore: I really want to redefine this property :) // @ts-ignore: I really want to redefine this property :)
// eslint-disable-next-line no-import-assign // eslint-disable-next-line no-import-assign
router.useRouter = () => _defaultsDeep(hooksConfig?.router, NEXT_ROUTER_MOCK); router.useRouter = () => ({
...NEXT_ROUTER_MOCK,
...hooksConfig?.router,
});
// set current date // set current date
MockDate.set('2022-11-11T12:00:00Z'); MockDate.set('2022-11-11T12:00:00Z');
......
This source diff could not be displayed because it is too large. You can view the blob instead.
import noop from 'lodash/noop'; import { noop } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { test, expect } from 'playwright/lib'; import { test, expect } from 'playwright/lib';
......
import { Accordion, Box, Flex, Link } from '@chakra-ui/react'; import { Accordion, Box, Flex, Link } from '@chakra-ui/react';
import _range from 'lodash/range'; import { range } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { SmartContractMethod } from './types'; import type { SmartContractMethod } from './types';
...@@ -39,7 +39,7 @@ const ContractAbi = ({ abi, addressHash, sourceAddress, tab, visibleItems }: Pro ...@@ -39,7 +39,7 @@ const ContractAbi = ({ abi, addressHash, sourceAddress, tab, visibleItems }: Pro
} }
if (expandedSections.length < abi.length) { if (expandedSections.length < abi.length) {
setExpandedSections(_range(0, abi.length)); setExpandedSections(range(0, abi.length));
} else { } else {
setExpandedSections([]); setExpandedSections([]);
} }
......
import _set from 'lodash/set'; import { set } from 'es-toolkit/compat';
import type { ContractAbiItemInput } from '../types'; import type { ContractAbiItemInput } from '../types';
...@@ -78,7 +78,7 @@ export function transformFormDataToMethodArgs(formData: ContractMethodFormFields ...@@ -78,7 +78,7 @@ export function transformFormDataToMethodArgs(formData: ContractMethodFormFields
for (const field in formData) { for (const field in formData) {
const value = formData[field]; const value = formData[field];
_set(result, field.replaceAll(':', '.'), value); set(result, field.replaceAll(':', '.'), value);
} }
const filteredResult = filterOutEmptyItems(result); const filteredResult = filterOutEmptyItems(result);
......
import _pickBy from 'lodash/pickBy'; import { pickBy } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -63,7 +63,7 @@ export default function useMethodsFilters({ abi }: Params) { ...@@ -63,7 +63,7 @@ export default function useMethodsFilters({ abi }: Params) {
return; return;
} }
const queryForPathname = _pickBy(router.query, (value, key) => router.pathname.includes(`[${ key }]`)); const queryForPathname = pickBy(router.query, (value, key) => router.pathname.includes(`[${ key }]`));
router.push( router.push(
{ pathname: router.pathname, query: { ...queryForPathname, tab: nextTab } }, { pathname: router.pathname, query: { ...queryForPathname, tab: nextTab } },
undefined, undefined,
......
import { Image, Tooltip } from '@chakra-ui/react'; import { Image, Tooltip } from '@chakra-ui/react';
import _capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { MultichainProviderConfigParsed } from 'types/client/multichainProviderConfig'; import type { MultichainProviderConfigParsed } from 'types/client/multichainProviderConfig';
...@@ -25,10 +25,10 @@ const AddressMultichainButton = ({ item, addressHash, onClick, hasSingleProvider ...@@ -25,10 +25,10 @@ const AddressMultichainButton = ({ item, addressHash, onClick, hasSingleProvider
const buttonContent = hasSingleProvider ? ( const buttonContent = hasSingleProvider ? (
<> <>
{ buttonIcon } { buttonIcon }
{ _capitalize(item.name) } { capitalize(item.name) }
</> </>
) : ( ) : (
<Tooltip label={ _capitalize(item.name) }>{ buttonIcon }</Tooltip> <Tooltip label={ capitalize(item.name) }>{ buttonIcon }</Tooltip>
); );
const linkProps = { const linkProps = {
......
...@@ -12,7 +12,7 @@ import { ...@@ -12,7 +12,7 @@ import {
chakra, chakra,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import _clamp from 'lodash/clamp'; import { clamp } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type * as bens from '@blockscout/bens-types'; import type * as bens from '@blockscout/bens-types';
...@@ -37,7 +37,7 @@ interface Props { ...@@ -37,7 +37,7 @@ interface Props {
const DomainsGrid = ({ data }: { data: Array<bens.Domain> }) => { const DomainsGrid = ({ data }: { data: Array<bens.Domain> }) => {
return ( return (
<Grid <Grid
templateColumns={{ base: `repeat(${ _clamp(data.length, 1, 2) }, 1fr)`, lg: `repeat(${ _clamp(data.length, 1, 3) }, 1fr)` }} templateColumns={{ base: `repeat(${ clamp(data.length, 1, 2) }, 1fr)`, lg: `repeat(${ clamp(data.length, 1, 3) }, 1fr)` }}
columnGap={ 8 } columnGap={ 8 }
rowGap={ 4 } rowGap={ 4 }
mt={ 2 } mt={ 2 }
......
import { Box, Flex, IconButton, Tooltip } from '@chakra-ui/react'; import { Box, Flex, IconButton, 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 'es-toolkit';
import NextLink from 'next/link'; import NextLink from 'next/link';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -50,7 +50,7 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -50,7 +50,7 @@ const TokenSelect = ({ onClick }: Props) => {
); );
} }
const hasTokens = _sumBy(Object.values(data), ({ items }) => items.length) > 0; const hasTokens = sumBy(Object.values(data), ({ items }) => items.length) > 0;
if (isError || !hasTokens) { if (isError || !hasTokens) {
return <Box py="6px">0</Box>; return <Box py="6px">0</Box>;
} }
......
import { 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 'es-toolkit';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -26,7 +26,7 @@ interface Props { ...@@ -26,7 +26,7 @@ interface Props {
const TokenSelectMenu = ({ erc20sort, erc1155sort, erc404sort, filteredData, onInputChange, onSortClick, searchTerm }: Props) => { const TokenSelectMenu = ({ erc20sort, erc1155sort, erc404sort, filteredData, onInputChange, onSortClick, searchTerm }: Props) => {
const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600'); const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600');
const hasFilteredResult = _sumBy(Object.values(filteredData), ({ items }) => items.length) > 0; const hasFilteredResult = sumBy(Object.values(filteredData), ({ items }) => items.length) > 0;
return ( return (
<> <>
......
import _mapValues from 'lodash/mapValues'; import { mapValues } from 'es-toolkit';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -31,7 +31,7 @@ export default function useTokenSelect(data: FormattedData) { ...@@ -31,7 +31,7 @@ export default function useTokenSelect(data: FormattedData) {
}, []); }, []);
const filteredData = React.useMemo(() => { const filteredData = React.useMemo(() => {
return _mapValues(data, ({ items, isOverflow }) => ({ return mapValues(data, ({ items, isOverflow }) => ({
isOverflow, isOverflow,
items: items.filter(filterTokens(searchTerm.toLowerCase())), items: items.filter(filterTokens(searchTerm.toLowerCase())),
})); }));
......
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import fpAdd from 'lodash/fp/add';
import type { AddressTokenBalance } from 'types/api/address'; import type { AddressTokenBalance } from 'types/api/address';
import type { TokenType } from 'types/api/token'; import type { TokenType } from 'types/api/token';
...@@ -100,7 +99,7 @@ export const getTokensTotalInfo = (data: TokenSelectData) => { ...@@ -100,7 +99,7 @@ export const getTokensTotalInfo = (data: TokenSelectData) => {
const num = Object.values(data) const num = Object.values(data)
.map(({ items }) => items.length) .map(({ items }) => items.length)
.reduce(fpAdd, 0); .reduce((result, item) => result + item, 0);
const isOverflow = Object.values(data).some(({ isOverflow }) => isOverflow); const isOverflow = Object.values(data).some(({ isOverflow }) => isOverflow);
......
import { Flex, Select, Input, InputGroup, InputRightElement, VStack, IconButton } from '@chakra-ui/react'; import { Flex, Select, Input, InputGroup, InputRightElement, VStack, IconButton } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual'; import { isEqual } from 'es-toolkit';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
......
import { Flex, Input, Text } from '@chakra-ui/react'; import { Flex, Input, Text } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual'; import { isEqual } from 'es-toolkit';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
......
import { Flex, Input, Tag, Text } from '@chakra-ui/react'; import { Flex, Input, Tag, Text } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual'; import { isEqual } from 'es-toolkit';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
......
import { Flex, Checkbox, CheckboxGroup, Text, Spinner, Select } from '@chakra-ui/react'; import { Flex, Checkbox, CheckboxGroup, Text, Spinner, Select } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual'; import { isEqual } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { AdvancedFilterParams } from 'types/api/advancedFilter'; import type { AdvancedFilterParams } from 'types/api/advancedFilter';
......
import { Flex, Checkbox, CheckboxGroup, Spinner, chakra } from '@chakra-ui/react'; import { Flex, Checkbox, CheckboxGroup, Spinner, chakra } from '@chakra-ui/react';
import differenceBy from 'lodash/differenceBy'; import { isEqual, differenceBy } from 'es-toolkit';
import isEqual from 'lodash/isEqual';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
......
import { Flex, Checkbox, CheckboxGroup } from '@chakra-ui/react'; import { Flex, Checkbox, CheckboxGroup } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual'; import { isEqual, without } from 'es-toolkit';
import without from 'lodash/without';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
......
import castArray from 'lodash/castArray'; import { castArray } from 'es-toolkit/compat';
import type { AdvancedFilterAge, AdvancedFilterParams } from 'types/api/advancedFilter'; import type { AdvancedFilterAge, AdvancedFilterParams } from 'types/api/advancedFilter';
......
import { Grid, GridItem, Text, Link, Box, Tooltip } from '@chakra-ui/react'; import { Grid, GridItem, Text, Link, Box, Tooltip } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import { scroller, Element } from 'react-scroll'; import { scroller, Element } from 'react-scroll';
......
import _padStart from 'lodash/padStart'; import { padStart } from 'es-toolkit/compat';
export default function splitSecondsInPeriods(value: number) { export default function splitSecondsInPeriods(value: number) {
const seconds = value % 60; const seconds = value % 60;
...@@ -7,9 +7,9 @@ export default function splitSecondsInPeriods(value: number) { ...@@ -7,9 +7,9 @@ export default function splitSecondsInPeriods(value: number) {
const days = (value - seconds - minutes * 60 - hours * 60 * 60) / (60 * 60 * 24); const days = (value - seconds - minutes * 60 - hours * 60 * 60) / (60 * 60 * 24);
return { return {
seconds: _padStart(String(seconds), 2, '0'), seconds: padStart(String(seconds), 2, '0'),
minutes: _padStart(String(minutes), 2, '0'), minutes: padStart(String(minutes), 2, '0'),
hours: _padStart(String(hours), 2, '0'), hours: padStart(String(hours), 2, '0'),
days: _padStart(String(days), 2, '0'), days: padStart(String(days), 2, '0'),
}; };
} }
import { Flex, Text, Box, Tooltip } from '@chakra-ui/react'; import { Flex, Text, Box, Tooltip } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { Block } from 'types/api/block'; import type { Block } from 'types/api/block';
......
import { Table, Tbody, Tr, Th } from '@chakra-ui/react'; import { Table, Tbody, Tr, Th } from '@chakra-ui/react';
import { capitalize } from 'es-toolkit';
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import capitalize from 'lodash/capitalize';
import React from 'react'; import React from 'react';
import type { Block } from 'types/api/block'; import type { Block } from 'types/api/block';
......
import _get from 'lodash/get'; import { get } from 'es-toolkit/compat';
import React from 'react'; import React from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
...@@ -43,7 +43,7 @@ const ContractVerificationFieldGitHubRepo = ({ onCommitHashChange }: Props) => { ...@@ -43,7 +43,7 @@ const ContractVerificationFieldGitHubRepo = ({ onCommitHashChange }: Props) => {
const response = await fetch(`https://api.github.com/repos/${ gitHubData.owner }/${ gitHubData.repo }/commits?per_page=1`); const response = await fetch(`https://api.github.com/repos/${ gitHubData.owner }/${ gitHubData.repo }/commits?per_page=1`);
repoErrorRef.current = undefined; repoErrorRef.current = undefined;
trigger('repository_url'); trigger('repository_url');
onCommitHashChange(_get(response, '[0].sha')); onCommitHashChange(get(response, '[0].sha'));
return; return;
} catch (error) { } catch (error) {
repoErrorRef.current = 'GitHub repository not found'; repoErrorRef.current = 'GitHub repository not found';
......
import _capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { UseFormReturn } from 'react-hook-form'; import type { UseFormReturn } from 'react-hook-form';
...@@ -40,7 +40,7 @@ const CsvExportFormField = ({ formApi, name }: Props) => { ...@@ -40,7 +40,7 @@ const CsvExportFormField = ({ formApi, name }: Props) => {
name={ name } name={ name }
type="date" type="date"
max={ dayjs().format('YYYY-MM-DD') } max={ dayjs().format('YYYY-MM-DD') }
placeholder={ _capitalize(name) } placeholder={ capitalize(name) }
isRequired isRequired
rules={{ validate }} rules={{ validate }}
size={{ base: 'md', lg: 'lg' }} size={{ base: 'md', lg: 'lg' }}
......
...@@ -15,7 +15,7 @@ import { ...@@ -15,7 +15,7 @@ import {
HStack, HStack,
Link, Link,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import omit from 'lodash/omit'; import { omit } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
......
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
......
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
......
import _inRange from 'lodash/inRange'; import { inRange } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -43,7 +43,7 @@ const UserOp = () => { ...@@ -43,7 +43,7 @@ const UserOp = () => {
if (!userOpQuery.data) { if (!userOpQuery.data) {
return true; return true;
} else { } else {
if (_inRange( if (inRange(
Number(tt.log_index), Number(tt.log_index),
userOpQuery.data?.user_logs_start_index, userOpQuery.data?.user_logs_start_index,
userOpQuery.data?.user_logs_start_index + userOpQuery.data?.user_logs_count, userOpQuery.data?.user_logs_start_index + userOpQuery.data?.user_logs_count,
...@@ -58,7 +58,7 @@ const UserOp = () => { ...@@ -58,7 +58,7 @@ const UserOp = () => {
if (!userOpQuery.data) { if (!userOpQuery.data) {
return true; return true;
} else { } else {
if (_inRange(log.index, userOpQuery.data?.user_logs_start_index, userOpQuery.data?.user_logs_start_index + userOpQuery.data?.user_logs_count)) { if (inRange(log.index, userOpQuery.data?.user_logs_start_index, userOpQuery.data?.user_logs_start_index + userOpQuery.data?.user_logs_count)) {
return true; return true;
} }
return false; return false;
......
import { Alert, Box, Button, Flex, Grid, GridItem } from '@chakra-ui/react'; import { Alert, Box, Button, Flex, Grid, GridItem } from '@chakra-ui/react';
import _pickBy from 'lodash/pickBy'; import { pickBy } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { FormSubmitResult } from './types'; import type { FormSubmitResult } from './types';
...@@ -26,7 +26,7 @@ const PublicTagsSubmitResult = ({ data }: Props) => { ...@@ -26,7 +26,7 @@ const PublicTagsSubmitResult = ({ data }: Props) => {
const hasErrors = groupedData.items.some((item) => item.error !== null); const hasErrors = groupedData.items.some((item) => item.error !== null);
const companyWebsite = makePrettyLink(groupedData.companyWebsite); const companyWebsite = makePrettyLink(groupedData.companyWebsite);
const startOverButtonQuery = hasErrors ? _pickBy({ const startOverButtonQuery = hasErrors ? pickBy({
requesterName: groupedData.requesterName, requesterName: groupedData.requesterName,
requesterEmail: groupedData.requesterEmail, requesterEmail: groupedData.requesterEmail,
companyName: groupedData.companyName, companyName: groupedData.companyName,
......
import { chakra, Flex } from '@chakra-ui/react'; import { chakra, Flex } from '@chakra-ui/react';
import type { GroupBase, SelectComponentsConfig, SingleValueProps } from 'chakra-react-select'; import type { GroupBase, SelectComponentsConfig, SingleValueProps } from 'chakra-react-select';
import { chakraComponents } from 'chakra-react-select'; import { chakraComponents } from 'chakra-react-select';
import _capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
...@@ -22,7 +22,7 @@ const PublicTagsSubmitFieldTagType = ({ index, tagTypes }: Props) => { ...@@ -22,7 +22,7 @@ const PublicTagsSubmitFieldTagType = ({ index, tagTypes }: Props) => {
const typeOptions = React.useMemo(() => tagTypes?.map((type) => ({ const typeOptions = React.useMemo(() => tagTypes?.map((type) => ({
value: type.type, value: type.type,
label: _capitalize(type.type), label: capitalize(type.type),
})) ?? [], [ tagTypes ]); })) ?? [], [ tagTypes ]);
const fieldValue = watch(`tags.${ index }.type`).value; const fieldValue = watch(`tags.${ index }.type`).value;
......
import { Box, Button, Flex, Grid, GridItem, useColorModeValue } from '@chakra-ui/react'; import { Box, Button, Flex, Grid, GridItem, useColorModeValue } from '@chakra-ui/react';
import _pickBy from 'lodash/pickBy'; import { pickBy } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { FormSubmitResultGrouped } from '../types'; import type { FormSubmitResultGrouped } from '../types';
...@@ -23,7 +23,7 @@ const PublicTagsSubmitResultWithErrors = ({ data }: Props) => { ...@@ -23,7 +23,7 @@ const PublicTagsSubmitResultWithErrors = ({ data }: Props) => {
<Flex flexDir="column" rowGap={ 3 }> <Flex flexDir="column" rowGap={ 3 }>
{ data.items.map((item, index) => { { data.items.map((item, index) => {
const startOverButtonQuery = _pickBy({ const startOverButtonQuery = pickBy({
addresses: item.addresses, addresses: item.addresses,
requesterName: data.requesterName, requesterName: data.requesterName,
requesterEmail: data.requesterEmail, requesterEmail: data.requesterEmail,
......
import _isEqual from 'lodash/isEqual'; import { pickBy, isEqual } from 'es-toolkit';
import _pickBy from 'lodash/pickBy';
import type { FormFieldTag, FormFields, FormSubmitResult, FormSubmitResultGrouped, FormSubmitResultItemGrouped, SubmitRequestBody } from './types'; import type { FormFieldTag, FormFields, FormSubmitResult, FormSubmitResultGrouped, FormSubmitResultItemGrouped, SubmitRequestBody } from './types';
import type { UserInfo } from 'types/api/account'; import type { UserInfo } from 'types/api/account';
...@@ -22,7 +21,7 @@ export function convertFormDataToRequestsBody(data: FormFields): Array<SubmitReq ...@@ -22,7 +21,7 @@ export function convertFormDataToRequestsBody(data: FormFields): Array<SubmitReq
name: tag.name, name: tag.name,
tagType: tag.type.value, tagType: tag.type.value,
description: data.description, description: data.description,
meta: _pickBy({ meta: pickBy({
bgColor: tag.bgColor, bgColor: tag.bgColor,
textColor: tag.textColor, textColor: tag.textColor,
tagUrl: tag.url, tagUrl: tag.url,
...@@ -72,7 +71,7 @@ export function groupSubmitResult(data: FormSubmitResult | undefined): FormSubmi ...@@ -72,7 +71,7 @@ export function groupSubmitResult(data: FormSubmitResult | undefined): FormSubmi
// merge items with the same error and tags // merge items with the same error and tags
for (const item of _items) { for (const item of _items) {
const existingItem = items.find(({ error, tags }) => error === item.error && _isEqual(tags, item.tags)); const existingItem = items.find(({ error, tags }) => error === item.error && isEqual(tags, item.tags));
if (existingItem) { if (existingItem) {
existingItem.addresses.push(...item.addresses); existingItem.addresses.push(...item.addresses);
continue; continue;
......
import { PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react'; import { PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import type { FormEvent, FocusEvent } from 'react'; import type { FormEvent, FocusEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -59,7 +59,7 @@ const SearchResultsInput = ({ searchTerm, handleSubmit, handleSearchTermChange } ...@@ -59,7 +59,7 @@ const SearchResultsInput = ({ searchTerm, handleSubmit, handleSearchTermChange }
} }
calculateMenuWidth(); calculateMenuWidth();
const resizeHandler = _debounce(calculateMenuWidth, 200); const resizeHandler = debounce(calculateMenuWidth, 200);
const resizeObserver = new ResizeObserver(resizeHandler); const resizeObserver = new ResizeObserver(resizeHandler);
resizeObserver.observe(inputRef.current); resizeObserver.observe(inputRef.current);
......
import { Box, useColorModeValue } from '@chakra-ui/react'; import { Box, useColorModeValue } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import React, { useRef, useEffect, useState, useCallback } from 'react'; import React, { useRef, useEffect, useState, useCallback } from 'react';
const CUT_HEIGHT = 144; const CUT_HEIGHT = 144;
...@@ -25,7 +25,7 @@ const AccountPageDescription = ({ children, allowCut = true }: { children: React ...@@ -25,7 +25,7 @@ const AccountPageDescription = ({ children, allowCut = true }: { children: React
} }
calculateCut(); calculateCut();
const resizeHandler = _debounce(calculateCut, 300); const resizeHandler = debounce(calculateCut, 300);
window.addEventListener('resize', resizeHandler); window.addEventListener('resize', resizeHandler);
return function cleanup() { return function cleanup() {
window.removeEventListener('resize', resizeHandler); window.removeEventListener('resize', resizeHandler);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
import type { As } from '@chakra-ui/react'; import type { As } from '@chakra-ui/react';
import { Tooltip, chakra } from '@chakra-ui/react'; import { Tooltip, chakra } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import React, { useCallback, useEffect, useRef } from 'react'; import React, { useCallback, useEffect, useRef } from 'react';
import type { FontFace } from 'use-font-face-observer'; import type { FontFace } from 'use-font-face-observer';
import useFontFaceObserver from 'use-font-face-observer'; import useFontFaceObserver from 'use-font-face-observer';
...@@ -81,7 +81,7 @@ const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled, ...@@ -81,7 +81,7 @@ const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled,
}, [ calculateString, isFontFaceLoaded ]); }, [ calculateString, isFontFaceLoaded ]);
useEffect(() => { useEffect(() => {
const resizeHandler = _debounce(calculateString, 100); const resizeHandler = debounce(calculateString, 100);
const resizeObserver = new ResizeObserver(resizeHandler); const resizeObserver = new ResizeObserver(resizeHandler);
resizeObserver.observe(document.body); resizeObserver.observe(document.body);
......
import { Heading, Flex, Tooltip, Link, chakra, useDisclosure } from '@chakra-ui/react'; import { Heading, Flex, Tooltip, Link, chakra, useDisclosure } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import React from 'react'; import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
...@@ -94,7 +94,7 @@ const PageTitle = ({ title, contentAfter, withTextAd, backLink, className, isLoa ...@@ -94,7 +94,7 @@ const PageTitle = ({ title, contentAfter, withTextAd, backLink, className, isLoa
}, [ isLoading, updatedTruncateState ]); }, [ isLoading, updatedTruncateState ]);
React.useEffect(() => { React.useEffect(() => {
const handleResize = _debounce(updatedTruncateState, 1000); const handleResize = debounce(updatedTruncateState, 1000);
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize);
return function cleanup() { return function cleanup() {
......
import type { ChakraProps, ThemingProps } from '@chakra-ui/react'; import type { ChakraProps, ThemingProps } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _pickBy from 'lodash/pickBy'; import { pickBy } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
...@@ -42,7 +42,7 @@ const RoutedTabs = ({ ...@@ -42,7 +42,7 @@ const RoutedTabs = ({
const handleTabChange = React.useCallback((index: number) => { const handleTabChange = React.useCallback((index: number) => {
const nextTab = tabs[index]; const nextTab = tabs[index];
const queryForPathname = _pickBy(router.query, (value, key) => router.pathname.includes(`[${ key }]`)); const queryForPathname = pickBy(router.query, (value, key) => router.pathname.includes(`[${ key }]`));
const tabId = Array.isArray(nextTab.id) ? nextTab.id[0] : nextTab.id; const tabId = Array.isArray(nextTab.id) ? nextTab.id[0] : nextTab.id;
router.push( router.push(
{ pathname: router.pathname, query: { ...queryForPathname, tab: tabId } }, { pathname: router.pathname, query: { ...queryForPathname, tab: tabId } },
......
...@@ -6,7 +6,7 @@ import { ...@@ -6,7 +6,7 @@ import {
TabPanels, TabPanels,
chakra, chakra,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import type { TabItem } from './types'; import type { TabItem } from './types';
...@@ -69,7 +69,7 @@ const TabsWithScroll = ({ ...@@ -69,7 +69,7 @@ const TabsWithScroll = ({
}, [ defaultTabIndex ]); }, [ defaultTabIndex ]);
React.useEffect(() => { React.useEffect(() => {
const resizeHandler = _debounce(() => { const resizeHandler = debounce(() => {
setScreenWidth(window.innerWidth); setScreenWidth(window.innerWidth);
}, 100); }, 100);
const resizeObserver = new ResizeObserver(resizeHandler); const resizeObserver = new ResizeObserver(resizeHandler);
......
import { Thead, useColorModeValue } from '@chakra-ui/react'; import { Thead, useColorModeValue } from '@chakra-ui/react';
import type { TableHeadProps, PositionProps } from '@chakra-ui/react'; import type { TableHeadProps, PositionProps } from '@chakra-ui/react';
import throttle from 'lodash/throttle'; import { throttle } from 'es-toolkit';
import React from 'react'; import React from 'react';
interface Props extends TableHeadProps { interface Props extends TableHeadProps {
......
import type { PlacementWithLogical } from '@chakra-ui/react'; import type { PlacementWithLogical } from '@chakra-ui/react';
import { Tooltip, useDisclosure } from '@chakra-ui/react'; import { Tooltip, useDisclosure } from '@chakra-ui/react';
import debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import React from 'react'; import React from 'react';
import useFontFaceObserver from 'use-font-face-observer'; import useFontFaceObserver from 'use-font-face-observer';
......
import { Box, Flex, chakra, useColorModeValue } from '@chakra-ui/react'; import { Box, Flex, chakra, useColorModeValue } from '@chakra-ui/react';
import clamp from 'lodash/clamp'; import { clamp } from 'es-toolkit';
import React from 'react'; import React from 'react';
import Skeleton from 'ui/shared/chakra/Skeleton'; import Skeleton from 'ui/shared/chakra/Skeleton';
......
import * as d3 from 'd3'; import * as d3 from 'd3';
import _clamp from 'lodash/clamp'; import { clamp } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { POINT_SIZE } from './utils'; import { POINT_SIZE } from './utils';
...@@ -69,33 +69,33 @@ function calculatePosition({ pointX, pointY, canvasWidth, canvasHeight, nodeWidt ...@@ -69,33 +69,33 @@ function calculatePosition({ pointX, pointY, canvasWidth, canvasHeight, nodeWidt
// right // right
if (pointX + offset + nodeWidth <= canvasWidth) { if (pointX + offset + nodeWidth <= canvasWidth) {
const x = pointX + offset; const x = pointX + offset;
const y = _clamp(pointY - nodeHeight / 2, 0, canvasHeight - nodeHeight); const y = clamp(pointY - nodeHeight / 2, 0, canvasHeight - nodeHeight);
return [ x, y ]; return [ x, y ];
} }
// left // left
if (nodeWidth + offset <= pointX) { if (nodeWidth + offset <= pointX) {
const x = pointX - offset - nodeWidth; const x = pointX - offset - nodeWidth;
const y = _clamp(pointY - nodeHeight / 2, 0, canvasHeight - nodeHeight); const y = clamp(pointY - nodeHeight / 2, 0, canvasHeight - nodeHeight);
return [ x, y ]; return [ x, y ];
} }
// top // top
if (nodeHeight + offset <= pointY) { if (nodeHeight + offset <= pointY) {
const x = _clamp(pointX - nodeWidth / 2, 0, canvasWidth - nodeWidth); const x = clamp(pointX - nodeWidth / 2, 0, canvasWidth - nodeWidth);
const y = pointY - offset - nodeHeight; const y = pointY - offset - nodeHeight;
return [ x, y ]; return [ x, y ];
} }
// bottom // bottom
if (pointY + offset + nodeHeight <= canvasHeight) { if (pointY + offset + nodeHeight <= canvasHeight) {
const x = _clamp(pointX - nodeWidth / 2, 0, canvasWidth - nodeWidth); const x = clamp(pointX - nodeWidth / 2, 0, canvasWidth - nodeWidth);
const y = pointY + offset; const y = pointY + offset;
return [ x, y ]; return [ x, y ];
} }
const x = _clamp(pointX / 2, 0, canvasWidth - nodeWidth); const x = clamp(pointX / 2, 0, canvasWidth - nodeWidth);
const y = _clamp(pointY / 2, 0, canvasHeight - nodeHeight); const y = clamp(pointY / 2, 0, canvasHeight - nodeHeight);
return [ x, y ]; return [ x, y ];
} }
import _range from 'lodash/range'; import { range } from 'es-toolkit';
import React from 'react'; import React from 'react';
export default function useChartLegend(dataLength: number) { export default function useChartLegend(dataLength: number) {
const [ selectedLines, setSelectedLines ] = React.useState<Array<number>>(_range(dataLength)); const [ selectedLines, setSelectedLines ] = React.useState<Array<number>>(range(dataLength));
const handleLegendItemClick = React.useCallback((index: number) => { const handleLegendItemClick = React.useCallback((index: number) => {
const nextSelectedLines = selectedLines.includes(index) ? selectedLines.filter((item) => item !== index) : [ ...selectedLines, index ]; const nextSelectedLines = selectedLines.includes(index) ? selectedLines.filter((item) => item !== index) : [ ...selectedLines, index ];
......
import * as d3 from 'd3'; import * as d3 from 'd3';
import _maxBy from 'lodash/maxBy'; import { maxBy, uniq } from 'es-toolkit';
import _unique from 'lodash/uniq';
import type { AxesConfig, AxisConfig, TimeChartData } from '../types'; import type { AxesConfig, AxisConfig, TimeChartData } from '../types';
...@@ -88,8 +87,8 @@ function getYLabelFormatParams(ticks: Array<number>, maximumSignificantDigits = ...@@ -88,8 +87,8 @@ function getYLabelFormatParams(ticks: Array<number>, maximumSignificantDigits =
notation: 'compact' as const, notation: 'compact' as const,
}; };
const uniqTicksStr = _unique(ticks.map((tick) => tick.toLocaleString(undefined, params))); const uniqTicksStr = uniq(ticks.map((tick) => tick.toLocaleString(undefined, params)));
const maxLabelLength = _maxBy(uniqTicksStr, (items) => items.length)?.length ?? DEFAULT_LABEL_LENGTH; const maxLabelLength = maxBy(uniqTicksStr, (items) => items.length)?.length ?? DEFAULT_LABEL_LENGTH;
if (uniqTicksStr.length === ticks.length || maximumSignificantDigits === MAXIMUM_SIGNIFICANT_DIGITS_LIMIT) { if (uniqTicksStr.length === ticks.length || maximumSignificantDigits === MAXIMUM_SIGNIFICANT_DIGITS_LIMIT) {
return { ...params, maxLabelLength }; return { ...params, maxLabelLength };
......
import _noop from 'lodash/noop'; import { noop } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { test, expect } from 'playwright/lib'; import { test, expect } from 'playwright/lib';
...@@ -18,7 +18,7 @@ const defaultProps = { ...@@ -18,7 +18,7 @@ const defaultProps = {
isRequired: true, isRequired: true,
placeholder: 'Compiler', placeholder: 'Compiler',
name: 'compiler', name: 'compiler',
onChange: _noop, onChange: noop,
}; };
[ 'md' as const, 'lg' as const ].forEach((size) => { [ 'md' as const, 'lg' as const ].forEach((size) => {
......
import type { HTMLChakraProps } from '@chakra-ui/react'; import type { HTMLChakraProps } from '@chakra-ui/react';
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs, useBoolean } from '@chakra-ui/react'; import { Box, Tab, TabList, TabPanel, TabPanels, Tabs, useBoolean } from '@chakra-ui/react';
import _throttle from 'lodash/throttle'; import { throttle } from 'es-toolkit';
import type * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import type * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import React from 'react'; import React from 'react';
...@@ -47,7 +47,7 @@ const CodeEditorSideBar = ({ onFileSelect, data, monaco, editor, selectedFile, m ...@@ -47,7 +47,7 @@ const CodeEditorSideBar = ({ onFileSelect, data, monaco, editor, selectedFile, m
letterSpacing: 0.3, letterSpacing: 0.3,
}; };
const handleScrollThrottled = React.useRef(_throttle((event: React.SyntheticEvent) => { const handleScrollThrottled = React.useRef(throttle((event: React.SyntheticEvent) => {
setIsStuck((event.target as HTMLDivElement).scrollTop > 0); setIsStuck((event.target as HTMLDivElement).scrollTop > 0);
}, 100)); }, 100));
......
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import omit from 'lodash/omit'; import { omit } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { animateScroll } from 'react-scroll'; import { animateScroll } from 'react-scroll';
...@@ -154,7 +154,14 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({ ...@@ -154,7 +154,14 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
}, [ queryClient, resourceName, router, scrollToTop ]); }, [ queryClient, resourceName, router, scrollToTop ]);
const onFilterChange = useCallback(<R extends PaginatedResources = Resource>(newFilters: PaginationFilters<R> | undefined) => { const onFilterChange = useCallback(<R extends PaginatedResources = Resource>(newFilters: PaginationFilters<R> | undefined) => {
const newQuery = omit<typeof router.query>(router.query, 'next_page_params', 'page', 'filterFields' in resource ? resource.filterFields : []); const newQuery: typeof router.query = omit(
router.query,
[
'next_page_params',
'page',
...('filterFields' in resource ? resource.filterFields : []),
],
);
if (newFilters) { if (newFilters) {
Object.entries(newFilters).forEach(([ key, value ]) => { Object.entries(newFilters).forEach(([ key, value ]) => {
const isValidValue = typeof value === 'boolean' || (value && value.length); const isValidValue = typeof value === 'boolean' || (value && value.length);
...@@ -179,8 +186,8 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({ ...@@ -179,8 +186,8 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
}, [ router, resource, scrollToTop ]); }, [ router, resource, scrollToTop ]);
const onSortingChange = useCallback((newSorting: PaginationSorting<Resource> | undefined) => { const onSortingChange = useCallback((newSorting: PaginationSorting<Resource> | undefined) => {
const newQuery = { const newQuery: typeof router.query = {
...omit<typeof router.query>(router.query, 'next_page_params', 'page', SORTING_FIELDS), ...omit(router.query, [ 'next_page_params', 'page', ...SORTING_FIELDS ]),
...newSorting, ...newSorting,
}; };
scrollToTop(); scrollToTop();
......
import _noop from 'lodash/noop'; import { noop } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { test, expect } from 'playwright/lib'; import { test, expect } from 'playwright/lib';
...@@ -12,7 +12,7 @@ test('base view +@dark-mode', async({ render }) => { ...@@ -12,7 +12,7 @@ test('base view +@dark-mode', async({ render }) => {
<TagGroupSelect <TagGroupSelect
items={ [ { id: '1', title: 'Option 1' }, { id: '2', title: 'Option 2' }, { id: 'duck', title: 'Cute little duck' } ] } items={ [ { id: '1', title: 'Option 1' }, { id: '2', title: 'Option 2' }, { id: 'duck', title: 'Cute little duck' } ] }
value="duck" value="duck"
onChange={ _noop } onChange={ noop }
/>, />,
); );
......
import { Box, Select, VStack, Flex } from '@chakra-ui/react'; import { Box, Select, VStack, Flex } from '@chakra-ui/react';
import capitalize from 'lodash/capitalize'; import { capitalize } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { NetworkGroup, FeaturedNetwork } from 'types/networks'; import type { NetworkGroup, FeaturedNetwork } from 'types/networks';
......
...@@ -8,7 +8,7 @@ import { ...@@ -8,7 +8,7 @@ import {
useDisclosure, useDisclosure,
useOutsideClick, useOutsideClick,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import _debounce from 'lodash/debounce'; import { debounce } from 'es-toolkit';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import type { FormEvent } from 'react'; import type { FormEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -115,7 +115,7 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -115,7 +115,7 @@ const SearchBar = ({ isHomepage }: Props) => {
} }
calculateMenuWidth(); calculateMenuWidth();
const resizeHandler = _debounce(calculateMenuWidth, 200); const resizeHandler = debounce(calculateMenuWidth, 200);
const resizeObserver = new ResizeObserver(resizeHandler); const resizeObserver = new ResizeObserver(resizeHandler);
resizeObserver.observe(inputRef.current); resizeObserver.observe(inputRef.current);
......
import { InputGroup, Input, InputLeftElement, chakra, useColorModeValue, forwardRef, InputRightElement, Center } from '@chakra-ui/react'; import { InputGroup, Input, InputLeftElement, chakra, useColorModeValue, forwardRef, InputRightElement, Center } from '@chakra-ui/react';
import throttle from 'lodash/throttle'; import { throttle } from 'es-toolkit';
import React from 'react'; import React from 'react';
import type { ChangeEvent, FormEvent, FocusEvent } from 'react'; import type { ChangeEvent, FormEvent, FocusEvent } from 'react';
......
import { Box, Tab, TabList, Tabs, Text, useColorModeValue } from '@chakra-ui/react'; import { Box, Tab, TabList, Tabs, Text, useColorModeValue } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import throttle from 'lodash/throttle'; import { throttle } from 'es-toolkit';
import React from 'react'; import React from 'react';
import { scroller, Element } from 'react-scroll'; import { scroller, Element } from 'react-scroll';
......
import _upperFirst from 'lodash/upperFirst'; import { upperFirst } from 'es-toolkit';
export function formatName(_name: string) { export function formatName(_name: string) {
const name = _name const name = _name
.replaceAll('_', ' ') .replaceAll('_', ' ')
.replaceAll(/\burl|nft|id\b/gi, (str) => str.toUpperCase()); .replaceAll(/\burl|nft|id\b/gi, (str) => str.toUpperCase());
return _upperFirst(name.trim()); return upperFirst(name.trim());
} }
const PINNED_FIELDS = [ 'name', 'description' ]; const PINNED_FIELDS = [ 'name', 'description' ];
......
import { Table, Tbody, Tr, Th, Box, Text, Show, Hide } from '@chakra-ui/react'; import { Table, Tbody, Tr, Th, Box, Text, Show, Hide } from '@chakra-ui/react';
import _chunk from 'lodash/chunk'; import { chunk } from 'es-toolkit';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import type { PaginationParams } from 'ui/shared/pagination/types'; import type { PaginationParams } from 'ui/shared/pagination/types';
...@@ -34,7 +34,7 @@ export default function TxAssetFlows(props: FlowViewProps) { ...@@ -34,7 +34,7 @@ export default function TxAssetFlows(props: FlowViewProps) {
const [ page, setPage ] = useState<number>(1); const [ page, setPage ] = useState<number>(1);
const ViewData = useMemo(() => (queryData ? generateFlowViewData(queryData) : []), [ queryData ]); const ViewData = useMemo(() => (queryData ? generateFlowViewData(queryData) : []), [ queryData ]);
const chunkedViewData = _chunk(ViewData, 50); const chunkedViewData = chunk(ViewData, 50);
const paginationProps: PaginationParams = useMemo(() => ({ const paginationProps: PaginationParams = useMemo(() => ({
onNextPageClick: () => setPage(page + 1), onNextPageClick: () => setPage(page + 1),
......
import _findIndex from 'lodash/findIndex';
import type { NovesNft, NovesResponseData, NovesSentReceived, NovesToken } from 'types/api/noves'; import type { NovesNft, NovesResponseData, NovesSentReceived, NovesToken } from 'types/api/noves';
export interface NovesAction { export interface NovesAction {
...@@ -27,7 +25,7 @@ export function generateFlowViewData(data: NovesResponseData): Array<NovesFlowVi ...@@ -27,7 +25,7 @@ export function generateFlowViewData(data: NovesResponseData): Array<NovesFlowVi
const txItems = [ ...sent, ...received ]; const txItems = [ ...sent, ...received ];
const paidGasIndex = _findIndex(txItems, (item) => item.action === 'paidGas'); const paidGasIndex = txItems.findIndex((item) => item.action === 'paidGas');
if (paidGasIndex >= 0) { if (paidGasIndex >= 0) {
const element = txItems.splice(paidGasIndex, 1)[0]; const element = txItems.splice(paidGasIndex, 1)[0];
element.to.name = 'Validators'; element.to.name = 'Validators';
......
import _groupBy from 'lodash/groupBy'; import { groupBy, mapValues } from 'es-toolkit';
import _keysIn from 'lodash/keysIn';
import _mapValues from 'lodash/mapValues';
import type { NovesResponseData } from 'types/api/noves'; import type { NovesResponseData } from 'types/api/noves';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
...@@ -49,28 +47,28 @@ export function getTokensData(data: NovesResponseData): TokensData { ...@@ -49,28 +47,28 @@ export function getTokensData(data: NovesResponseData): TokensData {
}); });
// Group tokens by property into arrays // Group tokens by property into arrays
const tokensGroupByname = _groupBy(tokens, 'name'); const tokensGroupByName = groupBy(tokens, (item) => item.name || 'null');
const tokensGroupBySymbol = _groupBy(tokens, 'symbol'); const tokensGroupBySymbol = groupBy(tokens, (item) => item.symbol || 'null');
const tokensGroupById = _groupBy(tokens, 'id'); const tokensGroupById = groupBy(tokens, (item) => item.id || 'null');
// Map properties to an object and remove duplicates // Map properties to an object and remove duplicates
const mappedNames = _mapValues(tokensGroupByname, (i) => { const mappedNames = mapValues(tokensGroupByName, (i) => {
return i[0]; return i[0];
}); });
const mappedSymbols = _mapValues(tokensGroupBySymbol, (i) => { const mappedSymbols = mapValues(tokensGroupBySymbol, (i) => {
return i[0]; return i[0];
}); });
const mappedIds = _mapValues(tokensGroupById, (i) => { const mappedIds = mapValues(tokensGroupById, (i) => {
return i[0]; return i[0];
}); });
const filters = [ 'undefined', 'null' ]; const filters = [ 'undefined', 'null' ];
// Array of keys to match in string // Array of keys to match in string
const nameList = _keysIn(mappedNames).filter(i => !filters.includes(i)); const nameList = Object.keys(mappedNames).filter(i => !filters.includes(i));
const symbolList = _keysIn(mappedSymbols).filter(i => !filters.includes(i)); const symbolList = Object.keys(mappedSymbols).filter(i => !filters.includes(i));
const idList = _keysIn(mappedIds).filter(i => !filters.includes(i)); const idList = Object.keys(mappedIds).filter(i => !filters.includes(i));
return { return {
nameList, nameList,
......
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import _chunk from 'lodash/chunk'; import { uniq, chunk } from 'es-toolkit';
import _uniq from 'lodash/uniq';
import React from 'react'; import React from 'react';
import type { NovesDescribeTxsResponse } from 'types/api/noves'; import type { NovesDescribeTxsResponse } from 'types/api/noves';
...@@ -16,8 +15,8 @@ const translateEnabled = feature.isEnabled && feature.provider === 'noves'; ...@@ -16,8 +15,8 @@ const translateEnabled = feature.isEnabled && feature.provider === 'noves';
export default function useDescribeTxs(items: Array<Transaction> | undefined, viewAsAccountAddress: string | undefined, isPlaceholderData: boolean) { export default function useDescribeTxs(items: Array<Transaction> | undefined, viewAsAccountAddress: string | undefined, isPlaceholderData: boolean) {
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const txsHash = _uniq(items?.map(i => i.hash)); const txsHash = items ? uniq(items.map(i => i.hash)) : [];
const txChunks = _chunk(txsHash, 10); const txChunks = chunk(txsHash, 10);
const queryKey = { const queryKey = {
viewAsAccountAddress, viewAsAccountAddress,
......
...@@ -10376,6 +10376,11 @@ es-to-primitive@^1.2.1: ...@@ -10376,6 +10376,11 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1" is-date-object "^1.0.1"
is-symbol "^1.0.2" is-symbol "^1.0.2"
es-toolkit@1.31.0:
version "1.31.0"
resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.31.0.tgz#f4fc1382aea09cb239afa38f3c724a5658ff3163"
integrity sha512-vwS0lv/tzjM2/t4aZZRAgN9I9TP0MSkWuvt6By+hEXfG/uLs8yg2S1/ayRXH/x3pinbLgVJYT+eppueg3cM6tg==
esbuild@^0.21.3: esbuild@^0.21.3:
version "0.21.5" version "0.21.5"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
...@@ -13573,7 +13578,7 @@ lodash.throttle@^4.1.1: ...@@ -13573,7 +13578,7 @@ lodash.throttle@^4.1.1:
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.21: lodash@^4.15.0, lodash@^4.17.21:
version "4.17.21" version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
......
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