Commit 02393619 authored by Max Alekseenko's avatar Max Alekseenko Committed by GitHub

Bump `react` to v19 (#2782)

Co-authored-by: default avatartom <tom@ohhhh.me>
parent dd445832
...@@ -4,7 +4,7 @@ import React from 'react'; ...@@ -4,7 +4,7 @@ import React from 'react';
export default function useClientRect<E extends Element>(): [ DOMRect | null, LegacyRef<E> | undefined ] { export default function useClientRect<E extends Element>(): [ DOMRect | null, LegacyRef<E> | undefined ] {
const [ rect, setRect ] = React.useState<DOMRect | null>(null); const [ rect, setRect ] = React.useState<DOMRect | null>(null);
const nodeRef = React.useRef<E>(); const nodeRef = React.useRef<E>(null);
const ref = React.useCallback((node: E) => { const ref = React.useCallback((node: E) => {
if (node !== null) { if (node !== null) {
......
...@@ -3,7 +3,7 @@ import React from 'react'; ...@@ -3,7 +3,7 @@ import React from 'react';
// run effect only if value is updated since initial mount // run effect only if value is updated since initial mount
const useUpdateValueEffect = (effect: () => void, value: string) => { const useUpdateValueEffect = (effect: () => void, value: string) => {
const mountedRef = React.useRef(false); const mountedRef = React.useRef(false);
const valueRef = React.useRef<string>(); const valueRef = React.useRef<string>(undefined);
const isChangedRef = React.useRef(false); const isChangedRef = React.useRef(false);
React.useEffect(() => { React.useEffect(() => {
......
...@@ -17,8 +17,8 @@ interface Params { ...@@ -17,8 +17,8 @@ interface Params {
export default function useSocketChannel({ topic, params, isDisabled, onJoin, onSocketClose, onSocketError }: Params) { export default function useSocketChannel({ topic, params, isDisabled, onJoin, onSocketClose, onSocketError }: Params) {
const socket = useSocket(); const socket = useSocket();
const [ channel, setChannel ] = useState<Channel>(); const [ channel, setChannel ] = useState<Channel>();
const onCloseRef = useRef<string>(); const onCloseRef = useRef<string>(undefined);
const onErrorRef = useRef<string>(); const onErrorRef = useRef<string>(undefined);
const onJoinRef = useRef(onJoin); const onJoinRef = useRef(onJoin);
onJoinRef.current = onJoin; onJoinRef.current = onJoin;
......
...@@ -6,25 +6,25 @@ export function monaco(): CspDev.DirectiveDescriptor { ...@@ -6,25 +6,25 @@ export function monaco(): CspDev.DirectiveDescriptor {
return { return {
'script-src': [ 'script-src': [
KEY_WORDS.BLOB, KEY_WORDS.BLOB,
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/loader.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/loader.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/editor/editor.main.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/editor/editor.main.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/editor/editor.main.nls.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/editor/editor.main.nls.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/basic-languages/solidity/solidity.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/basic-languages/solidity/solidity.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/basic-languages/elixir/elixir.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/basic-languages/elixir/elixir.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/basic-languages/javascript/javascript.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/basic-languages/javascript/javascript.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/basic-languages/typescript/typescript.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/basic-languages/typescript/typescript.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/basic-languages/rust/rust.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/basic-languages/rust/rust.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/language/json/jsonMode.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/language/json/jsonMode.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/language/json/jsonWorker.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/language/json/jsonWorker.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/language/typescript/tsMode.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/language/typescript/tsMode.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/language/typescript/tsWorker.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/language/typescript/tsWorker.js',
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/base/worker/workerMain.js', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/base/worker/workerMain.js',
], ],
'style-src': [ 'style-src': [
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/editor/editor.main.css', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/editor/editor.main.css',
], ],
'font-src': [ 'font-src': [
'https://cdn.jsdelivr.net/npm/monaco-editor@0.33.0/min/vs/base/browser/ui/codicons/codicon/codicon.ttf', 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs/base/browser/ui/codicons/codicon/codicon.ttf',
], ],
}; };
} }
...@@ -44,8 +44,8 @@ ...@@ -44,8 +44,8 @@
"dependencies": { "dependencies": {
"@blockscout/bens-types": "1.4.1", "@blockscout/bens-types": "1.4.1",
"@blockscout/points-types": "1.3.0-alpha.2", "@blockscout/points-types": "1.3.0-alpha.2",
"@blockscout/tac-operation-lifecycle-types": "0.0.1-alpha.6",
"@blockscout/stats-types": "^2.9.0", "@blockscout/stats-types": "^2.9.0",
"@blockscout/tac-operation-lifecycle-types": "0.0.1-alpha.6",
"@blockscout/visualizer-types": "0.2.0", "@blockscout/visualizer-types": "0.2.0",
"@chakra-ui/react": "3.15.0", "@chakra-ui/react": "3.15.0",
"@cloudnouns/kit": "1.1.6", "@cloudnouns/kit": "1.1.6",
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
"@hypelab/sdk-react": "^1.0.0", "@hypelab/sdk-react": "^1.0.0",
"@metamask/post-message-stream": "^7.0.0", "@metamask/post-message-stream": "^7.0.0",
"@metamask/providers": "^10.2.1", "@metamask/providers": "^10.2.1",
"@monaco-editor/react": "^4.4.6", "@monaco-editor/react": "^4.7.0",
"@next/bundle-analyzer": "15.0.3", "@next/bundle-analyzer": "15.0.3",
"@opentelemetry/api": "^1.4.1", "@opentelemetry/api": "^1.4.1",
"@opentelemetry/auto-instrumentations-node": "0.43.0", "@opentelemetry/auto-instrumentations-node": "0.43.0",
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
"chakra-react-select": "^4.4.3", "chakra-react-select": "^4.4.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"d3": "^7.6.1", "d3": "^7.6.1",
"dappscout-iframe": "0.2.6", "dappscout-iframe": "0.3.0",
"dayjs": "^1.11.5", "dayjs": "^1.11.5",
"dom-to-image": "^2.6.0", "dom-to-image": "^2.6.0",
"es-toolkit": "1.31.0", "es-toolkit": "1.31.0",
...@@ -106,9 +106,9 @@ ...@@ -106,9 +106,9 @@
"pino-pretty": "^9.1.1", "pino-pretty": "^9.1.1",
"prom-client": "15.1.1", "prom-client": "15.1.1",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
"react": "18.3.1", "react": "19.1.0",
"react-device-detect": "^2.2.3", "react-device-detect": "^2.2.3",
"react-dom": "18.3.1", "react-dom": "19.1.0",
"react-google-recaptcha": "3.1.0", "react-google-recaptcha": "3.1.0",
"react-hook-form": "7.52.1", "react-hook-form": "7.52.1",
"react-icons": "5.4.0", "react-icons": "5.4.0",
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
"react-scroll": "^1.8.7", "react-scroll": "^1.8.7",
"rollbar": "2.26.4", "rollbar": "2.26.4",
"swagger-ui-react": "5.20.3", "swagger-ui-react": "5.20.3",
"use-font-face-observer": "^1.2.1", "use-font-face-observer": "^1.3.0",
"valibot": "0.38.0", "valibot": "0.38.0",
"viem": "2.23.14", "viem": "2.23.14",
"wagmi": "2.14.15", "wagmi": "2.14.15",
...@@ -147,8 +147,8 @@ ...@@ -147,8 +147,8 @@
"@types/node": "20.16.7", "@types/node": "20.16.7",
"@types/phoenix": "^1.5.4", "@types/phoenix": "^1.5.4",
"@types/qrcode": "^1.5.0", "@types/qrcode": "^1.5.0",
"@types/react": "18.3.12", "@types/react": "19.1.7",
"@types/react-dom": "18.3.1", "@types/react-dom": "19.1.6",
"@types/react-google-recaptcha": "^2.1.5", "@types/react-google-recaptcha": "^2.1.5",
"@types/swagger-ui-react": "5.18.0", "@types/swagger-ui-react": "5.18.0",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
......
import type { Locator } from '@playwright/test';
import { expect } from 'playwright/lib';
export async function stableHover(element: Locator) {
await expect(element).toBeVisible();
await expect(element).toBeAttached();
const page = element.page();
const box = await element.boundingBox();
await page.mouse.move(box!.x + box!.width / 2, box!.y + box!.height / 2);
await page.waitForTimeout(50);
}
...@@ -13,7 +13,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>( ...@@ -13,7 +13,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
// FIXME: I have to clone the children instead of using _icon props because of style overrides // FIXME: I have to clone the children instead of using _icon props because of style overrides
// in some pw tests for some reason the _icon style will be applied before the style of child (IconSvg component) // in some pw tests for some reason the _icon style will be applied before the style of child (IconSvg component)
const child = React.Children.only<React.ReactElement>(children as React.ReactElement); const child = React.Children.only<React.ReactElement>(children as React.ReactElement);
const clonedChildren = size ? React.cloneElement(child, { boxSize: 5 }) : child; const clonedChildren = size ? React.cloneElement(child, { boxSize: 5 } as React.HTMLAttributes<HTMLElement>) : child;
const sizeStyle = (() => { const sizeStyle = (() => {
switch (size) { switch (size) {
......
...@@ -7,10 +7,10 @@ import type { TabItemRegular } from './types'; ...@@ -7,10 +7,10 @@ import type { TabItemRegular } from './types';
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 { useIsSticky } from '../..//hooks/useIsSticky';
import { Skeleton } from '../../chakra/skeleton'; import { Skeleton } from '../../chakra/skeleton';
import type { TabsProps } from '../../chakra/tabs'; import type { TabsProps } from '../../chakra/tabs';
import { TabsCounter, TabsList, TabsTrigger } from '../../chakra/tabs'; import { TabsCounter, TabsList, TabsTrigger } from '../../chakra/tabs';
import { useIsSticky } from '../../hooks/useIsSticky';
import AdaptiveTabsMenu from './AdaptiveTabsMenu'; import AdaptiveTabsMenu from './AdaptiveTabsMenu';
import useAdaptiveTabs from './useAdaptiveTabs'; import useAdaptiveTabs from './useAdaptiveTabs';
import useScrollToActiveTab from './useScrollToActiveTab'; import useScrollToActiveTab from './useScrollToActiveTab';
......
...@@ -3,7 +3,7 @@ import React from 'react'; ...@@ -3,7 +3,7 @@ import React from 'react';
interface Props { interface Props {
activeTabIndex: number; activeTabIndex: number;
tabsRefs: Array<React.RefObject<HTMLButtonElement>>; tabsRefs: Array<React.RefObject<HTMLButtonElement>>;
listRef: React.RefObject<HTMLDivElement>; listRef: React.RefObject<HTMLDivElement | null>;
isMobile?: boolean; isMobile?: boolean;
isLoading?: boolean; isLoading?: boolean;
} }
......
...@@ -74,7 +74,7 @@ export const TruncatedTextTooltip = React.memo(({ children, label, placement, in ...@@ -74,7 +74,7 @@ export const TruncatedTextTooltip = React.memo(({ children, label, placement, in
onClick: handleClick, onClick: handleClick,
onMouseEnter: onOpen, onMouseEnter: onOpen,
onMouseLeave: onClose, onMouseLeave: onClose,
}, } as React.HTMLAttributes<HTMLElement>,
); );
if (isTruncated) { if (isTruncated) {
......
import { throttle } from 'es-toolkit'; import { throttle } from 'es-toolkit';
import React from 'react'; import React from 'react';
export function useIsSticky(ref: React.RefObject<HTMLDivElement>, offset = 0, isEnabled = true) { export function useIsSticky(ref: React.RefObject<HTMLElement | null>, offset = 0, isEnabled = true): boolean {
const [ isSticky, setIsSticky ] = React.useState(false); const [ isSticky, setIsSticky ] = React.useState(false);
const handleScroll = React.useCallback(() => { const handleScroll = React.useCallback(() => {
......
...@@ -32,7 +32,7 @@ interface Props { ...@@ -32,7 +32,7 @@ interface Props {
} }
const ContractMethodFieldInput = ({ data, hideLabel, path: name, className, isDisabled, isOptional: isOptionalProp, level }: Props) => { const ContractMethodFieldInput = ({ data, hideLabel, path: name, className, isDisabled, isOptional: isOptionalProp, level }: Props) => {
const ref = React.useRef<HTMLInputElement>(); const ref = React.useRef<HTMLInputElement>(null);
const [ intPower, setIntPower ] = React.useState<number>(18); const [ intPower, setIntPower ] = React.useState<number>(18);
......
...@@ -49,8 +49,8 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro ...@@ -49,8 +49,8 @@ const ContractVerificationForm = ({ method: methodFromQuery, config, hash }: Pro
defaultValues: getDefaultValues(methodFromQuery, config, hash, []), defaultValues: getDefaultValues(methodFromQuery, config, hash, []),
}); });
const { handleSubmit, watch, formState, setError, reset, getFieldState, getValues, clearErrors } = formApi; const { handleSubmit, watch, formState, setError, reset, getFieldState, getValues, clearErrors } = formApi;
const submitPromiseResolver = React.useRef<(value: unknown) => void>(); const submitPromiseResolver = React.useRef<((value: unknown) => void)>(undefined);
const methodNameRef = React.useRef<string>(); const methodNameRef = React.useRef<string>(undefined);
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const { trackContract } = useRewardsActivity(); const { trackContract } = useRewardsActivity();
......
...@@ -79,7 +79,7 @@ const Chart = () => { ...@@ -79,7 +79,7 @@ const Chart = () => {
const interval = intervalState || getIntervalByResolution(resolution); const interval = intervalState || getIntervalByResolution(resolution);
const ref = React.useRef(null); const ref = React.useRef<HTMLDivElement>(null);
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const isInBrowser = isBrowser(); const isInBrowser = isBrowser();
......
import type { Page } from '@playwright/test';
import React from 'react'; import React from 'react';
import { apps as appsMock } from 'mocks/apps/apps'; import { apps as appsMock } from 'mocks/apps/apps';
...@@ -7,8 +8,13 @@ import { test, expect } from 'playwright/lib'; ...@@ -7,8 +8,13 @@ import { test, expect } from 'playwright/lib';
import SearchResults from './SearchResults'; import SearchResults from './SearchResults';
async function resetScroll(page: Page) {
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.evaluate(() => window.scrollTo(0, 0));
}
test.describe('search by name', () => { test.describe('search by name', () => {
test('+@mobile +@dark-mode', async({ render, mockApiResponse, mockAssetResponse, mockEnvs }) => { test('+@mobile +@dark-mode', async({ render, mockApiResponse, mockAssetResponse, mockEnvs, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: 'o' }, query: { q: 'o' },
...@@ -31,12 +37,13 @@ test.describe('search by name', () => { ...@@ -31,12 +37,13 @@ test.describe('search by name', () => {
await mockApiResponse('general:search', data, { queryParams: { q: 'o' } }); await mockApiResponse('general:search', data, { queryParams: { q: 'o' } });
await mockAssetResponse(searchMock.token1.icon_url as string, './playwright/mocks/image_s.jpg'); await mockAssetResponse(searchMock.token1.icon_url as string, './playwright/mocks/image_s.jpg');
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
}); });
test('search by address hash +@mobile', async({ render, mockApiResponse }) => { test('search by address hash +@mobile', async({ render, mockApiResponse, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.address1.address_hash }, query: { q: searchMock.address1.address_hash },
...@@ -49,11 +56,12 @@ test('search by address hash +@mobile', async({ render, mockApiResponse }) => { ...@@ -49,11 +56,12 @@ test('search by address hash +@mobile', async({ render, mockApiResponse }) => {
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.address1.address_hash } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.address1.address_hash } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by meta tag +@mobile', async({ render, mockApiResponse }) => { test('search by meta tag +@mobile', async({ render, mockApiResponse, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: 'utko' }, query: { q: 'utko' },
...@@ -66,11 +74,12 @@ test('search by meta tag +@mobile', async({ render, mockApiResponse }) => { ...@@ -66,11 +74,12 @@ test('search by meta tag +@mobile', async({ render, mockApiResponse }) => {
await mockApiResponse('general:search', data, { queryParams: { q: 'utko' } }); await mockApiResponse('general:search', data, { queryParams: { q: 'utko' } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by block number +@mobile', async({ render, mockApiResponse }) => { test('search by block number +@mobile', async({ render, mockApiResponse, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: String(searchMock.block1.block_number) }, query: { q: String(searchMock.block1.block_number) },
...@@ -82,11 +91,12 @@ test('search by block number +@mobile', async({ render, mockApiResponse }) => { ...@@ -82,11 +91,12 @@ test('search by block number +@mobile', async({ render, mockApiResponse }) => {
}; };
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.block1.block_number } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.block1.block_number } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by block hash +@mobile', async({ render, mockApiResponse }) => { test('search by block hash +@mobile', async({ render, mockApiResponse, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.block1.block_hash }, query: { q: searchMock.block1.block_hash },
...@@ -98,11 +108,12 @@ test('search by block hash +@mobile', async({ render, mockApiResponse }) => { ...@@ -98,11 +108,12 @@ test('search by block hash +@mobile', async({ render, mockApiResponse }) => {
}; };
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.block1.block_hash } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.block1.block_hash } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by tx hash +@mobile', async({ render, mockApiResponse }) => { test('search by tx hash +@mobile', async({ render, mockApiResponse, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.tx1.transaction_hash }, query: { q: searchMock.tx1.transaction_hash },
...@@ -114,11 +125,12 @@ test('search by tx hash +@mobile', async({ render, mockApiResponse }) => { ...@@ -114,11 +125,12 @@ test('search by tx hash +@mobile', async({ render, mockApiResponse }) => {
}; };
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.tx1.transaction_hash } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.tx1.transaction_hash } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by tac operation hash +@mobile', async({ render, mockApiResponse, mockEnvs }) => { test('search by tac operation hash +@mobile', async({ render, mockApiResponse, mockEnvs, page }) => {
await mockEnvs(ENVS_MAP.tac); await mockEnvs(ENVS_MAP.tac);
const hooksConfig = { const hooksConfig = {
router: { router: {
...@@ -131,11 +143,12 @@ test('search by tac operation hash +@mobile', async({ render, mockApiResponse, m ...@@ -131,11 +143,12 @@ test('search by tac operation hash +@mobile', async({ render, mockApiResponse, m
}; };
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.tacOperation1.tac_operation.operation_id } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.tacOperation1.tac_operation.operation_id } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by blob hash +@mobile', async({ render, mockApiResponse, mockEnvs }) => { test('search by blob hash +@mobile', async({ render, mockApiResponse, mockEnvs, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.blob1.blob_hash }, query: { q: searchMock.blob1.blob_hash },
...@@ -148,11 +161,12 @@ test('search by blob hash +@mobile', async({ render, mockApiResponse, mockEnvs } ...@@ -148,11 +161,12 @@ test('search by blob hash +@mobile', async({ render, mockApiResponse, mockEnvs }
await mockEnvs(ENVS_MAP.dataAvailability); await mockEnvs(ENVS_MAP.dataAvailability);
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.blob1.blob_hash } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.blob1.blob_hash } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by domain name +@mobile', async({ render, mockApiResponse, mockEnvs }) => { test('search by domain name +@mobile', async({ render, mockApiResponse, mockEnvs, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.domain1.ens_info.name }, query: { q: searchMock.domain1.ens_info.name },
...@@ -165,10 +179,12 @@ test('search by domain name +@mobile', async({ render, mockApiResponse, mockEnvs ...@@ -165,10 +179,12 @@ test('search by domain name +@mobile', async({ render, mockApiResponse, mockEnvs
await mockEnvs(ENVS_MAP.nameService); await mockEnvs(ENVS_MAP.nameService);
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.domain1.ens_info.name } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.domain1.ens_info.name } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('search by user op hash +@mobile', async({ render, mockApiResponse, mockEnvs }) => { test('search by user op hash +@mobile', async({ render, mockApiResponse, mockEnvs, page }) => {
const hooksConfig = { const hooksConfig = {
router: { router: {
query: { q: searchMock.userOp1.user_operation_hash }, query: { q: searchMock.userOp1.user_operation_hash },
...@@ -181,12 +197,13 @@ test('search by user op hash +@mobile', async({ render, mockApiResponse, mockEnv ...@@ -181,12 +197,13 @@ test('search by user op hash +@mobile', async({ render, mockApiResponse, mockEnv
await mockEnvs(ENVS_MAP.userOps); await mockEnvs(ENVS_MAP.userOps);
await mockApiResponse('general:search', data, { queryParams: { q: searchMock.userOp1.user_operation_hash } }); await mockApiResponse('general:search', data, { queryParams: { q: searchMock.userOp1.user_operation_hash } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test.describe('with apps', () => { test.describe('with apps', () => {
test('default view +@mobile', async({ render, mockApiResponse, mockConfigResponse, mockAssetResponse, mockEnvs }) => { test('default view +@mobile', async({ render, mockApiResponse, mockConfigResponse, mockAssetResponse, mockEnvs, page }) => {
const MARKETPLACE_CONFIG_URL = 'https://localhost:4000/marketplace-config.json'; const MARKETPLACE_CONFIG_URL = 'https://localhost:4000/marketplace-config.json';
const hooksConfig = { const hooksConfig = {
router: { router: {
...@@ -216,6 +233,7 @@ test.describe('with apps', () => { ...@@ -216,6 +233,7 @@ test.describe('with apps', () => {
await mockAssetResponse(appsMock[0].logo, './playwright/mocks/image_s.jpg'); await mockAssetResponse(appsMock[0].logo, './playwright/mocks/image_s.jpg');
await mockAssetResponse(appsMock[1].logo, './playwright/mocks/image_s.jpg'); await mockAssetResponse(appsMock[1].logo, './playwright/mocks/image_s.jpg');
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
...@@ -229,20 +247,22 @@ test.describe('block countdown', () => { ...@@ -229,20 +247,22 @@ test.describe('block countdown', () => {
}, },
}; };
test('no results', async({ render, mockApiResponse }) => { test('no results', async({ render, mockApiResponse, page }) => {
await mockApiResponse('general:search', { items: [], next_page_params: null }, { queryParams: { q: blockHeight } }); await mockApiResponse('general:search', { items: [], next_page_params: null }, { queryParams: { q: blockHeight } });
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
test('with results +@mobile', async({ render, mockApiResponse }) => { test('with results +@mobile', async({ render, mockApiResponse, page }) => {
await mockApiResponse( await mockApiResponse(
'general:search', 'general:search',
{ items: [ { ...searchMock.token1, name: '1234567890123456789' } ], next_page_params: null }, { items: [ { ...searchMock.token1, name: '1234567890123456789' } ], next_page_params: null },
{ queryParams: { q: blockHeight } }, { queryParams: { q: blockHeight } },
); );
const component = await render(<SearchResults/>, { hooksConfig }); const component = await render(<SearchResults/>, { hooksConfig });
await resetScroll(page);
await expect(component.locator('main')).toHaveScreenshot(); await expect(component.locator('main')).toHaveScreenshot();
}); });
......
...@@ -65,7 +65,9 @@ const SearchResultsInput = ({ searchTerm, handleSubmit, handleSearchTermChange } ...@@ -65,7 +65,9 @@ const SearchResultsInput = ({ searchTerm, handleSubmit, handleSearchTermChange }
const resizeHandler = debounce(calculateMenuWidth, 200); const resizeHandler = debounce(calculateMenuWidth, 200);
const resizeObserver = new ResizeObserver(resizeHandler); const resizeObserver = new ResizeObserver(resizeHandler);
if (inputRef.current) {
resizeObserver.observe(inputRef.current); resizeObserver.observe(inputRef.current);
}
return function cleanup() { return function cleanup() {
resizeObserver.unobserve(inputEl); resizeObserver.unobserve(inputEl);
......
...@@ -9,7 +9,7 @@ const INCREMENT = 3; ...@@ -9,7 +9,7 @@ const INCREMENT = 3;
const ChartLineLoader = ({ className }: { className?: string }) => { const ChartLineLoader = ({ className }: { className?: string }) => {
const ref = React.useRef<SVGPathElement>(null); const ref = React.useRef<SVGPathElement>(null);
const raf = React.useRef<number>(); const raf = React.useRef<number>(undefined);
const offset = React.useRef(0); const offset = React.useRef(0);
const [ lineBgColor ] = useToken('colors', useColorModeValue('gray.200', 'gray.500')); const [ lineBgColor ] = useToken('colors', useColorModeValue('gray.200', 'gray.500'));
......
...@@ -22,7 +22,7 @@ export type Props = { ...@@ -22,7 +22,7 @@ export type Props = {
description?: string; description?: string;
units?: string; units?: string;
isLoading: boolean; isLoading: boolean;
chartRef: React.RefObject<HTMLDivElement>; chartRef: React.RefObject<HTMLDivElement | null>;
chartUrl?: string; chartUrl?: string;
resolution?: Resolution; resolution?: Resolution;
zoomRange?: [ Date, Date ]; zoomRange?: [ Date, Date ];
......
...@@ -21,8 +21,8 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) => ...@@ -21,8 +21,8 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
const ref = React.useRef(null); const ref = React.useRef(null);
const isActive = React.useRef(false); const isActive = React.useRef(false);
const startX = React.useRef<number>(); const startX = React.useRef<number>(undefined);
const endX = React.useRef<number>(); const endX = React.useRef<number>(undefined);
const getIndexByX = React.useCallback((x: number) => { const getIndexByX = React.useCallback((x: number) => {
const xDate = scale.invert(x); const xDate = scale.invert(x);
......
...@@ -38,7 +38,7 @@ const ChartTooltip = ({ ...@@ -38,7 +38,7 @@ const ChartTooltip = ({
...props ...props
}: Props) => { }: Props) => {
const ref = React.useRef<SVGGElement>(null); const ref = React.useRef<SVGGElement>(null);
const trackerId = React.useRef<number>(); const trackerId = React.useRef<number>(undefined);
const isVisible = React.useRef(false); const isVisible = React.useRef(false);
const transitionDuration = !noAnimation ? 100 : null; const transitionDuration = !noAnimation ? 100 : null;
......
...@@ -24,7 +24,7 @@ interface UseRenderBackdropParams { ...@@ -24,7 +24,7 @@ interface UseRenderBackdropParams {
transitionDuration: number | null; transitionDuration: number | null;
} }
export function useRenderBackdrop(ref: React.RefObject<SVGGElement>, { seriesNum, transitionDuration }: UseRenderBackdropParams) { export function useRenderBackdrop(ref: React.RefObject<SVGGElement | null>, { seriesNum, transitionDuration }: UseRenderBackdropParams) {
return React.useCallback((width: number, isIncompleteData: boolean) => { return React.useCallback((width: number, isIncompleteData: boolean) => {
const height = calculateContainerHeight(seriesNum, isIncompleteData); const height = calculateContainerHeight(seriesNum, isIncompleteData);
......
...@@ -22,7 +22,7 @@ interface UseRenderContentParams { ...@@ -22,7 +22,7 @@ interface UseRenderContentParams {
transitionDuration: number | null; transitionDuration: number | null;
} }
export function useRenderContent(ref: React.RefObject<SVGGElement>, { chart, transitionDuration }: UseRenderContentParams) { export function useRenderContent(ref: React.RefObject<SVGGElement | null>, { chart, transitionDuration }: UseRenderContentParams) {
return React.useCallback((x: number, y: number) => { return React.useCallback((x: number, y: number) => {
const tooltipContent = d3.select(ref.current).select('.ChartTooltip__content'); const tooltipContent = d3.select(ref.current).select('.ChartTooltip__content');
......
...@@ -9,7 +9,7 @@ const ChartTooltipLine = () => { ...@@ -9,7 +9,7 @@ const ChartTooltipLine = () => {
export default React.memo(ChartTooltipLine); export default React.memo(ChartTooltipLine);
export function useRenderLine(ref: React.RefObject<SVGGElement>, chartHeight: number | undefined) { export function useRenderLine(ref: React.RefObject<SVGGElement | null>, chartHeight: number | undefined) {
return React.useCallback((x: number) => { return React.useCallback((x: number) => {
d3.select(ref.current) d3.select(ref.current)
.select('.ChartTooltip__line') .select('.ChartTooltip__line')
......
...@@ -43,7 +43,7 @@ interface RenderPointsReturnType { ...@@ -43,7 +43,7 @@ interface RenderPointsReturnType {
currentPoints: Array<CurrentPoint>; currentPoints: Array<CurrentPoint>;
} }
export function useRenderPoints(ref: React.RefObject<SVGGElement>, params: UseRenderPointsParams) { export function useRenderPoints(ref: React.RefObject<SVGGElement | null>, params: UseRenderPointsParams) {
return React.useCallback((x: number): RenderPointsReturnType => { return React.useCallback((x: number): RenderPointsReturnType => {
const xDate = params.xScale.invert(x); const xDate = params.xScale.invert(x);
const bisectDate = d3.bisector<TimeChartItem, unknown>((d) => d.date).left; const bisectDate = d3.bisector<TimeChartItem, unknown>((d) => d.date).left;
......
...@@ -51,7 +51,7 @@ interface UseRenderRowsReturnType { ...@@ -51,7 +51,7 @@ interface UseRenderRowsReturnType {
width: number; width: number;
} }
export function useRenderRows(ref: React.RefObject<SVGGElement>, { data, xScale, minWidth }: UseRenderRowsParams) { export function useRenderRows(ref: React.RefObject<SVGGElement | null>, { data, xScale, minWidth }: UseRenderRowsParams) {
return React.useCallback((x: number, currentPoints: Array<CurrentPoint>): UseRenderRowsReturnType => { return React.useCallback((x: number, currentPoints: Array<CurrentPoint>): UseRenderRowsReturnType => {
// update "transform" prop of all rows // update "transform" prop of all rows
......
...@@ -29,7 +29,7 @@ const ChartTooltipTitle = ({ resolution = Resolution.DAY }: { resolution?: Resol ...@@ -29,7 +29,7 @@ const ChartTooltipTitle = ({ resolution = Resolution.DAY }: { resolution?: Resol
export default React.memo(ChartTooltipTitle); export default React.memo(ChartTooltipTitle);
export function useRenderTitle(ref: React.RefObject<SVGGElement>) { export function useRenderTitle(ref: React.RefObject<SVGGElement | null>) {
return React.useCallback((isVisible: boolean) => { return React.useCallback((isVisible: boolean) => {
d3.select(ref.current) d3.select(ref.current)
.select('.ChartTooltip__title') .select('.ChartTooltip__title')
......
...@@ -11,7 +11,7 @@ interface Props { ...@@ -11,7 +11,7 @@ interface Props {
} }
export default function useBrushX({ limits, anchor, setRange }: Props) { export default function useBrushX({ limits, anchor, setRange }: Props) {
const brushRef = React.useRef<d3.BrushBehavior<unknown>>(); const brushRef = React.useRef<d3.BrushBehavior<unknown>>(undefined);
const [ brushSelectionBg ] = useToken('colors', useColorModeValue('blackAlpha.400', 'whiteAlpha.500')); const [ brushSelectionBg ] = useToken('colors', useColorModeValue('blackAlpha.400', 'whiteAlpha.500'));
React.useEffect(() => { React.useEffect(() => {
......
import React from 'react'; import React from 'react';
import * as domainMock from 'mocks/ens/domain'; import * as domainMock from 'mocks/ens/domain';
import { stableHover } from 'playwright/helpers/stableHover';
import { test, expect } from 'playwright/lib'; import { test, expect } from 'playwright/lib';
import EnsEntity from './EnsEntity'; import EnsEntity from './EnsEntity';
...@@ -43,7 +44,7 @@ test('with long name', async({ render }) => { ...@@ -43,7 +44,7 @@ test('with long name', async({ render }) => {
/>, />,
); );
await component.getByText(name.slice(0, 4)).hover(); await stableHover(component.getByText(name.slice(0, 4)));
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
......
...@@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react'; ...@@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import * as tokenMock from 'mocks/tokens/tokenInfo'; import * as tokenMock from 'mocks/tokens/tokenInfo';
import { stableHover } from 'playwright/helpers/stableHover';
import { test, expect } from 'playwright/lib'; import { test, expect } from 'playwright/lib';
import TokenEntity from './TokenEntity'; import TokenEntity from './TokenEntity';
...@@ -46,10 +47,10 @@ test('with logo, long name and symbol', async({ page, render }) => { ...@@ -46,10 +47,10 @@ test('with logo, long name and symbol', async({ page, render }) => {
/>, />,
); );
await page.getByText(/this/i).hover(); await stableHover(page.getByText(/this/i));
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot();
await page.getByText(/duc/i).hover(); await stableHover(page.getByText(/duc/i));
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot();
}); });
......
...@@ -7,7 +7,7 @@ import type { Params as ApiInfiniteQueryParams } from 'lib/api/useApiInfiniteQue ...@@ -7,7 +7,7 @@ import type { Params as ApiInfiniteQueryParams } from 'lib/api/useApiInfiniteQue
import useApiInfiniteQuery from 'lib/api/useApiInfiniteQuery'; import useApiInfiniteQuery from 'lib/api/useApiInfiniteQuery';
interface Params<Resource extends PaginatedResourceName> extends ApiInfiniteQueryParams<Resource> { interface Params<Resource extends PaginatedResourceName> extends ApiInfiniteQueryParams<Resource> {
rootRef: React.RefObject<HTMLElement>; rootRef: React.RefObject<HTMLElement | null>;
} }
interface ReturnType<Resource extends PaginatedResourceName> { interface ReturnType<Resource extends PaginatedResourceName> {
......
...@@ -22,7 +22,7 @@ export interface Params<Resource extends PaginatedResourceName> { ...@@ -22,7 +22,7 @@ export interface Params<Resource extends PaginatedResourceName> {
pathParams?: UseApiQueryParams<Resource>['pathParams']; pathParams?: UseApiQueryParams<Resource>['pathParams'];
filters?: PaginationFilters<Resource>; filters?: PaginationFilters<Resource>;
sorting?: PaginationSorting<Resource>; sorting?: PaginationSorting<Resource>;
scrollRef?: React.RefObject<HTMLDivElement>; scrollRef?: React.RefObject<HTMLDivElement | null>;
} }
type NextPageParams = Record<string, unknown>; type NextPageParams = Record<string, unknown>;
......
...@@ -4,7 +4,6 @@ import { debounce } from 'es-toolkit'; ...@@ -4,7 +4,6 @@ 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';
import { Element } from 'react-scroll';
import type { Route } from 'nextjs-routes'; import type { Route } from 'nextjs-routes';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -123,7 +122,9 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -123,7 +122,9 @@ const SearchBar = ({ isHomepage }: Props) => {
const resizeHandler = debounce(calculateMenuWidth, 200); const resizeHandler = debounce(calculateMenuWidth, 200);
const resizeObserver = new ResizeObserver(resizeHandler); const resizeObserver = new ResizeObserver(resizeHandler);
if (inputRef.current) {
resizeObserver.observe(inputRef.current); resizeObserver.observe(inputRef.current);
}
return function cleanup() { return function cleanup() {
resizeObserver.unobserve(inputEl); resizeObserver.unobserve(inputEl);
...@@ -170,7 +171,6 @@ const SearchBar = ({ isHomepage }: Props) => { ...@@ -170,7 +171,6 @@ const SearchBar = ({ isHomepage }: Props) => {
overflowY="auto" overflowY="auto"
id={ SCROLL_CONTAINER_ID } id={ SCROLL_CONTAINER_ID }
ref={ scrollRef } ref={ scrollRef }
as={ Element }
px={ 4 } px={ 4 }
> >
{ searchTerm.trim().length === 0 && recentSearchKeywords.length > 0 && ( { searchTerm.trim().length === 0 && recentSearchKeywords.length > 0 && (
......
...@@ -24,7 +24,7 @@ interface Props { ...@@ -24,7 +24,7 @@ interface Props {
data?: TokenInstance; data?: TokenInstance;
token?: TokenInfo; token?: TokenInfo;
isLoading?: boolean; isLoading?: boolean;
scrollRef?: React.RefObject<HTMLDivElement>; scrollRef?: React.RefObject<HTMLDivElement | null>;
} }
const TokenInstanceDetails = ({ data, token, scrollRef, isLoading }: Props) => { const TokenInstanceDetails = ({ data, token, scrollRef, isLoading }: Props) => {
......
...@@ -28,7 +28,7 @@ interface Props { ...@@ -28,7 +28,7 @@ interface Props {
} }
const TokenInstanceMetadataFetcher = ({ hash, id }: Props) => { const TokenInstanceMetadataFetcher = ({ hash, id }: Props) => {
const timeoutId = React.useRef<number>(); const timeoutId = React.useRef<number>(undefined);
const { status, setStatus } = useMetadataUpdateContext() || {}; const { status, setStatus } = useMetadataUpdateContext() || {};
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
......
...@@ -4143,20 +4143,19 @@ ...@@ -4143,20 +4143,19 @@
semver "^7.5.4" semver "^7.5.4"
superstruct "^1.0.3" superstruct "^1.0.3"
"@monaco-editor/loader@^1.3.2": "@monaco-editor/loader@^1.5.0":
version "1.3.2" version "1.5.0"
resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.3.2.tgz#04effbb87052d19cd7d3c9d81c0635490f9bb6d8" resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.5.0.tgz#dcdbc7fe7e905690fb449bed1c251769f325c55d"
integrity sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g== integrity sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==
dependencies: dependencies:
state-local "^1.0.6" state-local "^1.0.6"
"@monaco-editor/react@^4.4.6": "@monaco-editor/react@^4.7.0":
version "4.4.6" version "4.7.0"
resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.4.6.tgz#8ae500b0edf85276d860ed702e7056c316548218" resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.7.0.tgz#35a1ec01bfe729f38bfc025df7b7bac145602a60"
integrity sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA== integrity sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==
dependencies: dependencies:
"@monaco-editor/loader" "^1.3.2" "@monaco-editor/loader" "^1.5.0"
prop-types "^15.7.2"
"@motionone/animation@^10.15.1": "@motionone/animation@^10.15.1":
version "10.15.1" version "10.15.1"
...@@ -7676,6 +7675,11 @@ ...@@ -7676,6 +7675,11 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react-dom@19.1.6":
version "19.1.6"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.6.tgz#4af629da0e9f9c0f506fc4d1caa610399c595d64"
integrity sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==
"@types/react-google-recaptcha@^2.1.5": "@types/react-google-recaptcha@^2.1.5":
version "2.1.5" version "2.1.5"
resolved "https://registry.yarnpkg.com/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.5.tgz#af157dc2e4bde3355f9b815a64f90e85cfa9df8b" resolved "https://registry.yarnpkg.com/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.5.tgz#af157dc2e4bde3355f9b815a64f90e85cfa9df8b"
...@@ -7684,9 +7688,9 @@ ...@@ -7684,9 +7688,9 @@
"@types/react" "*" "@types/react" "*"
"@types/react-scroll@^1.8.4": "@types/react-scroll@^1.8.4":
version "1.8.4" version "1.8.10"
resolved "https://registry.yarnpkg.com/@types/react-scroll/-/react-scroll-1.8.4.tgz#2b6258fb34104d3fcc7a22e8eceaadc669ba3ad1" resolved "https://registry.yarnpkg.com/@types/react-scroll/-/react-scroll-1.8.10.tgz#585a5c4bd0654434f3e55a08e94ed2e048bae7c7"
integrity sha512-DpHA9PYw42/rBrfKbGE/kAEvHRfyDL/ACfKB/ORWUYuCLi/yGrntxSzYXmg/7TLgQsJ5ma13GCDOzFSOz+8XOA== integrity sha512-RD4Z7grbdNGOKwKnUBKar6zNxqaW3n8m9QSrfvljW+gmkj1GArb8AFBomVr6xMOgHPD3v1uV3BrIf01py57daQ==
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
...@@ -7705,6 +7709,13 @@ ...@@ -7705,6 +7709,13 @@
"@types/prop-types" "*" "@types/prop-types" "*"
csstype "^3.0.2" csstype "^3.0.2"
"@types/react@19.1.7":
version "19.1.7"
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.7.tgz#9fc4ab6003a8e4f38710c83cb5f8afbdacb7d687"
integrity sha512-BnsPLV43ddr05N71gaGzyZ5hzkCmGwhMvYc8zmvI8Ci1bRkkDSzDDVfAXfN2tk748OwI7ediiPX6PfT9p0QGVg==
dependencies:
csstype "^3.0.2"
"@types/retry@0.12.2": "@types/retry@0.12.2":
version "0.12.2" version "0.12.2"
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a"
...@@ -10791,13 +10802,13 @@ damerau-levenshtein@^1.0.8: ...@@ -10791,13 +10802,13 @@ damerau-levenshtein@^1.0.8:
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
dappscout-iframe@0.2.6: dappscout-iframe@0.3.0:
version "0.2.6" version "0.3.0"
resolved "https://registry.yarnpkg.com/dappscout-iframe/-/dappscout-iframe-0.2.6.tgz#2d3411f1f24ee28b0227fdbd78eb6fc7f832c828" resolved "https://registry.yarnpkg.com/dappscout-iframe/-/dappscout-iframe-0.3.0.tgz#785d46774552dbc2a29f4196b6f39daa53689cd6"
integrity sha512-RmAa8qo8a8YZeffJxIUefU5WG8hwztDFso9W/4fGnGdvQsC+xJ3HYrcTCo08ASdRuaYahEaVkVrebBEsGAkTMQ== integrity sha512-vHiDO9jXG4Q80ZZbtqiHrDXEYbO1q3nNGYnF5nbUpe7lrYiCHvXK/NUKXC6sHt1zp8tSfD95fmgY/6ZDCrgfpA==
dependencies: dependencies:
react "18.3.1" react "19.1.0"
react-dom "18.3.1" react-dom "19.1.0"
viem "^1.20.3" viem "^1.20.3"
data-uri-to-buffer@^4.0.0: data-uri-to-buffer@^4.0.0:
...@@ -15002,7 +15013,7 @@ look-it-up@2.1.0: ...@@ -15002,7 +15013,7 @@ look-it-up@2.1.0:
resolved "https://registry.yarnpkg.com/look-it-up/-/look-it-up-2.1.0.tgz#278a7ffc9da60a928452a0bab5452bb8855d7d13" resolved "https://registry.yarnpkg.com/look-it-up/-/look-it-up-2.1.0.tgz#278a7ffc9da60a928452a0bab5452bb8855d7d13"
integrity sha512-nMoGWW2HurtuJf6XAL56FWTDCWLOTSsanrgwOyaR5Y4e3zfG5N/0cU5xWZSEU3tBxhQugRbV1xL9jb+ug7yZww== integrity sha512-nMoGWW2HurtuJf6XAL56FWTDCWLOTSsanrgwOyaR5Y4e3zfG5N/0cU5xWZSEU3tBxhQugRbV1xL9jb+ug7yZww==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: loose-envify@^1.0.0, loose-envify@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
...@@ -16805,13 +16816,12 @@ react-device-detect@^2.2.3: ...@@ -16805,13 +16816,12 @@ react-device-detect@^2.2.3:
dependencies: dependencies:
ua-parser-js "^1.0.33" ua-parser-js "^1.0.33"
react-dom@18.3.1: react-dom@19.1.0:
version "18.3.1" version "19.1.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
dependencies: dependencies:
loose-envify "^1.1.0" scheduler "^0.26.0"
scheduler "^0.23.2"
react-focus-lock@^2.5.2: react-focus-lock@^2.5.2:
version "2.9.4" version "2.9.4"
...@@ -16951,9 +16961,9 @@ react-script-hook@^1.7.2: ...@@ -16951,9 +16961,9 @@ react-script-hook@^1.7.2:
integrity sha512-fhyCEfXb94fag34UPRF0zry1XGwmVY+79iibWwTqAoOiCzYJQOYTiWJ7CnqglA9tMSV8g45cQpHCMcBwr7dwhA== integrity sha512-fhyCEfXb94fag34UPRF0zry1XGwmVY+79iibWwTqAoOiCzYJQOYTiWJ7CnqglA9tMSV8g45cQpHCMcBwr7dwhA==
react-scroll@^1.8.7: react-scroll@^1.8.7:
version "1.8.7" version "1.9.3"
resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.8.7.tgz#8020035329efad00f03964e18aff6822137de3aa" resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.9.3.tgz#8312831244a7a8f86036e72c71de155a454a78c0"
integrity sha512-fBOIwweAlhicx8RqP9tQXn/Uhd+DTtVRjw+0VBsIn1Z+MjRYLhTZ0tMoTAU1vOD3dce8mI6copexI4yWII+Luw== integrity sha512-xv7FXqF3k63aSLNu4/NjFvRNI0ge7DmmmsbeGarP7LZVAlJMSjUuW3dTtLxp1Afijyv0lS2qwC0GiFHvx1KBHQ==
dependencies: dependencies:
lodash.throttle "^4.1.1" lodash.throttle "^4.1.1"
prop-types "^15.7.2" prop-types "^15.7.2"
...@@ -17004,20 +17014,10 @@ react-transition-group@^4.3.0: ...@@ -17004,20 +17014,10 @@ react-transition-group@^4.3.0:
loose-envify "^1.4.0" loose-envify "^1.4.0"
prop-types "^15.6.2" prop-types "^15.6.2"
react@17.0.2: react@19.1.0:
version "17.0.2" version "19.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
react@18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
dependencies:
loose-envify "^1.1.0"
readable-stream@3.6.2, readable-stream@^3.4.0, readable-stream@^3.6.2: readable-stream@3.6.2, readable-stream@^3.4.0, readable-stream@^3.6.2:
version "3.6.2" version "3.6.2"
...@@ -17493,12 +17493,10 @@ saxes@^6.0.0: ...@@ -17493,12 +17493,10 @@ saxes@^6.0.0:
dependencies: dependencies:
xmlchars "^2.2.0" xmlchars "^2.2.0"
scheduler@^0.23.2: scheduler@^0.26.0:
version "0.23.2" version "0.26.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337"
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==
dependencies:
loose-envify "^1.1.0"
scslre@^0.3.0: scslre@^0.3.0:
version "0.3.0" version "0.3.0"
...@@ -18999,13 +18997,12 @@ use-callback-ref@^1.3.0: ...@@ -18999,13 +18997,12 @@ use-callback-ref@^1.3.0:
dependencies: dependencies:
tslib "^2.0.0" tslib "^2.0.0"
use-font-face-observer@^1.2.1: use-font-face-observer@^1.3.0:
version "1.2.1" version "1.3.0"
resolved "https://registry.yarnpkg.com/use-font-face-observer/-/use-font-face-observer-1.2.1.tgz#2b33a389b82b48e2744f439abc1d5d6201fc099d" resolved "https://registry.yarnpkg.com/use-font-face-observer/-/use-font-face-observer-1.3.0.tgz#12987ed66450fdb1f48749be7ef70a3542951f70"
integrity sha512-5ieKTMvtUux0l7YoOEz842djfgMH3oVg+tO13E/kyS+gGRLDyfAMmRv0D3fzM7UdFag1kz+3AQIFLkkfEF3TUg== integrity sha512-gS5UoSPcOoCF+JMbw2By1E3FtXl6ZPxgFo8MW4shpM15lf+MNyzEfjsLJFJ3T/mHLdGTBhQgZYSAXEzubr6v5Q==
dependencies: dependencies:
fontfaceobserver "2.1.0" fontfaceobserver "2.1.0"
react "17.0.2"
use-isomorphic-layout-effect@^1.1.2: use-isomorphic-layout-effect@^1.1.2:
version "1.1.2" version "1.1.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