UNPKG

@hhgtech/hhg-components

Version:
58 lines (55 loc) 2.47 kB
import { useState, useRef, useEffect } from 'react'; import debounce from 'lodash/debounce'; const MEASURE_ELEMENT_CLASS = 'measure-scrollbar-size'; const useScrollbarSize = (trigger = true) => { const [dimensions, setDimensions] = useState({ height: 0, width: 0 }); const element = useRef(null); // initialize resize event handler and state when mounted useEffect(() => { if (!trigger || typeof window === 'undefined') { return; } const getElement = () => { if (!element.current) { // element was not created yet -- initialize element.current = document.createElement('div'); element.current.classList.add(MEASURE_ELEMENT_CLASS); element.current.style.width = '99px'; element.current.style.height = '99px'; element.current.style.overflow = 'scroll'; element.current.style.position = 'absolute'; element.current.style.top = '-9999px'; element.current.setAttribute('aria-hidden', 'true'); element.current.setAttribute('role', 'presentation'); } return element.current; }; const updateState = () => { const { offsetHeight, clientHeight, offsetWidth, clientWidth } = getElement(); const scrollbarHeight = offsetHeight - clientHeight; const scrollbarWidth = offsetWidth - clientWidth; setDimensions((currentDimensions) => { const { height, width } = currentDimensions; return height !== scrollbarHeight || width !== scrollbarWidth ? { height: scrollbarHeight, width: scrollbarWidth } : currentDimensions; }); }; const handleResize = debounce(updateState, 100); // initialize window.addEventListener('resize', handleResize, { passive: true, }); document.body.appendChild(getElement()); updateState(); const elementToRemove = getElement(); // cleanup return () => { handleResize.cancel(); window.removeEventListener('resize', handleResize); document.body.removeChild(elementToRemove); }; }, [trigger]); return dimensions; }; export { MEASURE_ELEMENT_CLASS as M, useScrollbarSize as u };