From 1dd32c2b942f22d42f638594b80250d6d78bfd9c Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Sat, 22 Jun 2024 18:03:19 +0300 Subject: [PATCH 1/9] fix(CustomScrollView): add resize container handler --- .../CustomScrollView/CustomScrollView.tsx | 3 ++ packages/vkui/src/hooks/useResizeObserver.ts | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 packages/vkui/src/hooks/useResizeObserver.ts diff --git a/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx b/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx index 275b0452eb..baece4e5bf 100644 --- a/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx +++ b/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx @@ -3,6 +3,7 @@ import { classNames } from '@vkontakte/vkjs'; import { useAdaptivity } from '../../hooks/useAdaptivity'; import { useEventListener } from '../../hooks/useEventListener'; import { useExternRef } from '../../hooks/useExternRef'; +import { useResizeObserver } from '../../hooks/useResizeObserver'; import { useDOM } from '../../lib/dom'; import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect'; import { stopPropagation } from '../../lib/utils'; @@ -104,6 +105,8 @@ export const CustomScrollView = ({ } }, [windowResize, window]); + useResizeObserver(boxRef, resize); + useIsomorphicLayoutEffect(() => { let style = trackerY.current?.style; let prop = ''; diff --git a/packages/vkui/src/hooks/useResizeObserver.ts b/packages/vkui/src/hooks/useResizeObserver.ts new file mode 100644 index 0000000000..e535385ab9 --- /dev/null +++ b/packages/vkui/src/hooks/useResizeObserver.ts @@ -0,0 +1,41 @@ +import * as React from 'react'; +import { CustomResizeObserver } from '../lib/floating/customResizeObserver'; +import { useIsomorphicLayoutEffect } from "../lib/useIsomorphicLayoutEffect"; +import { useStableCallback } from './useStableCallback'; + +interface UseResizeObserverConfig { + // Флаг определяет, нужно ли использовать MutationObserver + // Это позволяет покрыть большую часть кейсов и не переусложнять код + useMutationObserver?: boolean, +} + +const DEFAULT_CONFIG: UseResizeObserverConfig = { + useMutationObserver: false, +} + +/** + * Хук вызывает переданный коллбэк при изменении размеров элемента. + */ +export function useResizeObserver(ref: React.MutableRefObject, callback: () => void, config: UseResizeObserverConfig = DEFAULT_CONFIG) { + const stableCallback = useStableCallback(callback); + + useIsomorphicLayoutEffect( + function addResizeObserverHandler() { + if (!ref.current) { + return; + } + + const observer = new CustomResizeObserver(stableCallback); + if (config.useMutationObserver) { + observer.observeUsingMutationObserver(ref.current); + } + else { + observer.observe(ref.current); + } + observer.appendToTheDOM() + + return () => observer.disconnect(); + }, + [ref], + ); +} \ No newline at end of file From af0c7df97024bb9ff27e507d113de4f797479a10 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Sat, 22 Jun 2024 22:21:25 +0300 Subject: [PATCH 2/9] fix: improve code of useResizeObserver --- packages/vkui/src/hooks/useResizeObserver.ts | 59 +++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/packages/vkui/src/hooks/useResizeObserver.ts b/packages/vkui/src/hooks/useResizeObserver.ts index e535385ab9..cfc086ffbe 100644 --- a/packages/vkui/src/hooks/useResizeObserver.ts +++ b/packages/vkui/src/hooks/useResizeObserver.ts @@ -1,41 +1,46 @@ import * as React from 'react'; import { CustomResizeObserver } from '../lib/floating/customResizeObserver'; -import { useIsomorphicLayoutEffect } from "../lib/useIsomorphicLayoutEffect"; +import { useIsomorphicLayoutEffect } from '../lib/useIsomorphicLayoutEffect'; import { useStableCallback } from './useStableCallback'; interface UseResizeObserverConfig { - // Флаг определяет, нужно ли использовать MutationObserver - // Это позволяет покрыть большую часть кейсов и не переусложнять код - useMutationObserver?: boolean, + // Флаг определяет, нужно ли использовать MutationObserver + // Это позволяет покрыть большую часть кейсов и не переусложнять код + useMutationObserver?: boolean; } const DEFAULT_CONFIG: UseResizeObserverConfig = { - useMutationObserver: false, -} + useMutationObserver: false, +}; /** * Хук вызывает переданный коллбэк при изменении размеров элемента. */ -export function useResizeObserver(ref: React.MutableRefObject, callback: () => void, config: UseResizeObserverConfig = DEFAULT_CONFIG) { - const stableCallback = useStableCallback(callback); - - useIsomorphicLayoutEffect( - function addResizeObserverHandler() { - if (!ref.current) { - return; - } +export function useResizeObserver( + ref: React.MutableRefObject, + callback: (rect: DOMRect) => void, + config: UseResizeObserverConfig = DEFAULT_CONFIG, +) { + const stableCallback = useStableCallback(callback); - const observer = new CustomResizeObserver(stableCallback); - if (config.useMutationObserver) { - observer.observeUsingMutationObserver(ref.current); - } - else { - observer.observe(ref.current); - } - observer.appendToTheDOM() + useIsomorphicLayoutEffect( + function addResizeObserverHandler() { + if (!ref.current) { + return; + } + const element = ref.current; + const observer = new CustomResizeObserver(() => { + stableCallback(element.getBoundingClientRect()); + }); + if (config.useMutationObserver) { + observer.observeUsingMutationObserver(element); + } else { + observer.observe(element); + observer.appendToTheDOM(); + } - return () => observer.disconnect(); - }, - [ref], - ); -} \ No newline at end of file + return () => observer.disconnect(); + }, + [ref], + ); +} From ea5bb1d008b675eaa303c3033b481a2de8d0441b Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Sat, 22 Jun 2024 22:50:00 +0300 Subject: [PATCH 3/9] test(useResizeObserver): add tests --- .../vkui/src/hooks/useResizeObserver.test.tsx | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 packages/vkui/src/hooks/useResizeObserver.test.tsx diff --git a/packages/vkui/src/hooks/useResizeObserver.test.tsx b/packages/vkui/src/hooks/useResizeObserver.test.tsx new file mode 100644 index 0000000000..91f636e00d --- /dev/null +++ b/packages/vkui/src/hooks/useResizeObserver.test.tsx @@ -0,0 +1,32 @@ +import { act, useRef } from "react"; +import { render, screen } from "@testing-library/react"; +import { useResizeObserver } from "./useResizeObserver"; + + +describe('test useResizeObserver', () => { + it('should call callback when add block', async () => { + const callback = jest.fn(); + const Fixture = (props: {mockedBlocksIds: string[]}) => { + const ref = useRef(null); + useResizeObserver(ref, callback, { + useMutationObserver: true, + }); + return ( +
+ {props.mockedBlocksIds.map((id) => ( +
+ ))} +
+ ); + } + + const rerender = render(); + + await act(async () => { + rerender.rerender() + }) + + expect(callback).toHaveBeenCalledTimes(1); + expect(screen.getByTestId('block-2')).toBeInTheDocument(); + }); +}); From 590620f5560ad142ff671fb921f679293fb4204e Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Sat, 22 Jun 2024 22:53:04 +0300 Subject: [PATCH 4/9] fix: run prettier --- .../vkui/src/hooks/useResizeObserver.test.tsx | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/packages/vkui/src/hooks/useResizeObserver.test.tsx b/packages/vkui/src/hooks/useResizeObserver.test.tsx index 91f636e00d..a2b59d492d 100644 --- a/packages/vkui/src/hooks/useResizeObserver.test.tsx +++ b/packages/vkui/src/hooks/useResizeObserver.test.tsx @@ -1,32 +1,31 @@ -import { act, useRef } from "react"; -import { render, screen } from "@testing-library/react"; -import { useResizeObserver } from "./useResizeObserver"; - +import { act, useRef } from 'react'; +import { render, screen } from '@testing-library/react'; +import { useResizeObserver } from './useResizeObserver'; describe('test useResizeObserver', () => { - it('should call callback when add block', async () => { - const callback = jest.fn(); - const Fixture = (props: {mockedBlocksIds: string[]}) => { - const ref = useRef(null); - useResizeObserver(ref, callback, { - useMutationObserver: true, - }); - return ( -
- {props.mockedBlocksIds.map((id) => ( -
- ))} -
- ); - } - - const rerender = render(); + it('should call callback when add block', async () => { + const callback = jest.fn(); + const Fixture = (props: { mockedBlocksIds: string[] }) => { + const ref = useRef(null); + useResizeObserver(ref, callback, { + useMutationObserver: true, + }); + return ( +
+ {props.mockedBlocksIds.map((id) => ( +
+ ))} +
+ ); + }; - await act(async () => { - rerender.rerender() - }) + const result = render(); - expect(callback).toHaveBeenCalledTimes(1); - expect(screen.getByTestId('block-2')).toBeInTheDocument(); + await act(async () => { + result.rerender(); }); + + expect(callback).toHaveBeenCalledTimes(1); + expect(screen.getByTestId('block-2')).toBeInTheDocument(); + }); }); From 3796377c89bc8d993172dd9edbdf526ebe0d3a9f Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Sun, 23 Jun 2024 20:35:01 +0300 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20remake=20of=20using=20useResizeObse?= =?UTF-8?q?rver=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B0=D0=BB=D0=B0=D0=BB?= =?UTF-8?q?=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8E?= =?UTF-8?q?=20useResizeObserver=20=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B5=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=B2=20CustomScrollView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomScrollView.module.css | 4 ++++ .../CustomScrollView/CustomScrollView.tsx | 7 +++++-- .../vkui/src/hooks/useResizeObserver.test.tsx | 6 ++---- packages/vkui/src/hooks/useResizeObserver.ts | 19 ++----------------- .../src/lib/floating/customResizeObserver.ts | 3 ++- 5 files changed, 15 insertions(+), 24 deletions(-) diff --git a/packages/vkui/src/components/CustomScrollView/CustomScrollView.module.css b/packages/vkui/src/components/CustomScrollView/CustomScrollView.module.css index 711a5f0644..d6d48406fe 100644 --- a/packages/vkui/src/components/CustomScrollView/CustomScrollView.module.css +++ b/packages/vkui/src/components/CustomScrollView/CustomScrollView.module.css @@ -15,6 +15,10 @@ position: relative; } +.CustomScrollView__box-content { + position: relative; +} + .CustomScrollView__barY:active + .CustomScrollView__box { pointer-events: none; } diff --git a/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx b/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx index baece4e5bf..711a55ee57 100644 --- a/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx +++ b/packages/vkui/src/components/CustomScrollView/CustomScrollView.tsx @@ -58,6 +58,7 @@ export const CustomScrollView = ({ const trackerTop = React.useRef(0); const boxRef = useExternRef(externalBoxRef); + const boxContentRef = React.useRef(null); const barY = React.useRef(null); const trackerY = React.useRef(null); @@ -105,7 +106,7 @@ export const CustomScrollView = ({ } }, [windowResize, window]); - useResizeObserver(boxRef, resize); + useResizeObserver(boxContentRef, resize); useIsomorphicLayoutEffect(() => { let style = trackerY.current?.style; @@ -203,7 +204,9 @@ export const CustomScrollView = ({ {...restProps} >
- {children} +
+ {children} +
diff --git a/packages/vkui/src/hooks/useResizeObserver.test.tsx b/packages/vkui/src/hooks/useResizeObserver.test.tsx index a2b59d492d..66ab7ca129 100644 --- a/packages/vkui/src/hooks/useResizeObserver.test.tsx +++ b/packages/vkui/src/hooks/useResizeObserver.test.tsx @@ -7,11 +7,9 @@ describe('test useResizeObserver', () => { const callback = jest.fn(); const Fixture = (props: { mockedBlocksIds: string[] }) => { const ref = useRef(null); - useResizeObserver(ref, callback, { - useMutationObserver: true, - }); + useResizeObserver(ref, callback); return ( -
+
{props.mockedBlocksIds.map((id) => (
))} diff --git a/packages/vkui/src/hooks/useResizeObserver.ts b/packages/vkui/src/hooks/useResizeObserver.ts index cfc086ffbe..b0290ef6a2 100644 --- a/packages/vkui/src/hooks/useResizeObserver.ts +++ b/packages/vkui/src/hooks/useResizeObserver.ts @@ -3,23 +3,12 @@ import { CustomResizeObserver } from '../lib/floating/customResizeObserver'; import { useIsomorphicLayoutEffect } from '../lib/useIsomorphicLayoutEffect'; import { useStableCallback } from './useStableCallback'; -interface UseResizeObserverConfig { - // Флаг определяет, нужно ли использовать MutationObserver - // Это позволяет покрыть большую часть кейсов и не переусложнять код - useMutationObserver?: boolean; -} - -const DEFAULT_CONFIG: UseResizeObserverConfig = { - useMutationObserver: false, -}; - /** * Хук вызывает переданный коллбэк при изменении размеров элемента. */ export function useResizeObserver( ref: React.MutableRefObject, callback: (rect: DOMRect) => void, - config: UseResizeObserverConfig = DEFAULT_CONFIG, ) { const stableCallback = useStableCallback(callback); @@ -32,12 +21,8 @@ export function useResizeObserver( const observer = new CustomResizeObserver(() => { stableCallback(element.getBoundingClientRect()); }); - if (config.useMutationObserver) { - observer.observeUsingMutationObserver(element); - } else { - observer.observe(element); - observer.appendToTheDOM(); - } + observer.observe(element); + observer.appendToTheDOM(); return () => observer.disconnect(); }, diff --git a/packages/vkui/src/lib/floating/customResizeObserver.ts b/packages/vkui/src/lib/floating/customResizeObserver.ts index e516b2725a..19962526bc 100644 --- a/packages/vkui/src/lib/floating/customResizeObserver.ts +++ b/packages/vkui/src/lib/floating/customResizeObserver.ts @@ -1,6 +1,6 @@ const defaultIframeStyles: Pick< CSSStyleDeclaration, - 'position' | 'left' | 'top' | 'zIndex' | 'width' | 'height' | 'pointerEvents' | 'opacity' + 'position' | 'left' | 'top' | 'zIndex' | 'width' | 'height' | 'pointerEvents' | 'opacity' | 'border' > = { position: 'absolute', left: '0', @@ -10,6 +10,7 @@ const defaultIframeStyles: Pick< height: '100%', pointerEvents: 'none', opacity: '0', + border: '0', }; /* From c6b95b5b76a66eb4729c1db79b9f1bfed7e28fe7 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Mon, 24 Jun 2024 11:02:06 +0300 Subject: [PATCH 6/9] fix: run prettier and fix test --- packages/vkui/src/hooks/useResizeObserver.test.tsx | 2 +- .../vkui/src/lib/floating/customResizeObserver.test.ts | 1 + packages/vkui/src/lib/floating/customResizeObserver.ts | 10 +++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/vkui/src/hooks/useResizeObserver.test.tsx b/packages/vkui/src/hooks/useResizeObserver.test.tsx index 66ab7ca129..4e84a9c95a 100644 --- a/packages/vkui/src/hooks/useResizeObserver.test.tsx +++ b/packages/vkui/src/hooks/useResizeObserver.test.tsx @@ -9,7 +9,7 @@ describe('test useResizeObserver', () => { const ref = useRef(null); useResizeObserver(ref, callback); return ( -
+
{props.mockedBlocksIds.map((id) => (
))} diff --git a/packages/vkui/src/lib/floating/customResizeObserver.test.ts b/packages/vkui/src/lib/floating/customResizeObserver.test.ts index abf711c30c..b83c56008c 100644 --- a/packages/vkui/src/lib/floating/customResizeObserver.test.ts +++ b/packages/vkui/src/lib/floating/customResizeObserver.test.ts @@ -77,6 +77,7 @@ describe(CustomResizeObserver, () => { height: '100%', pointerEvents: 'none', opacity: '0', + border: '0', }); // скрытым от скринридеров diff --git a/packages/vkui/src/lib/floating/customResizeObserver.ts b/packages/vkui/src/lib/floating/customResizeObserver.ts index 19962526bc..2451745fea 100644 --- a/packages/vkui/src/lib/floating/customResizeObserver.ts +++ b/packages/vkui/src/lib/floating/customResizeObserver.ts @@ -1,6 +1,14 @@ const defaultIframeStyles: Pick< CSSStyleDeclaration, - 'position' | 'left' | 'top' | 'zIndex' | 'width' | 'height' | 'pointerEvents' | 'opacity' | 'border' + | 'position' + | 'left' + | 'top' + | 'zIndex' + | 'width' + | 'height' + | 'pointerEvents' + | 'opacity' + | 'border' > = { position: 'absolute', left: '0', From 9416916b07e85c5ad53aafd369b0de6a63c0452d Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Mon, 24 Jun 2024 13:10:50 +0300 Subject: [PATCH 7/9] fix: remove getBoundingClientRect call --- packages/vkui/src/hooks/useResizeObserver.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/vkui/src/hooks/useResizeObserver.ts b/packages/vkui/src/hooks/useResizeObserver.ts index b0290ef6a2..1c55febb17 100644 --- a/packages/vkui/src/hooks/useResizeObserver.ts +++ b/packages/vkui/src/hooks/useResizeObserver.ts @@ -8,7 +8,7 @@ import { useStableCallback } from './useStableCallback'; */ export function useResizeObserver( ref: React.MutableRefObject, - callback: (rect: DOMRect) => void, + callback: () => void, ) { const stableCallback = useStableCallback(callback); @@ -18,9 +18,7 @@ export function useResizeObserver( return; } const element = ref.current; - const observer = new CustomResizeObserver(() => { - stableCallback(element.getBoundingClientRect()); - }); + const observer = new CustomResizeObserver(stableCallback); observer.observe(element); observer.appendToTheDOM(); From 4f21f25a53b8b62bbe14f94b3b3ab2c35b0952e5 Mon Sep 17 00:00:00 2001 From: "e.muhamethanov" Date: Mon, 24 Jun 2024 13:12:38 +0300 Subject: [PATCH 8/9] fix: add call callback with element --- packages/vkui/src/hooks/useResizeObserver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vkui/src/hooks/useResizeObserver.ts b/packages/vkui/src/hooks/useResizeObserver.ts index 1c55febb17..2ba903d931 100644 --- a/packages/vkui/src/hooks/useResizeObserver.ts +++ b/packages/vkui/src/hooks/useResizeObserver.ts @@ -8,7 +8,7 @@ import { useStableCallback } from './useStableCallback'; */ export function useResizeObserver( ref: React.MutableRefObject, - callback: () => void, + callback: (element: HTMLElement) => void, ) { const stableCallback = useStableCallback(callback); @@ -18,7 +18,7 @@ export function useResizeObserver( return; } const element = ref.current; - const observer = new CustomResizeObserver(stableCallback); + const observer = new CustomResizeObserver(() => stableCallback(element)); observer.observe(element); observer.appendToTheDOM(); From 4a7abcefe691273c694269e1a68a513c7ce620a5 Mon Sep 17 00:00:00 2001 From: EldarMuhamethanov <61377022+EldarMuhamethanov@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:13:25 +0300 Subject: [PATCH 9/9] fix: add ignore coverage to useResizeObserver Co-authored-by: Inomdzhon Mirdzhamolov --- packages/vkui/src/hooks/useResizeObserver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vkui/src/hooks/useResizeObserver.ts b/packages/vkui/src/hooks/useResizeObserver.ts index 2ba903d931..118121f65b 100644 --- a/packages/vkui/src/hooks/useResizeObserver.ts +++ b/packages/vkui/src/hooks/useResizeObserver.ts @@ -14,6 +14,7 @@ export function useResizeObserver( useIsomorphicLayoutEffect( function addResizeObserverHandler() { + /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */ if (!ref.current) { return; }