Skip to content

Commit 93f0cf2

Browse files
committed
add use element size hook and demo
1 parent 284bb39 commit 93f0cf2

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { CSSProperties } from 'react';
2+
3+
import { useRef } from 'react';
4+
5+
import { useElementSize } from './useElementSize';
6+
7+
const Demo = () => {
8+
const element = useRef<HTMLTextAreaElement>(null);
9+
10+
const { height, width } = useElementSize(element);
11+
12+
const containerStyle: CSSProperties = {
13+
display: 'flex',
14+
flexDirection: 'column',
15+
gap: '15px'
16+
};
17+
18+
const textareaStyle: CSSProperties = {
19+
resize: 'both',
20+
width: '200px',
21+
height: '200px'
22+
};
23+
24+
return (
25+
<div style={containerStyle}>
26+
<span>Resize the box to see changes</span>
27+
<textarea ref={element} style={textareaStyle} value={`width: ${width}\nheight: ${height}`} />
28+
</div>
29+
);
30+
};
31+
32+
export default Demo;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { RefObject } from 'react';
2+
3+
import { useEffect, useState } from 'react';
4+
5+
interface ElementSize {
6+
height: number;
7+
width: number;
8+
}
9+
10+
type UseElementSizeTarget = RefObject<Element>;
11+
12+
type UseElementSizeReturn = ElementSize;
13+
14+
/**
15+
* @name useElementSize
16+
* @description - Hook that returns the width and height of the element
17+
* @category Elements
18+
*
19+
* @param {UseElementSizeTarget} target The target element to observe
20+
* @param {ElementSize} [initialSize] The initial size of the element
21+
* @returns {UseElementSizeReturn} An object containing the width and height of the element
22+
*
23+
* @example
24+
* const { width, height } = useElementSize(elementRef);
25+
*/
26+
export const useElementSize = (
27+
target: UseElementSizeTarget,
28+
initialSize: ElementSize = { height: 0, width: 0 }
29+
): UseElementSizeReturn => {
30+
const [width, setWidth] = useState(initialSize.width);
31+
const [height, setHeight] = useState(initialSize.height);
32+
33+
useEffect(() => {
34+
const observer = new ResizeObserver(([entry]) => {
35+
const { inlineSize: width, blockSize: height } = entry.borderBoxSize[0];
36+
37+
setWidth(width);
38+
setHeight(height);
39+
});
40+
41+
if (target.current) {
42+
observer.observe(target.current);
43+
}
44+
45+
return () => {
46+
observer.disconnect();
47+
};
48+
}, [target]);
49+
50+
return { width, height };
51+
};

0 commit comments

Comments
 (0)