Skip to content

Commit 1dcac3c

Browse files
authored
Merge pull request #3 from envato/typescript
Add TypeScript definitions
2 parents 70945b1 + d9ee924 commit 1dcac3c

15 files changed

+166
-102
lines changed

.babelrc

-6
This file was deleted.

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019 Envato
3+
Copyright (c) 2019-2021 Envato
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+14-11
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313

1414
---
1515

16-
> Observe multiple React components with a single ResizeObserver.
16+
> Observe multiple DOM elements with a single ResizeObserver.
1717
1818
This package provides you with:
1919

20-
* a context `<Provider>` with a `ResizeObserver` instance;
21-
* a `useResizeObserver()` hook to observe any element's changes in size.
20+
- a context `<Provider>` with a `ResizeObserver` instance;
21+
- a `useResizeObserver()` hook to observe any element's size changes.
2222

2323
This allows you to know the size of each observed element.
2424

@@ -41,14 +41,10 @@ npm install @envato/react-resize-observer-hook
4141
```javascript
4242
import { Provider as ResizeObserverProvider } from '@envato/react-resize-observer-hook';
4343

44-
const App = () => (
45-
<ResizeObserverProvider>
46-
...
47-
</ResizeObserverProvider>
48-
);
44+
const App = () => <ResizeObserverProvider>...</ResizeObserverProvider>;
4945
```
5046

51-
⚠️ **Caution** — You may need to pass some props to `<Provider>` to increase browser support. Please refer to the [React Breakpoints API Docs](https://github.com/envato/react-breakpoints/docs/api.md#provider).
47+
⚠️ **Caution** — You may need to pass some props to `<Provider>` to increase **browser support**. Please refer to the [React Breakpoints API Docs](https://github.com/envato/react-breakpoints/docs/api.md#provider).
5248

5349
## Observe an element
5450

@@ -59,7 +55,11 @@ const ObservedDiv = () => {
5955
const [ref, observedEntry] = useResizeObserver();
6056
const { width, height } = observedEntry.contentRect;
6157

62-
return <div ref={ref}>This element is {width}px wide and {height}px high.</div>
58+
return (
59+
<div ref={ref}>
60+
This element is {width}px wide and {height}px high.
61+
</div>
62+
);
6363
};
6464
```
6565

@@ -71,13 +71,16 @@ const options = {
7171
};
7272

7373
const [ref, observedEntry] = useResizeObserver(options);
74+
75+
const width = observedEntry.borderBox[0].inlineSize;
76+
const height = observedEntry.borderBox[0].blockSize;
7477
```
7578

7679
See [MDN reference guide](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) for further information.
7780

7881
# Maintainers
7982

80-
* [Marc Dingena](https://github.com/mdingena) (owner)
83+
- [Marc Dingena](https://github.com/mdingena) (owner)
8184

8285
# Contributing
8386

package.json

+20-11
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,50 @@
33
"version": "1.0.1",
44
"description": "Observe multiple React components with a single ResizeObserver.",
55
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
67
"scripts": {
7-
"build": "babel src/ -d dist/ --source-maps",
8+
"build": "tsc -b",
89
"prepare": "npm run build"
910
},
1011
"repository": {
1112
"type": "git",
1213
"url": "git+https://github.com/envato/react-resize-observer-hook.git"
1314
},
1415
"keywords": [
16+
"resize-observer",
1517
"react-hooks",
1618
"hooks",
1719
"react",
18-
"performance",
19-
"resize-observer"
20+
"performance"
2021
],
21-
"author": "Envato",
22+
"author": "[email protected]",
2223
"license": "MIT",
2324
"bugs": {
2425
"url": "https://github.com/envato/react-resize-observer-hook/issues"
2526
},
2627
"homepage": "https://github.com/envato/react-resize-observer-hook#readme",
2728
"peerDependencies": {
28-
"react": ">=16.8.0",
29-
"react-dom": ">=16.8.0"
29+
"react": "16.8 - 17",
30+
"react-dom": "16.8 - 17"
3031
},
3132
"devDependencies": {
32-
"@babel/cli": "^7.8.4",
33-
"@babel/core": "^7.8.6",
34-
"@babel/preset-env": "^7.7.7",
35-
"@babel/preset-react": "^7.8.3",
33+
"@types/react": "^17.0.0",
34+
"@typescript-eslint/eslint-plugin": "^4.13.0",
35+
"@typescript-eslint/parser": "^4.13.0",
36+
"babel-eslint": "^10.1.0",
37+
"eslint": "^7.17.0",
38+
"eslint-config-react-app": "^6.0.0",
39+
"eslint-plugin-flowtype": "^5.2.0",
40+
"eslint-plugin-import": "^2.22.1",
41+
"eslint-plugin-jsx-a11y": "^6.4.1",
42+
"eslint-plugin-react": "^7.22.0",
43+
"eslint-plugin-react-hooks": "^4.2.0",
3644
"husky": "^4.3.7",
3745
"lint-staged": "^10.5.3",
3846
"prettier": "^2.2.1",
3947
"react": "^17.0.1",
40-
"react-dom": "^17.0.1"
48+
"react-dom": "^17.0.1",
49+
"typescript": "^4.2.2"
4150
},
4251
"eslintConfig": {
4352
"extends": "react-app"

src/Context.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { createContext } from 'react';
2+
3+
export const Context = createContext<ResizeObserver | null>(null);

src/ExtendedResizeObserverEntry.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { ObservedElement } from './ObservedElement';
2+
3+
export interface ExtendedResizeObserverEntry extends ResizeObserverEntry {
4+
target: ObservedElement;
5+
}

src/ObservedElement.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry';
2+
3+
export interface ObservedElement extends Element {
4+
onResizeObservation?: (resizeObserverEntry: ExtendedResizeObserverEntry) => void;
5+
}

src/Provider.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { createResizeObserver } from './createResizeObserver';
2+
import { Context } from './Context';
3+
4+
interface ProviderProps {
5+
ponyfill?: typeof ResizeObserver;
6+
children: React.ReactNode;
7+
}
8+
9+
/**
10+
* See API Docs: {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#provider|Provider}
11+
*
12+
* Returns a React context provider with a ResizeObserver instance as its value.
13+
* Uses `window.ResizeObserver` to construct the instance if no `ponyfill` prop is provided.
14+
* @example
15+
* return (
16+
* <Provider ponyfill={ResizeObserver}>
17+
* ...
18+
* </Provider>
19+
* );
20+
*/
21+
export const Provider = ({ ponyfill = undefined, children }: ProviderProps) => {
22+
const instance = createResizeObserver(ponyfill || window.ResizeObserver);
23+
24+
return <Context.Provider value={instance}>{children}</Context.Provider>;
25+
};

src/createResizeObserver.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry';
2+
3+
/**
4+
* Creates a new ResizeObserver instance that works with the
5+
* {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#useresizeobserver|useResizeObserver}
6+
* hook.
7+
* @example
8+
* const resizeObserverInstance = createResizeObserver(window.ResizeObserver);
9+
* return (
10+
* <Context.Provider value={resizeObserverInstance}>
11+
* ...
12+
* </Context.Provider>
13+
* );
14+
*/
15+
export const createResizeObserver = (Constructor: typeof ResizeObserver) => {
16+
const handleResizeObserverEntry = (resizeObserverEntry: ExtendedResizeObserverEntry) => {
17+
const { onResizeObservation } = resizeObserverEntry.target;
18+
onResizeObservation && onResizeObservation(resizeObserverEntry);
19+
};
20+
21+
return new Constructor((entries: ExtendedResizeObserverEntry[]) => entries.forEach(handleResizeObserverEntry));
22+
};

src/index.js

-2
This file was deleted.

src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { Context } from './Context';
2+
export { Provider } from './Provider';
3+
export { createResizeObserver } from './createResizeObserver';
4+
export { useResizeObserver } from './useResizeObserver';

src/resizeObserverContext.js

-32
This file was deleted.

src/useResizeObserver.js

-39
This file was deleted.

src/useResizeObserver.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { useContext, useCallback, useRef, useState } from 'react';
2+
import { Context } from './Context';
3+
import { ObservedElement } from './ObservedElement';
4+
import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry';
5+
6+
/**
7+
* See API Docs: {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#useresizeobserver|useResizeObserver}
8+
*
9+
* Returns a React callback ref to attach to a DOM element. It also returns
10+
* a resize observation entry every time the observed element changes size.
11+
* This causes the component that uses `useResizeObserver` to rerender.
12+
* @example
13+
* const [ref, observedEntry] = useResizeObserver(options);
14+
* const observedWidth = observedEntry.borderBoxSize[0].inlineSize;
15+
* return (
16+
* <div ref={ref}>
17+
* This container is {observedWidth}px wide.
18+
* </div>
19+
* );
20+
*/
21+
export const useResizeObserver = (
22+
options: ResizeObserverOptions = {}
23+
): [React.RefCallback<ObservedElement | null>, ExtendedResizeObserverEntry | null] => {
24+
const resizeObserver = useContext<ResizeObserver | null>(Context);
25+
26+
const [observedEntry, setObservedEntry] = useState<ExtendedResizeObserverEntry | null>(null);
27+
28+
const handleResizeObservation = (resizeObserverEntry: ExtendedResizeObserverEntry) =>
29+
setObservedEntry(resizeObserverEntry);
30+
31+
const ref = useRef<ObservedElement | null>(null);
32+
33+
const setRef = useCallback(
34+
node => {
35+
if (ref.current) {
36+
resizeObserver?.unobserve(ref.current);
37+
delete ref.current.onResizeObservation;
38+
}
39+
40+
if (node) {
41+
node.onResizeObservation = handleResizeObservation;
42+
resizeObserver?.observe(node, options);
43+
}
44+
45+
ref.current = node;
46+
},
47+
[resizeObserver, options]
48+
);
49+
50+
return [setRef, observedEntry];
51+
};

tsconfig.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "commonjs",
5+
"jsx": "react-jsx",
6+
"declaration": true,
7+
"declarationMap": true,
8+
"sourceMap": true,
9+
"outDir": "./dist",
10+
"strict": true,
11+
"esModuleInterop": true,
12+
"skipLibCheck": true,
13+
"forceConsistentCasingInFileNames": true
14+
},
15+
"include": ["./src/**/*"]
16+
}

0 commit comments

Comments
 (0)