Skip to content

Commit

Permalink
fix(): add support for Safari/Firefox and mobiles devices to useDimen…
Browse files Browse the repository at this point in the history
…sions() and <ResizeObserver/>
  • Loading branch information
ykadosh committed Apr 25, 2021
1 parent 2752481 commit c597f24
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/hooks/useDimensions/useDimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
*/

import {useState, useRef, useEffect} from 'react';
import {readResizeObserverEntry} from 'utility/rect';

export default ref => {
const [dimensions, setDimensions] = useState({width: 0, height: 0});
const observer = useRef(new window.ResizeObserver(entries => {
const {inlineSize: width, blockSize: height} = entries[0].borderBoxSize[0];
setDimensions({width, height});
setDimensions(readResizeObserverEntry(entries[0]));
}));
useEffect(() => {
const {current: obs} = observer;
Expand Down
4 changes: 2 additions & 2 deletions src/tools/ResizeObserver/ResizeObserver.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
import React, {useEffect, useRef} from 'react';
import {node, func} from 'prop-types';
import {copyComponentRef} from 'utility/react';
import {readResizeObserverEntry} from 'utility/rect';
import {noop} from 'utility/memory';

const ResizeObserver = ({children, onResize}) => {
const child = React.Children.only(children);
const ref = useRef();
const observer = useRef(new window.ResizeObserver(entries => {
const {inlineSize: width, blockSize: height} = entries[0].borderBoxSize[0];
onResize({width, height});
onResize(readResizeObserverEntry(entries[0]));
}));
useEffect(() => {
const {current: obs} = observer;
Expand Down
19 changes: 19 additions & 0 deletions src/utility/rect/rect.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,22 @@ export const add = (rect, delta) => new DOMRect(
rect.width + delta.width,
rect.height + delta.height,
);

/**
* Converts a ResizeObserverEntry to an object with width/height,
* unifying the different APIs between older/newer browsers, and mobile devices.
*
* @param entry
* @returns {{width: number, height: number}|{width: *, height: *}}
*/
export const readResizeObserverEntry = entry => {
if (entry.contentBoxSize) {
// Firefox implements `contentBoxSize` as a single content rect, rather than an array
const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;
const {inlineSize: width, blockSize: height} = contentBoxSize;
return {width, height};
} else { // For older browsers & mobile devices that don't support the newer `contentBoxSize`
const {width, height} = entry.contentRect;
return {width, height};
}
};
9 changes: 8 additions & 1 deletion src/utility/rect/rect.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {expect} from 'chai';
import {getCenterPoint, getRelativePosition, equal, contained, intersect, union, area, add} from './rect';
import {getCenterPoint, getRelativePosition, equal, contained, intersect, union, area, add, readResizeObserverEntry} from './rect';

describe('rect', () => {

Expand Down Expand Up @@ -73,4 +73,11 @@ describe('rect', () => {
expect(add(r(0, 0, 10, 10), r(10, 10, 10, 10))).to.eql(r(10, 10, 20, 20));
expect(add(r(0, 0, 10, 10), r(10, 10, -5, -5))).to.eql(r(10, 10, 5, 5));
});

it('readResizeObserverEntry()', () => {
const output = {width: 100, height: 100};
expect(readResizeObserverEntry({contentBoxSize: [{inlineSize: 100, blockSize: 100}]})).to.eql(output);
expect(readResizeObserverEntry({contentBoxSize: {inlineSize: 100, blockSize: 100}})).to.eql(output);
expect(readResizeObserverEntry({contentRect: {width: 100, height: 100}})).to.eql(output);
});
});

0 comments on commit c597f24

Please sign in to comment.