import { useLayoutEffect, useMemo, useEffect, useState, EffectCallback, RefObject, } from 'react'; import { isNonEmptyArray } from '../fp/NonEmptyArray'; type Dimensions = { clientWidth: number; height: number; scrollWidth: number; width: number; }; const useNativeResizeObserver = ( resizeCallback: (dimensions: Dimensions) => void, refElement: HTMLElement | null ): void => { useLayoutEffect(() => { if (refElement === null) return; const resizeObserver = new ResizeObserver(entries => { if (isNonEmptyArray(entries)) { const targetElement = entries[0].target as HTMLElement; resizeCallback({ height: targetElement.offsetHeight, width: targetElement.offsetWidth, clientWidth: targetElement.clientWidth, scrollWidth: targetElement.scrollWidth, }); } }); resizeObserver.observe(refElement); return (): void => resizeObserver.unobserve(refElement); }, [resizeCallback, refElement]); }; const useCustomResizeObserver = ( resizeCallback: (dimensions: Dimensions) => void, refElement: HTMLElement | null ): void => { const width = refElement !== null ? refElement.offsetWidth : 0; const height = refElement !== null ? refElement.offsetHeight : 0; const clientWidth = refElement !== null ? refElement.clientWidth : 0; const scrollWidth = refElement !== null ? refElement.scrollWidth : 0; useLayoutEffect(() => { resizeCallback({ width, height, clientWidth, scrollWidth }); }, [width, height, resizeCallback, clientWidth, scrollWidth]); }; const useResizeObserver = ( resizeCallback: (dimensions: Dimensions) => void, refElement: HTMLElement | null ): void => { const observer = useMemo(() => { return typeof window !== 'undefined' && window.ResizeObserver !== undefined ? useNativeResizeObserver : useCustomResizeObserver; }, []); observer(resizeCallback, refElement); }; const useHover = (ref: RefObject) => { const [value, setValue] = useState(false); const handleMouseEnter = () => setValue(true); const handleMouseLeave = () => setValue(false); useEffect((): ReturnType => { const node = ref.current; if (node !== null) { node.addEventListener('mouseenter', handleMouseEnter); node.addEventListener('mouseleave', handleMouseLeave); return () => { node.removeEventListener('mouseenter', handleMouseEnter); node.removeEventListener('mouseleave', handleMouseLeave); }; } }, [ref]); return value; }; const useDeprecation = (message: string, cond = true) => { useEffect(() => { if (process.env['NODE_ENV'] === 'development' && cond === true) { // eslint-disable-next-line no-console console.warn( `%c ██████╗ ███████╗██████╗ ██████╗ ███████╗ ██████╗ █████╗ ████████╗███████╗██████╗ ██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗╚══██╔══╝██╔════╝██╔══██╗ ██║ ██║█████╗ ██████╔╝██████╔╝█████╗ ██║ ███████║ ██║ █████╗ ██║ ██║ ██║ ██║██╔══╝ ██╔═══╝ ██╔══██╗██╔══╝ ██║ ██╔══██║ ██║ ██╔══╝ ██║ ██║ ██████╔╝███████╗██║ ██║ ██║███████╗╚██████╗██║ ██║ ██║ ███████╗██████╔╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═════╝ %c${message}`, 'color: red', 'color: red; font-size: 15px' ); } }, [message, cond]); }; export { useResizeObserver, useHover, useDeprecation };