|
import { useState, useMemo, useEffect, useCallback } from 'react'; |
|
|
|
const getSizeOnly = ({ width, height }) => ({ width, height }); |
|
|
|
export const getElementDimensions = (el) => { |
|
if (!el) { |
|
return { width: 0, height: 0 }; |
|
} |
|
|
|
return getSizeOnly(el.getBoundingClientRect()); |
|
}; |
|
|
|
export const useResizeObserver = (handler, elRef) => { |
|
const observer = useMemo(() => { |
|
if (!elRef.current) { |
|
return null; |
|
} |
|
|
|
return new ResizeObserver(handler); |
|
}, [handler, elRef.current]); |
|
|
|
useEffect(() => { |
|
if (!observer) { |
|
return; |
|
} |
|
|
|
observer.observe(elRef.current); |
|
|
|
return () => observer.disconnect(); |
|
}, [observer, elRef.current]); |
|
}; |
|
|
|
export const useElementSize = (elRef, reinitInEffect = true) => { |
|
let [size, setSize] = useState(null); |
|
|
|
const handler = useCallback( |
|
([{ borderBox, contentRect }]) => { |
|
let size; |
|
if (contentRect) { |
|
size = getSizeOnly(contentRect); |
|
} else { |
|
size = borderBox.reduce( |
|
({ width, height }, { inlineSize, blockSize }) => ({ |
|
width: width + inlineSize, |
|
height: height > blockSize ? height : blockSize |
|
}), |
|
{ width: 0, height: 0 } |
|
); |
|
} |
|
|
|
setSize(size); |
|
}, |
|
[setSize] |
|
); |
|
|
|
useResizeObserver(handler, elRef); |
|
|
|
useEffect(() => { |
|
if (reinitInEffect) { |
|
setSize(getElementDimensions(elRef.current)); |
|
} |
|
}, []); |
|
|
|
return size; |
|
}; |