From 637f88d3f70084d9c7dbe7191e6cdee6c7380bd7 Mon Sep 17 00:00:00 2001 From: Nikita Gorin <36075690+NikitaCG@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:47:54 +0300 Subject: [PATCH] feat: create useViewportSize hook (#933) --- .../__tests__/useViewportSize.test.tsx | 25 ++++++++++++ src/components/utils/useViewportSize/index.ts | 2 + .../utils/useViewportSize/useViewportSize.tsx | 38 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/components/utils/useViewportSize/__tests__/useViewportSize.test.tsx create mode 100644 src/components/utils/useViewportSize/index.ts create mode 100644 src/components/utils/useViewportSize/useViewportSize.tsx diff --git a/src/components/utils/useViewportSize/__tests__/useViewportSize.test.tsx b/src/components/utils/useViewportSize/__tests__/useViewportSize.test.tsx new file mode 100644 index 0000000000..8b5c5a742b --- /dev/null +++ b/src/components/utils/useViewportSize/__tests__/useViewportSize.test.tsx @@ -0,0 +1,25 @@ +import {act, fireEvent, renderHook} from '@testing-library/react'; + +import {useViewportSize} from '..'; + +test('Check useViewportSize correct work', () => { + const view = renderHook(() => useViewportSize()); + + act(() => { + window.innerHeight = 500; + window.innerWidth = 500; + }); + + fireEvent(window, new Event('resize')); + + expect(view.result.current).toEqual({height: 500, width: 500}); + + act(() => { + window.innerHeight = 1200; + window.innerWidth = 1200; + }); + + fireEvent(window, new Event('resize')); + + expect(view.result.current).toEqual({height: 1200, width: 1200}); +}); diff --git a/src/components/utils/useViewportSize/index.ts b/src/components/utils/useViewportSize/index.ts new file mode 100644 index 0000000000..35c194400a --- /dev/null +++ b/src/components/utils/useViewportSize/index.ts @@ -0,0 +1,2 @@ +export {useViewportSize} from './useViewportSize'; +export type {ViewportSize} from './useViewportSize'; diff --git a/src/components/utils/useViewportSize/useViewportSize.tsx b/src/components/utils/useViewportSize/useViewportSize.tsx new file mode 100644 index 0000000000..f481c32b11 --- /dev/null +++ b/src/components/utils/useViewportSize/useViewportSize.tsx @@ -0,0 +1,38 @@ +import React from 'react'; + +export interface ViewportSize { + width?: number; + height?: number; +} + +const getViewportSize = (): ViewportSize => ({ + width: window?.visualViewport?.width ?? window?.innerWidth ?? undefined, + height: window?.visualViewport?.height ?? window?.innerHeight ?? undefined, +}); + +/** + * A hook to get the size of the viewport when resizing + * + * @return - {width, height} + */ +export const useViewportSize = (): ViewportSize => { + const [size, setSize] = React.useState(getViewportSize()); + + React.useEffect(() => { + const onResize = () => { + let newSize = getViewportSize(); + if (newSize.width === size?.width && newSize.height === size?.height) { + newSize = size; + } + setSize(newSize); + }; + + (window.visualViewport ?? window).addEventListener('resize', onResize); + + return () => { + (window.visualViewport ?? window).removeEventListener('resize', onResize); + }; + }, [size]); + + return size; +};