Skip to content

Commit

Permalink
feat: add useSize for observing the dimensions of an element
Browse files Browse the repository at this point in the history
  • Loading branch information
kripod committed Oct 25, 2019
1 parent 97dd3dd commit bb74f0b
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 4 deletions.
25 changes: 25 additions & 0 deletions packages/web-api-hooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { useGeolocation, useLocalStorage } from 'web-api-hooks';
- [usePreferredColorScheme](#usepreferredcolorscheme)
- [usePreferredLanguages](#usepreferredlanguages)
- [usePreferredMotionIntensity](#usepreferredmotionintensity)
- [useSize](#usesize)
- [useViewportScale](#useviewportscale)
- [useViewportScrollCoords](#useviewportscrollcoords)
- [useViewportSize](#useviewportsize)
Expand Down Expand Up @@ -266,6 +267,30 @@ function Component() {

Returns **(`"no-preference"` \| `"reduce"`)** Preferred motion intensity.

#### useSize

Tracks size of an element.

⚗️ _The underlying technology is experimental. Please be aware about browser compatibility before using this in production._

##### Parameters

- `ref` **React.RefObject<[HTMLElement](https://developer.mozilla.org/docs/Web/HTML/Element)>** Attribute attached to the element under observation.
- `ResizeObserverOverride` **TypeOf<ResizeObserver>** Replacement for `window.ResizeObserver`, e.g. [a polyfill](https://github.com/juggle/resize-observer).

##### Examples

```javascript
function Component() {
const ref = useRef < HTMLElement > null;
const [width, height] = useSize(ref);
// ...
return <ElementToObserve ref={ref} />;
}
```

Returns **Readonly&lt;\[[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)]>** Dimensions `[width, height]`, falling back to `[0, 0]` when unavailable.

#### useViewportScale

Tracks visual viewport scale.
Expand Down
1 change: 1 addition & 0 deletions packages/web-api-hooks/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ toc:
- usePreferredColorScheme
- usePreferredLanguages
- usePreferredMotionIntensity
- useSize
- useViewportScale
- useViewportScrollCoords
- useViewportSize
Expand Down
1 change: 1 addition & 0 deletions packages/web-api-hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"react": ">=16.8"
},
"dependencies": {
"@types/resize-observer-browser": "^0.1.2",
"network-information-types": "^0.1.0"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/web-api-hooks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export {
default as usePreferredMotionIntensity,
} from './usePreferredMotionIntensity';
export { default as useSessionStorage } from './useSessionStorage';
export { default as useSize } from './useSize';
export { default as useViewportScale } from './useViewportScale';
export { default as useViewportScrollCoords } from './useViewportScrollCoords';
export { default as useViewportSize } from './useViewportSize';
Expand Down
3 changes: 2 additions & 1 deletion packages/web-api-hooks/src/ssr.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jest-environment node */

import React from 'react';
import React, { useRef } from 'react';
import { renderToString } from 'react-dom/server';
import * as hooks from '.';

Expand Down Expand Up @@ -30,6 +30,7 @@ test.each(
useInterval: () => hooks.useInterval(() => {}, 0),
useLocalStorage: () => hooks.useLocalStorage('foo'),
useMedia: () => hooks.useMedia('(min-width: 600px)'),
useSize: () => hooks.useSize(useRef<HTMLElement>(null)),
useSessionStorage: () => hooks.useSessionStorage('foo'),
}),
)('%s supports SSR', (_name, callback) => {
Expand Down
45 changes: 45 additions & 0 deletions packages/web-api-hooks/src/useSize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useEffect, useState } from 'react';
import { canUseDOM } from './utils';

/**
* Tracks size of an element.
*
* ⚗️ _The underlying technology is experimental. Please be aware about browser compatibility before using this in production._
*
* @param ref Attribute attached to the element under observation.
* @param {TypeOf<ResizeObserver>} ResizeObserverOverride Replacement for `window.ResizeObserver`, e.g. [a polyfill](https://github.com/juggle/resize-observer).
*
* @returns Dimensions `[width, height]`, falling back to `[0, 0]` when unavailable.
*
* @example
* function Component() {
* const ref = useRef<HTMLElement>(null);
* const [width, height] = useSize(ref);
* // ...
* return <ElementToObserve ref={ref} />;
* }
*/
export default function useSize(
ref: React.RefObject<HTMLElement>,
ResizeObserverOverride?: typeof ResizeObserver,
): Readonly<[number, number]> {
const [size, setSize] = useState<Readonly<[number, number]>>([0, 0]);

const ResizeObserver =
ResizeObserverOverride || (canUseDOM ? window.ResizeObserver : undefined);
useEffect(() => {
if (!ResizeObserver || !ref.current) return undefined;

const observer = new ResizeObserver(([entry]) => {
const { width, height } = entry.contentRect;
setSize([width, height]);
});
observer.observe(ref.current);

return () => {
observer.disconnect();
};
}, [ResizeObserver, ref]);

return size;
}
3 changes: 1 addition & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
"target": "es2019", // TODO: Use `esnext`
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"esModuleInterop": true,
"types": ["jest", "network-information-types"]
"jsx": "react"
},
"exclude": ["**/*.test.{ts,tsx}"]
}
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2187,7 +2187,7 @@
resolved "https://registry.yarnpkg.com/@pika/types/-/types-0.6.1.tgz#864b1803f3a95093b871ced387bb87779ebfc862"
integrity sha512-1ZsOHGc0qJDofO+/98PfchHJqJjtfZL3liVGi4QZ28GtLmTVuZ4SUJFa5NgbsYawnrr//pdNOfx9JiaLFKpzrA==

"@pika/types@^0.7.0", "@pika/types@^0.7.1":
"@pika/types@^0.7.1":
version "0.7.1"
resolved "https://registry.yarnpkg.com/@pika/types/-/types-0.7.1.tgz#b875b4bb22c3949665e5f3e031634415e1ae0d8e"
integrity sha512-K4jnvnPAXbW1XqUQN4wsAt0H73gbgsRCESWF/Y2ceM1eBA13BS0fxc4ph2yRFXZfvwm+NrLojO14USqwF6gmeA==
Expand Down Expand Up @@ -2391,6 +2391,11 @@
"@types/prop-types" "*"
csstype "^2.2.0"

"@types/resize-observer-browser@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.2.tgz#615d567c094c6500d760289be0ce48c9798672c9"
integrity sha512-4mrAenvAObVQthn05TldKpZ/xW236GyCrpyQvH4hmKVWdobpqM8Fub5Kn4lTNZRKANZ3+P1bq8Zp53asvklKTQ==

"@types/semver@^6.0.1":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.2.tgz#5e8b09f0e4af53034b1d0fb9977a277847836205"
Expand Down

0 comments on commit bb74f0b

Please sign in to comment.