Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/vkui/docs/common/hooks/useInfiniteList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type ReactNode, type RefObject, useEffect, useMemo, useRef, useState } from 'react';
import { Spinner } from '../../../src';
import { useResizeObserver } from '../../../src/hooks/useResizeObserver';
import { useDOM } from '../../../src/lib/dom';
import { useResizeObserver } from '../../../src/hooks/useResizeObserver/useResizeObserver';

const SPINNER_HEIGHT = 24;
const WINDOW_PADDING_BOTTOM = 64;
Expand Down Expand Up @@ -138,7 +138,10 @@ export const useInfiniteList = <Section extends { id: string }>(

useEffect(recalculateSectionsBounds, [sectionsRefs]);

useResizeObserver(containerRef, () => requestAnimationFrame(showMoreVisible));
useResizeObserver({
ref: containerRef,
onResize: showMoreVisible,
});

useEffect(() => {
window!.addEventListener('scroll', recalculateVisibleSections);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { Card, Mark, Title, useDirection } from '../../../src';
import { useResizeObserver } from '../../../src/hooks/useResizeObserver';
import { useDOM } from '../../../src/lib/dom';
import type { CSSCustomProperties } from '../../../src/types';
import { useOverviewLayoutContext } from '../../common/components/OverviewLayoutContext';
import type { ComponentConfigData } from '../config';
import styles from './ComponentOverviewCard.module.css';
import { useResizeObserver } from '../../../src/hooks/useResizeObserver/useResizeObserver';

const CONTENT_PADDING = 10;

Expand Down Expand Up @@ -74,7 +74,10 @@ export const ComponentOverviewCard: React.FC<ComponentOverviewCardProps> = ({

React.useEffect(() => calculateScale(), [calculateScale]);

useResizeObserver(containerRef, calculateScale);
useResizeObserver({
ref: containerRef,
onResize: calculateScale,
});

const componentUrl = React.useMemo(() => {
if (!window) {
Expand Down
15 changes: 11 additions & 4 deletions packages/vkui/src/components/CarouselBase/CarouselBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { classNames } from '@vkontakte/vkjs';
import { useConfigDirection } from '../../hooks/useConfigDirection';
import { useExternRef } from '../../hooks/useExternRef';
import { useMutationObserver } from '../../hooks/useMutationObserver';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { useDOM } from '../../lib/dom';
import { useResizeObserver } from '../../hooks/useResizeObserver/useResizeObserver';
import { useWindowResizeObserver } from '../../hooks/useResizeObserver/useWindowResizeObserver';
import { mergeCalls } from '../../lib/mergeCalls';
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
import { warnOnce } from '../../lib/warnOnce';
Expand Down Expand Up @@ -347,8 +347,15 @@ export const CarouselBase = ({
initializeSlides();
}
};
const { window } = useDOM();
useResizeObserver(resizeSource === 'element' ? rootRef : window, onResize);
useWindowResizeObserver({
enabled: resizeSource === 'window',
onResize,
});
useResizeObserver({
ref: rootRef,
enabled: resizeSource === 'element',
onResize,
});

const loopedSlideChangePerform = () => {
const { snaps, slides } = slidesManager.current;
Expand Down
152 changes: 74 additions & 78 deletions packages/vkui/src/components/FixedLayout/FixedLayout.test.tsx
Original file line number Diff line number Diff line change
@@ -1,98 +1,94 @@
import { act, type RefObject } from 'react';
import { render } from '@testing-library/react';
import { baselineComponent } from '../../testing/utils';
import { baselineComponent, withFakeTimers } from '../../testing/utils';
import { SplitCol } from '../SplitCol/SplitCol';
import { FixedLayout, type FixedLayoutProps } from './FixedLayout';
import styles from './FixedLayout.module.css';

let updateFunction: () => void;

const mockResizeObserver = vi.fn(
class MockResizeObserver {
constructor(updateFunctionFn: () => void) {
updateFunction = updateFunctionFn;
}
describe('FixedLayout', () => {
baselineComponent(FixedLayout);

observe = vi.fn();
unobserve = vi.fn();
disconnect = vi.fn();
},
);
it(
'check update width by parent width',
withFakeTimers(async () => {
const parentRef: RefObject<HTMLDivElement | null> = {
current: null,
};
const layoutRef: RefObject<HTMLDivElement | null> = {
current: null,
};
let parentWidth = 500;

vi.stubGlobal('ResizeObserver', mockResizeObserver);
const mockParentRef = (element: HTMLDivElement) => {
if (!element) {
return;
}
vi.spyOn(element, 'getBoundingClientRect').mockImplementation(
() => new DOMRect(0, 0, parentWidth, 800),
);

describe('FixedLayout', () => {
baselineComponent(FixedLayout);
parentRef.current = element;
};

it('check update width by parent width', async () => {
const parentRef: RefObject<HTMLDivElement | null> = {
current: null,
};
const layoutRef: RefObject<HTMLDivElement | null> = {
current: null,
};
let parentWidth = 500;

const mockParentRef = (element: HTMLDivElement) => {
if (!element) {
return;
}
vi.spyOn(element, 'getBoundingClientRect').mockImplementation(
() => new DOMRect(0, 0, parentWidth, 800),
render(
<div ref={mockParentRef} style={{ width: 500, height: 800 }}>
<FixedLayout getRootRef={layoutRef} useParentWidth>
<div style={{ width: 200, height: 400 }} />
</FixedLayout>
</div>,
);

parentRef.current = element;
};
expect(layoutRef.current!).toHaveStyle('width: 500px');

parentWidth = 600;
act(() => {
globalThis.__resizeObserverMock.triggerAll();
vi.runAllTimers();
});

render(
<div ref={mockParentRef} style={{ width: 500, height: 800 }}>
<FixedLayout getRootRef={layoutRef} useParentWidth>
<div style={{ width: 200, height: 400 }} />
</FixedLayout>
</div>,
);
expect(layoutRef.current!).toHaveStyle('width: 600px');
}),
);

expect(layoutRef.current!).toHaveStyle('width: 500px');
it(
'check update width by column width',
withFakeTimers(async () => {
const colRef: RefObject<HTMLDivElement | null> = {
current: null,
};
const layoutRef: RefObject<HTMLDivElement | null> = {
current: null,
};
let colWidth = 280;

parentWidth = 600;
await act(async () => updateFunction());
const mockColRef = (element: HTMLDivElement) => {
if (!element) {
return;
}
vi.spyOn(element, 'clientWidth', 'get').mockImplementation(() => colWidth);

expect(layoutRef.current!).toHaveStyle('width: 600px');
});
colRef.current = element;
};

it('check update width by column width', async () => {
const colRef: RefObject<HTMLDivElement | null> = {
current: null,
};
const layoutRef: RefObject<HTMLDivElement | null> = {
current: null,
};
let colWidth = 280;

const mockColRef = (element: HTMLDivElement) => {
if (!element) {
return;
}
vi.spyOn(element, 'clientWidth', 'get').mockImplementation(() => colWidth);

colRef.current = element;
};

render(
<SplitCol width={colWidth} maxWidth={colWidth} getRootRef={mockColRef}>
<FixedLayout getRootRef={layoutRef}>
<div style={{ width: colWidth, height: 400 }} />
</FixedLayout>
</SplitCol>,
);

expect(layoutRef.current!).toHaveStyle('width: 280px');

colWidth = 360;
await act(async () => updateFunction());

expect(layoutRef.current!).toHaveStyle('width: 360px');
});
render(
<SplitCol width={colWidth} maxWidth={colWidth} getRootRef={mockColRef}>
<FixedLayout getRootRef={layoutRef}>
<div style={{ width: colWidth, height: 400 }} />
</FixedLayout>
</SplitCol>,
);

expect(layoutRef.current!).toHaveStyle('width: 280px');

colWidth = 360;
act(() => {
globalThis.__resizeObserverMock.triggerAll();
vi.runAllTimers();
});

expect(layoutRef.current!).toHaveStyle('width: 360px');
}),
);

describe('check correct classNames', () => {
it.each<{ props: Partial<FixedLayoutProps>; className: string }>([
Expand Down
14 changes: 9 additions & 5 deletions packages/vkui/src/components/FixedLayout/FixedLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useCallback } from 'react';
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { usePlatform } from '../../hooks/usePlatform';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { useDOM } from '../../lib/dom';
import { useResizeObserver } from '../../hooks/useResizeObserver/useResizeObserver';
import { useWindowResizeObserver } from '../../hooks/useResizeObserver/useWindowResizeObserver';
import { setRef } from '../../lib/utils';
import { warnOnce } from '../../lib/warnOnce';
import type { HasComponent, HTMLAttributesWithRootRef } from '../../types';
Expand Down Expand Up @@ -62,7 +62,6 @@ export const FixedLayout = ({
const platform = usePlatform();
const ref = React.useRef<HTMLElement | null>(null);
const [width, setWidth] = React.useState<string | undefined>(undefined);
const { window } = useDOM();
const { colRef } = React.useContext(SplitColContext);
const parentRef = React.useRef<HTMLElement | null>(null);

Expand Down Expand Up @@ -99,8 +98,13 @@ export const FixedLayout = ({
};
React.useEffect(doResize, [colRef, platform, ref, useParentWidth]);

useResizeObserver(window, doResize);
useResizeObserver(useParentWidth ? parentRef : colRef, doResize);
useWindowResizeObserver({
onResize: doResize,
});
useResizeObserver({
ref: useParentWidth ? parentRef : (colRef ?? undefined),
onResize: doResize,
});

return (
<OnboardingTooltipContainer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import * as React from 'react';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { useResizeObserver } from '../../hooks/useResizeObserver/useResizeObserver';
import { defineComponentDisplayNames } from '../../lib/react/defineComponentDisplayNames';
import { setRef } from '../../lib/utils';
import type { HasComponent } from '../../types';
Expand Down Expand Up @@ -37,7 +37,10 @@ export const ParentWidthWrapper: React.ForwardRefExoticComponent<
}, []);

React.useEffect(doResize, [doResize]);
useResizeObserver(parentRef, doResize);
useResizeObserver({
ref: parentRef,
onResize: doResize,
});

return <Component {...restProps} ref={handleRootRef} style={{ width, ...style }} />;
},
Expand Down
54 changes: 13 additions & 41 deletions packages/vkui/src/components/Gallery/Gallery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,10 @@ describe('Gallery', () => {

mockedData.containerWidth = 250;

fireEvent.resize(window);
vi.runAllTimers();
act(() => {
fireEvent.resize(window);
vi.runAllTimers();
});

if (looped) {
expect(mockedData.layerTransform).toBe('translate3d(35px, 0, 0)');
Expand Down Expand Up @@ -763,41 +765,9 @@ describe('Gallery', () => {
});
});

const mockResizeObserver = () => {
const callbacks = new Set<ResizeObserverCallback>();

class MockResizeObserver implements ResizeObserver {
constructor(callback: ResizeObserverCallback) {
callbacks.add(callback);
}

// eslint-disable-next-line @typescript-eslint/no-empty-function
observe() {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
unobserve() {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
disconnect() {}
}

const originalResizeObserver = window.ResizeObserver;
window.ResizeObserver = MockResizeObserver;

return {
triggerResize: () => {
callbacks.forEach((callback) => {
callback([], {} as unknown as ResizeObserver);
});
},
restore: () => {
window.ResizeObserver = originalResizeObserver;
},
};
};

it(
'check recalculate slides positions when resize element with resizeSource="element"',
withFakeTimers(() => {
const { triggerResize, restore } = mockResizeObserver();
const onChange = vi.fn();

const mockedData = setup({
Expand All @@ -817,12 +787,13 @@ describe('Gallery', () => {

mockedData.containerWidth = 250;

act(triggerResize);
vi.runAllTimers();
act(() => {
globalThis.__resizeObserverMock.triggerAll();
vi.runAllTimers();
});

expect(mockedData.layerTransform).toBe('translate3d(35px, 0, 0)');
expect(mockedData.getSlideMockData(0).transform).toBe('translate3d(0px, 0, 0)');
restore();
}),
);

Expand Down Expand Up @@ -884,10 +855,11 @@ describe('Gallery', () => {
mockedData.viewPortWidth = 540;
onDragStart.mockClear();
onDragEnd.mockClear();
fireEvent.resize(window);

rerender({ slideIndex: 1 });
vi.runAllTimers();
act(() => {
fireEvent.resize(window);
rerender({ slideIndex: 1 });
vi.runAllTimers();
});

expect(getArrows()).toHaveLength(0);

Expand Down
Loading
Loading