Skip to content

Commit

Permalink
fix: work with Vite out of the box, updated types
Browse files Browse the repository at this point in the history
- the package now works with Vite and other modern bundles out of the box
- the sizes object can now be either `null`, or an object with numeric width and height properties (never null)
  • Loading branch information
FezVrasta committed Mar 22, 2024
1 parent 93ed350 commit 7bc39f6
Show file tree
Hide file tree
Showing 10 changed files with 2,841 additions and 2,431 deletions.
1 change: 1 addition & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[ignore]
dist/

[include]

Expand Down
23 changes: 23 additions & 0 deletions .modern.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// @flow
import * as React from 'react';
import ResizeListener from './ResizeListener';

const defaultReporter = (target: ?HTMLElement) => ({
width: target != null ? target.offsetWidth : null,
height: target != null ? target.offsetHeight : null,
});

export default function useResizeAware(
reporter: typeof defaultReporter = defaultReporter
) {
const [sizes, setSizes] = React.useState(reporter(null));
const onResize = React.useCallback(ref => setSizes(reporter(ref.current)), [
reporter,
]);
const resizeListenerNode = React.useMemo(
() => <ResizeListener onResize={onResize} />,
[onResize]
);

return [resizeListenerNode, sizes];
}
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ The API is simple yet powerful, the `useResizeAware` [Hook](https://reactjs.org/
returns a React node you will place inside the measured element, and an object containing its sizes:

```jsx
import React from 'react';
import useResizeAware from 'react-resize-aware';
import React from "react";
import useResizeAware from "react-resize-aware";

const App = () => {
const [resizeListener, sizes] = useResizeAware();

return (
<div style={{ position: 'relative' }}>
<div style={{ position: "relative" }}>
{resizeListener}
Your content here. (div sizes are {sizes.width} x {sizes.height})
Your content here. (div sizes are {sizes?.width} x {sizes?.height})
</div>
);
};
Expand All @@ -57,21 +57,21 @@ The node is not going to interfer with your layouts, I promise.
### `[..., sizes]` (second element)
This object contains the `width` and `height` properties, these properties are going to be `null` before the component rendered, and will return a `number` after the component rendered.
This object contains the `width` and `height` properties, it could be `null` if the element is not yet rendered.
## Custom `reporter`
You can customize the properties of the `sizes` object by passing a custom `reporter` function as first argument of `useResizeAware`.
```jsx
const customReporter = target => ({
clientWidth: target != null ? target.clientWidth : null,
```tsx
const customReporter = (target: ?HTMLIFrameElement) => ({
clientWidth: target != null ? target.clientWidth : 0,
});

const [resizeListener, sizes] = useResizeAware(customReporter);

return (
<div style={{ position: 'relative' }}>
<div style={{ position: "relative" }}>
{resizeListener}
Your content here. (div clientWidth is {sizes.clientWidth})
</div>
Expand All @@ -87,16 +87,16 @@ For completeness, below you can find an example to show how to make your code re
```jsx
const App = () => {
const [resizeListener, sizes] = useResizeAware();

React.useEffect(() => {
console.log('Do something with the new size values');
console.log("Do something with the new size values");
}, [sizes.width, sizes.height]);

return (
<div style={{ position: 'relative' }}>
<div style={{ position: "relative" }}>
{resizeListener}
Your content here.
</div>
);
}
};
```
2 changes: 1 addition & 1 deletion docs/react-resize-aware.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 12 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-resize-aware",
"version": "3.1.3",
"version": "4.0.0",
"description": "A React hook that makes it possible to listen to element resize events.",
"homepage": "https://github.com/FezVrasta/react-resize-aware#readme",
"author": "Federico Zivolo <federico.zivolo@gmail.com>",
Expand All @@ -23,21 +23,26 @@
"query",
"react-component"
],
"main": "dist/index.js",
"umd:main": "dist/index.umd.js",
"source": "src/index.js",
"type": "module",
"main": "./dist/index.umd.js",
"module": "./dist/index.modern.js",
"source": "./src/index.js",
"exports": {
"require": "./dist/index.cjs",
"default": "./dist/index.modern.js"
},
"scripts": {
"start": "microbundle watch",
"prepare": "microbundle --name useResizeAware --jsx jsx --jsxImportSource react --globals react/jsx-runtime=jsx && cp -f dist/index.umd.js docs/react-resize-aware.js && flow-copy-source src dist && cp src/index.d.ts dist/index.d.ts"
"prepare": "rm -rf dist && microbundle --jsx 'React.createElement' --jsxImportSource react --globals react/jsx-runtime=jsx && flow-copy-source src dist && cp ./dist/index.js.flow ./dist/index.umd.js.flow && cp ./src/index.d.ts ./dist"
},
"files": [
"dist/*",
"src/*"
],
"devDependencies": {
"flow-bin": "^0.113.0",
"flow-bin": "0.199.1",
"flow-copy-source": "^2.0.9",
"microbundle": "0.12.0-next.6",
"microbundle": "^0.15.1",
"react": "16.12.0"
},
"peerDependencies": {
Expand Down
26 changes: 14 additions & 12 deletions src/ResizeListener.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
// @flow
import * as React from 'react';
import useOnResize from './useOnResize';
import * as React from "react";
import useOnResize from "./useOnResize";

export type ReactRef<T> = { current: ?T };

const style = {
display: 'block',
display: "block",
opacity: 0,
position: 'absolute',
position: "absolute",
top: 0,
left: 0,
height: '100%',
width: '100%',
overflow: 'hidden',
pointerEvents: 'none',
height: "100%",
width: "100%",
overflow: "hidden",
pointerEvents: "none",
zIndex: -1,
maxHeight: 'inherit',
maxWidth: 'inherit',
maxHeight: "inherit",
maxWidth: "inherit",
};

// This automatically attaches to itself the resize event listener
// and adds onResize as callback
export default ({
onResize,
}: {
onResize: (React.ElementRef<any>) => void,
}) => {
onResize: (ReactRef<HTMLIFrameElement>) => void,
}): React.Node => {
const ref = React.useRef();
useOnResize(ref, () => onResize(ref));

Expand Down
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// @flow
export { default } from './useResizeAware';
import useResizeAware from "./useResizeAware";
export default useResizeAware;
27 changes: 18 additions & 9 deletions src/useOnResize.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
// @flow
import * as React from 'react';
import * as React from "react";

export type ReactRef<T> = { current: ?T };

// This is just an utility to cleanly attach a `resize` event listener
// to a target HTMLObjectElement or HTMLIFrameElement
// The real Hook is `useResizeAware.js`
export default (ref: React.ElementRef<any>, onResize: () => void) => {
const getTarget = () => ref.current && ref.current.contentDocument && ref.current.contentDocument.defaultView;
export default (
ref: ReactRef<HTMLIFrameElement>,
onResize: () => void
): void => {
const getTarget = () =>
ref.current &&
ref.current.contentDocument &&
ref.current.contentDocument.defaultView;
function run() {
// trigger onResize event on mount to provide initial sizes
onResize();
var target = getTarget();
target && target.addEventListener('resize', onResize);
target && target.addEventListener("resize", onResize);
}
React.useEffect(() => {
if (getTarget()) {
run();
}
else if (ref.current && ref.current.addEventListener) {
ref.current.addEventListener('load', run)
} else if (ref.current && "addEventListener" in ref.current) {
ref.current.addEventListener("load", run);
}

// clean event listener on unmount
Expand All @@ -26,10 +33,12 @@ export default (ref: React.ElementRef<any>, onResize: () => void) => {
// this fixes an issue where contentDocument.defaultView is not a real window object
// as can be the case when used with React portals
const target = getTarget();
if (target == null) return;

const isListener =
target && typeof target.removeEventListener === 'function';
target && typeof target.removeEventListener === "function";

isListener && target.removeEventListener('resize', onResize);
isListener && target.removeEventListener("resize", onResize);
};
}, []);
};
34 changes: 24 additions & 10 deletions src/useResizeAware.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
// @flow
import * as React from 'react';
import ResizeListener from './ResizeListener';
import * as React from "react";
import ResizeListener from "./ResizeListener";

const defaultReporter = (target: ?HTMLElement) => ({
width: target != null ? target.offsetWidth : null,
height: target != null ? target.offsetHeight : null,
});
type Reporter<T> = (target: ?HTMLIFrameElement) => T;

const defaultReporter = (target: ?HTMLIFrameElement) =>
target != null
? {
width: target.offsetWidth,
height: target.offsetHeight,
}
: null;

declare export default function useResizeAware(): [
React.Node,
?{ width: number, height: number }
];
declare export default function useResizeAware<T>(
reporter: Reporter<T>
): [React.Node, T];

export default function useResizeAware(
reporter: typeof defaultReporter = defaultReporter
reporter?: Reporter<mixed> = defaultReporter
) {
const [sizes, setSizes] = React.useState(reporter(null));
const onResize = React.useCallback(ref => setSizes(reporter(ref.current)), [
reporter,
]);
const onResize = React.useCallback(
(ref) => setSizes(reporter(ref.current)),
[reporter]
);
const resizeListenerNode = React.useMemo(
() => <ResizeListener onResize={onResize} />,
[onResize]
Expand Down

0 comments on commit 7bc39f6

Please sign in to comment.