@@ -3,6 +3,12 @@ import { Context } from './Context';
33import { ObservedElement } from './ObservedElement' ;
44import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry' ;
55
6+ const boxOptions = {
7+ BORDER_BOX : 'border-box' , // https://caniuse.com/mdn-api_resizeobserverentry_borderboxsize
8+ CONTENT_BOX : 'content-box' , // https://caniuse.com/mdn-api_resizeobserverentry_contentboxsize
9+ DEVICE_PIXEL_CONTENT_BOX : 'device-pixel-content-box' // https://github.com/w3c/csswg-drafts/pull/4476
10+ } ;
11+
612/**
713 * See API Docs: {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#useresizeobserver|useResizeObserver}
814 *
@@ -25,8 +31,60 @@ export const useResizeObserver = (
2531
2632 const [ observedEntry , setObservedEntry ] = useState < ExtendedResizeObserverEntry | null > ( null ) ;
2733
28- const handleResizeObservation = ( resizeObserverEntry : ExtendedResizeObserverEntry ) =>
29- setObservedEntry ( resizeObserverEntry ) ;
34+ const handleResizeObservation = useCallback (
35+ ( resizeObserverEntry : ExtendedResizeObserverEntry ) => {
36+ if ( ! observedEntry ) return setObservedEntry ( resizeObserverEntry ) ;
37+
38+ let isIdentical = true ;
39+
40+ switch ( options . box ) {
41+ case boxOptions . BORDER_BOX :
42+ isIdentical = resizeObserverEntry . borderBoxSize . every (
43+ ( boxSize , index ) =>
44+ boxSize . inlineSize === observedEntry . borderBoxSize [ index ] . inlineSize &&
45+ boxSize . blockSize === observedEntry . borderBoxSize [ index ] . blockSize
46+ ) ;
47+ break ;
48+
49+ case boxOptions . CONTENT_BOX :
50+ isIdentical = resizeObserverEntry . contentBoxSize . every (
51+ ( boxSize , index ) =>
52+ boxSize . inlineSize === observedEntry . contentBoxSize [ index ] . inlineSize &&
53+ boxSize . blockSize === observedEntry . contentBoxSize [ index ] . blockSize
54+ ) ;
55+ break ;
56+
57+ case boxOptions . DEVICE_PIXEL_CONTENT_BOX :
58+ /* TypeScript 4.2 is missing devicePixelContentBoxSize. */
59+ if ( typeof resizeObserverEntry . devicePixelContentBoxSize !== 'undefined' ) {
60+ isIdentical = resizeObserverEntry . devicePixelContentBoxSize . every ( ( boxSize , index ) => {
61+ if ( typeof observedEntry . devicePixelContentBoxSize !== 'undefined' ) {
62+ return (
63+ boxSize . inlineSize === observedEntry . devicePixelContentBoxSize [ index ] . inlineSize &&
64+ boxSize . blockSize === observedEntry . devicePixelContentBoxSize [ index ] . blockSize
65+ ) ;
66+ } else {
67+ throw Error ( 'resizeObserverEntry does not contain devicePixelContentBoxSize.' ) ;
68+ }
69+ } ) ;
70+ } else {
71+ throw Error ( 'resizeObserverEntry does not contain devicePixelContentBoxSize.' ) ;
72+ }
73+ break ;
74+
75+ default :
76+ if (
77+ resizeObserverEntry . contentRect . width !== observedEntry . contentRect . width ||
78+ resizeObserverEntry . contentRect . height !== observedEntry . contentRect . height
79+ ) {
80+ isIdentical = false ;
81+ }
82+ }
83+
84+ if ( ! isIdentical ) setObservedEntry ( resizeObserverEntry ) ;
85+ } ,
86+ [ options . box , observedEntry ]
87+ ) ;
3088
3189 const ref = useRef < ObservedElement | null > ( null ) ;
3290
@@ -44,7 +102,7 @@ export const useResizeObserver = (
44102
45103 ref . current = node ;
46104 } ,
47- [ resizeObserver , options ]
105+ [ resizeObserver , handleResizeObservation , options ]
48106 ) ;
49107
50108 return [ setRef , observedEntry ] ;
0 commit comments