Skip to content

Commit

Permalink
Merge pull request #3 from envato/typescript
Browse files Browse the repository at this point in the history
Add TypeScript definitions
  • Loading branch information
mdingena authored Mar 2, 2021
2 parents 70945b1 + d9ee924 commit 1dcac3c
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 102 deletions.
6 changes: 0 additions & 6 deletions .babelrc

This file was deleted.

2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 Envato
Copyright (c) 2019-2021 Envato

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

---

> Observe multiple React components with a single ResizeObserver.
> Observe multiple DOM elements with a single ResizeObserver.
This package provides you with:

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

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

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

const App = () => (
<ResizeObserverProvider>
...
</ResizeObserverProvider>
);
const App = () => <ResizeObserverProvider>...</ResizeObserverProvider>;
```

⚠️ **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).
⚠️ **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).

## Observe an element

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

return <div ref={ref}>This element is {width}px wide and {height}px high.</div>
return (
<div ref={ref}>
This element is {width}px wide and {height}px high.
</div>
);
};
```

Expand All @@ -71,13 +71,16 @@ const options = {
};

const [ref, observedEntry] = useResizeObserver(options);

const width = observedEntry.borderBox[0].inlineSize;
const height = observedEntry.borderBox[0].blockSize;
```

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

# Maintainers

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

# Contributing

Expand Down
31 changes: 20 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,50 @@
"version": "1.0.1",
"description": "Observe multiple React components with a single ResizeObserver.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "babel src/ -d dist/ --source-maps",
"build": "tsc -b",
"prepare": "npm run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/envato/react-resize-observer-hook.git"
},
"keywords": [
"resize-observer",
"react-hooks",
"hooks",
"react",
"performance",
"resize-observer"
"performance"
],
"author": "Envato",
"author": "marc.dingena@envato.com",
"license": "MIT",
"bugs": {
"url": "https://github.com/envato/react-resize-observer-hook/issues"
},
"homepage": "https://github.com/envato/react-resize-observer-hook#readme",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
"react": "16.8 - 17",
"react-dom": "16.8 - 17"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.6",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.8.3",
"@types/react": "^17.0.0",
"@typescript-eslint/eslint-plugin": "^4.13.0",
"@typescript-eslint/parser": "^4.13.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.17.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.7",
"lint-staged": "^10.5.3",
"prettier": "^2.2.1",
"react": "^17.0.1",
"react-dom": "^17.0.1"
"react-dom": "^17.0.1",
"typescript": "^4.2.2"
},
"eslintConfig": {
"extends": "react-app"
Expand Down
3 changes: 3 additions & 0 deletions src/Context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createContext } from 'react';

export const Context = createContext<ResizeObserver | null>(null);
5 changes: 5 additions & 0 deletions src/ExtendedResizeObserverEntry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ObservedElement } from './ObservedElement';

export interface ExtendedResizeObserverEntry extends ResizeObserverEntry {
target: ObservedElement;
}
5 changes: 5 additions & 0 deletions src/ObservedElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry';

export interface ObservedElement extends Element {
onResizeObservation?: (resizeObserverEntry: ExtendedResizeObserverEntry) => void;
}
25 changes: 25 additions & 0 deletions src/Provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createResizeObserver } from './createResizeObserver';
import { Context } from './Context';

interface ProviderProps {
ponyfill?: typeof ResizeObserver;
children: React.ReactNode;
}

/**
* See API Docs: {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#provider|Provider}
*
* Returns a React context provider with a ResizeObserver instance as its value.
* Uses `window.ResizeObserver` to construct the instance if no `ponyfill` prop is provided.
* @example
* return (
* <Provider ponyfill={ResizeObserver}>
* ...
* </Provider>
* );
*/
export const Provider = ({ ponyfill = undefined, children }: ProviderProps) => {
const instance = createResizeObserver(ponyfill || window.ResizeObserver);

return <Context.Provider value={instance}>{children}</Context.Provider>;
};
22 changes: 22 additions & 0 deletions src/createResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry';

/**
* Creates a new ResizeObserver instance that works with the
* {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#useresizeobserver|useResizeObserver}
* hook.
* @example
* const resizeObserverInstance = createResizeObserver(window.ResizeObserver);
* return (
* <Context.Provider value={resizeObserverInstance}>
* ...
* </Context.Provider>
* );
*/
export const createResizeObserver = (Constructor: typeof ResizeObserver) => {
const handleResizeObserverEntry = (resizeObserverEntry: ExtendedResizeObserverEntry) => {
const { onResizeObservation } = resizeObserverEntry.target;
onResizeObservation && onResizeObservation(resizeObserverEntry);
};

return new Constructor((entries: ExtendedResizeObserverEntry[]) => entries.forEach(handleResizeObserverEntry));
};
2 changes: 0 additions & 2 deletions src/index.js

This file was deleted.

4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { Context } from './Context';
export { Provider } from './Provider';
export { createResizeObserver } from './createResizeObserver';
export { useResizeObserver } from './useResizeObserver';
32 changes: 0 additions & 32 deletions src/resizeObserverContext.js

This file was deleted.

39 changes: 0 additions & 39 deletions src/useResizeObserver.js

This file was deleted.

51 changes: 51 additions & 0 deletions src/useResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useContext, useCallback, useRef, useState } from 'react';
import { Context } from './Context';
import { ObservedElement } from './ObservedElement';
import { ExtendedResizeObserverEntry } from './ExtendedResizeObserverEntry';

/**
* See API Docs: {@linkcode https://github.com/envato/react-breakpoints/blob/master/docs/api.md#useresizeobserver|useResizeObserver}
*
* Returns a React callback ref to attach to a DOM element. It also returns
* a resize observation entry every time the observed element changes size.
* This causes the component that uses `useResizeObserver` to rerender.
* @example
* const [ref, observedEntry] = useResizeObserver(options);
* const observedWidth = observedEntry.borderBoxSize[0].inlineSize;
* return (
* <div ref={ref}>
* This container is {observedWidth}px wide.
* </div>
* );
*/
export const useResizeObserver = (
options: ResizeObserverOptions = {}
): [React.RefCallback<ObservedElement | null>, ExtendedResizeObserverEntry | null] => {
const resizeObserver = useContext<ResizeObserver | null>(Context);

const [observedEntry, setObservedEntry] = useState<ExtendedResizeObserverEntry | null>(null);

const handleResizeObservation = (resizeObserverEntry: ExtendedResizeObserverEntry) =>
setObservedEntry(resizeObserverEntry);

const ref = useRef<ObservedElement | null>(null);

const setRef = useCallback(
node => {
if (ref.current) {
resizeObserver?.unobserve(ref.current);
delete ref.current.onResizeObservation;
}

if (node) {
node.onResizeObservation = handleResizeObservation;
resizeObserver?.observe(node, options);
}

ref.current = node;
},
[resizeObserver, options]
);

return [setRef, observedEntry];
};
16 changes: 16 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"jsx": "react-jsx",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["./src/**/*"]
}

0 comments on commit 1dcac3c

Please sign in to comment.