Socket
Socket
Sign inDemoInstall

react-resize-detector

Package Overview
Dependencies
Maintainers
2
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-resize-detector - npm Package Compare versions

Comparing version 10.0.1 to 11.0.0-beta.0

118

build/index.esm.js

@@ -1,2 +0,5 @@

import {useRef,useState,useMemo,useCallback,useEffect}from'react';import debounce from'lodash/debounce';import throttle from'lodash/throttle';const patchResizeCallback = (resizeCallback, refreshMode, refreshRate, refreshOptions) => {
import*as React from'react';import {useRef,useState,useCallback,useEffect}from'react';import debounce from'lodash/debounce';import throttle from'lodash/throttle';/**
* Wraps the resize callback with a lodash debounce / throttle based on the refresh mode
*/
const patchResizeCallback = (resizeCallback, refreshMode, refreshRate, refreshOptions) => {
switch (refreshMode) {

@@ -10,10 +13,23 @@ case 'debounce':

}
};function useResizeDetector({ skipOnMount = false, refreshMode, refreshRate = 1000, refreshOptions, handleWidth = true, handleHeight = true, targetRef, observerOptions, onResize } = {}) {
const skipResize = useRef(skipOnMount);
const [size, setSize] = useState({
width: undefined,
height: undefined
};
/**
* A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
* prop or avoid re-executing effects when passed as a dependency
*/
const useCallbackRef =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(callback) => {
const callbackRef = React.useRef(callback);
React.useEffect(() => {
callbackRef.current = callback;
});
return React.useMemo(() => ((...args) => { var _a; return (_a = callbackRef.current) === null || _a === void 0 ? void 0 : _a.call(callbackRef, ...args); }), []);
};
/** `useRef` hook doesn't handle conditional rendering or dynamic ref changes.
* This hook creates a proxy that ensures that `refElement` is updated whenever the ref is changed. */
const useRefProxy =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(targetRef) => {
// we are going to use this ref to store the last element that was passed to the hook
const [refElement, setRefElement] = useState((targetRef === null || targetRef === void 0 ? void 0 : targetRef.current) || null);
const [refElement, setRefElement] = React.useState((targetRef === null || targetRef === void 0 ? void 0 : targetRef.current) || null);
// if targetRef is passed, we need to update the refElement

@@ -32,3 +48,3 @@ // we have to use setTimeout because ref get assigned after the hook is called

// we call setState inside to trigger rerender
const refProxy = useMemo(() => new Proxy(node => {
const refProxy = React.useMemo(() => new Proxy(node => {
if (node !== refElement) {

@@ -54,14 +70,42 @@ setRefElement(node);

}), [refElement]);
const shouldSetSize = useCallback((prevSize, nextSize) => {
if (prevSize.width === nextSize.width && prevSize.height === nextSize.height) {
// skip if dimensions haven't changed
return false;
}
if ((prevSize.width === nextSize.width && !handleHeight) ||
(prevSize.height === nextSize.height && !handleWidth)) {
// process `handleHeight/handleWidth` props
return false;
}
return true;
}, [handleWidth, handleHeight]);
return { refProxy, refElement, setRefElement };
};
/** Calculates the dimensions of the element based on the current box model.
* @see https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model
*/
const getDimensions = (entry, box) => {
// Value Border Padding Inner Content
// ---------------------------------------------------
// 'border-box' Yes Yes Yes
// 'content-box' No No Yes
// undefined No No? Yes
if (box === 'border-box') {
return {
width: entry.borderBoxSize[0].inlineSize,
height: entry.borderBoxSize[0].blockSize
};
}
if (box === 'content-box') {
return {
width: entry.contentBoxSize[0].inlineSize,
height: entry.contentBoxSize[0].blockSize
};
}
return {
width: entry.contentRect.width,
height: entry.contentRect.height
};
};// eslint-disable-next-line @typescript-eslint/no-explicit-any
function useResizeDetector({ skipOnMount = false, refreshMode, refreshRate = 1000, refreshOptions, handleWidth = true, handleHeight = true, targetRef, observerOptions, onResize } = {}) {
// If `skipOnMount` is enabled, skip the first resize event
const skipResize = useRef(skipOnMount);
// Wrap the `onResize` callback with a ref to avoid re-renders
const onResizeRef = useCallbackRef(onResize);
const [size, setSize] = useState({
width: undefined,
height: undefined
});
// Create a proxy ref to handle conditional rendering and dynamic ref changes of the target element
const { refProxy, refElement } = useRefProxy(targetRef);
const { box } = observerOptions || {};
const resizeCallback = useCallback((entries) => {

@@ -74,11 +118,19 @@ if (!handleWidth && !handleHeight)

}
// Only update the size if one of the observed dimensions has changed
const shouldSetSize = (prevSize, nextSize) => (handleWidth && prevSize.width !== nextSize.width) || (handleHeight && prevSize.height !== nextSize.height);
entries.forEach(entry => {
const { width, height } = (entry === null || entry === void 0 ? void 0 : entry.contentRect) || {};
const dimensions = getDimensions(entry, box);
setSize(prevSize => {
if (!shouldSetSize(prevSize, { width, height }))
if (!shouldSetSize(prevSize, dimensions))
return prevSize;
return { width, height };
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({
width: dimensions.width,
height: dimensions.height,
entry
});
return dimensions;
});
});
}, [handleWidth, handleHeight, skipResize, shouldSetSize]);
}, [handleWidth, handleHeight, skipResize, box]);
// Throttle/Debounce the resize event if refreshMode is configured
const resizeHandler = useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [

@@ -90,3 +142,3 @@ resizeCallback,

]);
// on refElement change
// Attach ResizeObserver to the element
useEffect(() => {

@@ -98,7 +150,12 @@ let resizeObserver;

}
else {
if (size.width || size.height) {
setSize({ width: undefined, height: undefined });
}
// If refElement is not available, reset the size
else if (size.width || size.height) {
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({
width: null,
height: null,
entry: null
});
setSize({ width: undefined, height: undefined });
}
// Disconnect the ResizeObserver when the component is unmounted
return () => {

@@ -110,6 +167,3 @@ var _a, _b, _c;

}, [resizeHandler, refElement]);
useEffect(() => {
onResize === null || onResize === void 0 ? void 0 : onResize(size.width, size.height);
}, [size]);
return Object.assign({ ref: refProxy }, size);
}export{useResizeDetector};//# sourceMappingURL=index.esm.js.map

@@ -1,2 +0,5 @@

'use strict';var react=require('react'),debounce=require('lodash/debounce'),throttle=require('lodash/throttle');const patchResizeCallback = (resizeCallback, refreshMode, refreshRate, refreshOptions) => {
'use strict';var React=require('react'),debounce=require('lodash/debounce'),throttle=require('lodash/throttle');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var React__namespace=/*#__PURE__*/_interopNamespaceDefault(React);/**
* Wraps the resize callback with a lodash debounce / throttle based on the refresh mode
*/
const patchResizeCallback = (resizeCallback, refreshMode, refreshRate, refreshOptions) => {
switch (refreshMode) {

@@ -10,10 +13,23 @@ case 'debounce':

}
};function useResizeDetector({ skipOnMount = false, refreshMode, refreshRate = 1000, refreshOptions, handleWidth = true, handleHeight = true, targetRef, observerOptions, onResize } = {}) {
const skipResize = react.useRef(skipOnMount);
const [size, setSize] = react.useState({
width: undefined,
height: undefined
};
/**
* A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
* prop or avoid re-executing effects when passed as a dependency
*/
const useCallbackRef =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(callback) => {
const callbackRef = React__namespace.useRef(callback);
React__namespace.useEffect(() => {
callbackRef.current = callback;
});
return React__namespace.useMemo(() => ((...args) => { var _a; return (_a = callbackRef.current) === null || _a === void 0 ? void 0 : _a.call(callbackRef, ...args); }), []);
};
/** `useRef` hook doesn't handle conditional rendering or dynamic ref changes.
* This hook creates a proxy that ensures that `refElement` is updated whenever the ref is changed. */
const useRefProxy =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(targetRef) => {
// we are going to use this ref to store the last element that was passed to the hook
const [refElement, setRefElement] = react.useState((targetRef === null || targetRef === void 0 ? void 0 : targetRef.current) || null);
const [refElement, setRefElement] = React__namespace.useState((targetRef === null || targetRef === void 0 ? void 0 : targetRef.current) || null);
// if targetRef is passed, we need to update the refElement

@@ -32,3 +48,3 @@ // we have to use setTimeout because ref get assigned after the hook is called

// we call setState inside to trigger rerender
const refProxy = react.useMemo(() => new Proxy(node => {
const refProxy = React__namespace.useMemo(() => new Proxy(node => {
if (node !== refElement) {

@@ -54,15 +70,43 @@ setRefElement(node);

}), [refElement]);
const shouldSetSize = react.useCallback((prevSize, nextSize) => {
if (prevSize.width === nextSize.width && prevSize.height === nextSize.height) {
// skip if dimensions haven't changed
return false;
}
if ((prevSize.width === nextSize.width && !handleHeight) ||
(prevSize.height === nextSize.height && !handleWidth)) {
// process `handleHeight/handleWidth` props
return false;
}
return true;
}, [handleWidth, handleHeight]);
const resizeCallback = react.useCallback((entries) => {
return { refProxy, refElement, setRefElement };
};
/** Calculates the dimensions of the element based on the current box model.
* @see https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model
*/
const getDimensions = (entry, box) => {
// Value Border Padding Inner Content
// ---------------------------------------------------
// 'border-box' Yes Yes Yes
// 'content-box' No No Yes
// undefined No No? Yes
if (box === 'border-box') {
return {
width: entry.borderBoxSize[0].inlineSize,
height: entry.borderBoxSize[0].blockSize
};
}
if (box === 'content-box') {
return {
width: entry.contentBoxSize[0].inlineSize,
height: entry.contentBoxSize[0].blockSize
};
}
return {
width: entry.contentRect.width,
height: entry.contentRect.height
};
};// eslint-disable-next-line @typescript-eslint/no-explicit-any
function useResizeDetector({ skipOnMount = false, refreshMode, refreshRate = 1000, refreshOptions, handleWidth = true, handleHeight = true, targetRef, observerOptions, onResize } = {}) {
// If `skipOnMount` is enabled, skip the first resize event
const skipResize = React.useRef(skipOnMount);
// Wrap the `onResize` callback with a ref to avoid re-renders
const onResizeRef = useCallbackRef(onResize);
const [size, setSize] = React.useState({
width: undefined,
height: undefined
});
// Create a proxy ref to handle conditional rendering and dynamic ref changes of the target element
const { refProxy, refElement } = useRefProxy(targetRef);
const { box } = observerOptions || {};
const resizeCallback = React.useCallback((entries) => {
if (!handleWidth && !handleHeight)

@@ -74,12 +118,20 @@ return;

}
// Only update the size if one of the observed dimensions has changed
const shouldSetSize = (prevSize, nextSize) => (handleWidth && prevSize.width !== nextSize.width) || (handleHeight && prevSize.height !== nextSize.height);
entries.forEach(entry => {
const { width, height } = (entry === null || entry === void 0 ? void 0 : entry.contentRect) || {};
const dimensions = getDimensions(entry, box);
setSize(prevSize => {
if (!shouldSetSize(prevSize, { width, height }))
if (!shouldSetSize(prevSize, dimensions))
return prevSize;
return { width, height };
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({
width: dimensions.width,
height: dimensions.height,
entry
});
return dimensions;
});
});
}, [handleWidth, handleHeight, skipResize, shouldSetSize]);
const resizeHandler = react.useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [
}, [handleWidth, handleHeight, skipResize, box]);
// Throttle/Debounce the resize event if refreshMode is configured
const resizeHandler = React.useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [
resizeCallback,

@@ -90,4 +142,4 @@ refreshMode,

]);
// on refElement change
react.useEffect(() => {
// Attach ResizeObserver to the element
React.useEffect(() => {
let resizeObserver;

@@ -98,7 +150,12 @@ if (refElement) {

}
else {
if (size.width || size.height) {
setSize({ width: undefined, height: undefined });
}
// If refElement is not available, reset the size
else if (size.width || size.height) {
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({
width: null,
height: null,
entry: null
});
setSize({ width: undefined, height: undefined });
}
// Disconnect the ResizeObserver when the component is unmounted
return () => {

@@ -110,6 +167,3 @@ var _a, _b, _c;

}, [resizeHandler, refElement]);
react.useEffect(() => {
onResize === null || onResize === void 0 ? void 0 : onResize(size.width, size.height);
}, [size]);
return Object.assign({ ref: refProxy }, size);
}exports.useResizeDetector=useResizeDetector;//# sourceMappingURL=index.js.map
import useResizeDetector from './useResizeDetector';
export { useResizeDetector };
export type { UseResizeDetectorReturn, useResizeDetectorProps } from './types';
export type { UseResizeDetectorReturn, useResizeDetectorProps, OnResizeCallback, ResizePayload, ResfreshModeType, ResfreshOptionsType, Dimensions } from './types';
import type { MutableRefObject } from 'react';
export type ReactResizeDetectorDimensions = {
export type Dimensions = {
height?: number;
width?: number;
};
/** If element is mounted, returns its dimensions and `ResizeObserverEntry`
* If element is unmounted, returns null */
export type ResizePayload = {
width: number;
height: number;
entry: ResizeObserverEntry;
} | {
width: null;
height: null;
entry: null;
};
export type ResfreshModeType = 'throttle' | 'debounce';

@@ -11,6 +22,7 @@ export type ResfreshOptionsType = {

};
export type OnResizeCallback = (width?: number, height?: number) => void;
export type OnResizeCallback = (payload: ResizePayload) => void;
export type Props = {
/**
* Function that will be invoked with observable element's width and height.
* Function that will be invoked with observable element's width, height and ResizeObserverEntry.
* If element is unmounted, width and height will be null.
* Default: undefined

@@ -62,3 +74,3 @@ */

};
export interface UseResizeDetectorReturn<T> extends ReactResizeDetectorDimensions {
export interface UseResizeDetectorReturn<T> extends Dimensions {
ref: OnRefChangeType<T>;

@@ -65,0 +77,0 @@ }

@@ -0,4 +1,27 @@

import * as React from 'react';
import type { DebouncedFunc } from 'lodash';
import { Props } from './types';
import { OnRefChangeType, Props } from './types';
export type PatchedResizeObserverCallback = DebouncedFunc<ResizeObserverCallback> | ResizeObserverCallback;
/**
* Wraps the resize callback with a lodash debounce / throttle based on the refresh mode
*/
export declare const patchResizeCallback: (resizeCallback: ResizeObserverCallback, refreshMode: Props['refreshMode'], refreshRate: Props['refreshRate'], refreshOptions: Props['refreshOptions']) => PatchedResizeObserverCallback;
/**
* A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
* prop or avoid re-executing effects when passed as a dependency
*/
export declare const useCallbackRef: <T extends (...args: any[]) => any>(callback: T | undefined) => T;
/** `useRef` hook doesn't handle conditional rendering or dynamic ref changes.
* This hook creates a proxy that ensures that `refElement` is updated whenever the ref is changed. */
export declare const useRefProxy: <T extends HTMLElement = any>(targetRef: React.MutableRefObject<T | null> | undefined) => {
refProxy: OnRefChangeType<T>;
refElement: T | null;
setRefElement: React.Dispatch<React.SetStateAction<T | null>>;
};
/** Calculates the dimensions of the element based on the current box model.
* @see https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model
*/
export declare const getDimensions: (entry: ResizeObserverEntry, box: ResizeObserverBoxOptions | undefined) => {
width: number;
height: number;
};
{
"name": "react-resize-detector",
"version": "10.0.1",
"version": "11.0.0-beta.0",
"description": "React resize detector",

@@ -19,5 +19,4 @@ "main": "build/index.js",

"prettier": "prettier --write .",
"lint": "eslint .",
"lint-fix": "eslint --fix",
"fix": "npm run prettier && npm run lint-fix",
"lint": "eslint . --fix",
"fix": "npm run prettier && npm run lint",
"prerelease": "npm version prerelease --preid=rc",

@@ -30,19 +29,17 @@ "prepublishOnly": "npm run build"

"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@types/lodash": "^4.14.202",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^6.18.1",
"@typescript-eslint/parser": "^6.18.1",
"eslint": "^8.56.0",
"@types/lodash": "^4.17.4",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.11.0",
"@typescript-eslint/parser": "^7.11.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-react": "^7.33.2",
"prettier": "^3.1.1",
"rollup": "^4.9.5",
"rollup-plugin-node-externals": "^6.1.2",
"tslib": "^2.6.2",
"typescript": "^5.3.3"
"eslint-plugin-react": "^7.34.2",
"prettier": "^3.2.5",
"rollup": "^4.18.0",
"rollup-plugin-node-externals": "^7.1.2",
"typescript": "^5.4.5"
},

@@ -57,5 +54,2 @@ "peerDependencies": {

},
"directories": {
"example": "example"
},
"homepage": "https://github.com/maslianok/react-resize-detector",

@@ -62,0 +56,0 @@ "keywords": [

# Handle element resizes like it's 2024!
<img src="https://img.shields.io/npm/dm/react-resize-detector?style=flat-square"> <img src="https://badgen.net/bundlephobia/minzip/react-resize-detector?style=flat-square"> <img src="https://badgen.net/bundlephobia/tree-shaking/react-resize-detector?style=flat-square">
<img src="https://img.shields.io/npm/v/react-resize-detector?style=flat-square" /> <img src="https://img.shields.io/npm/l/react-resize-detector?style=flat-square" /> <img src="https://img.shields.io/npm/dm/react-resize-detector?style=flat-square" /> <img src="https://img.shields.io/bundlejs/size/react-resize-detector?style=flat-square" />

@@ -13,7 +13,7 @@ #### [Live demo](http://maslianok.github.io/react-resize-detector/)

🐠 Used by <a href="https://github.com/maslianok/react-resize-detector/network/dependents" target="__blank">160k repositories</a>
🐠 Used by <a href="https://github.com/maslianok/react-resize-detector/network/dependents" target="__blank">170k repositories</a>
🦄 Produces <a href="https://npmtrends.com/react-resize-detector" target="__blank">100 million downloads annually</a>
No `window.resize` listeners! No timeouts!
No `window.resize` listeners! No timeouts!

@@ -113,3 +113,3 @@ ## Is it necessary for you to use this library?

| --------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| onResize | Func | Function that will be invoked with `width` and `height` arguments | `undefined` |
| onResize | Func | Function that will be invoked with `width`, `height` and ResizeObserver `entry` arguments | `undefined` |
| handleWidth | Bool | Trigger `onResize` on width change | `true` |

@@ -116,0 +116,0 @@ | handleHeight | Bool | Trigger `onResize` on height change | `true` |

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc