react-resize-detector
Advanced tools
Comparing version 11.0.1 to 12.0.0
@@ -1,162 +0,2 @@ | ||
'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) { | ||
case 'debounce': | ||
return debounce(resizeCallback, refreshRate, refreshOptions); | ||
case 'throttle': | ||
return throttle(resizeCallback, refreshRate, refreshOptions); | ||
default: | ||
return resizeCallback; | ||
} | ||
}; | ||
/** | ||
* 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__namespace.useState((targetRef === null || targetRef === void 0 ? void 0 : targetRef.current) || null); | ||
// if targetRef is passed, we need to update the refElement | ||
// we have to use setTimeout because ref get assigned after the hook is called | ||
// in the future releases we are going to remove targetRef and force users to use ref returned by the hook | ||
if (targetRef) { | ||
setTimeout(() => { | ||
if (targetRef.current !== refElement) { | ||
setRefElement(targetRef.current); | ||
} | ||
}, 0); | ||
} | ||
// this is a memo that will be called every time the ref is changed | ||
// This proxy will properly call setState either when the ref is called as a function or when `.current` is set | ||
// we call setState inside to trigger rerender | ||
const refProxy = React__namespace.useMemo(() => new Proxy(node => { | ||
if (node !== refElement) { | ||
setRefElement(node); | ||
} | ||
}, { | ||
get(target, prop) { | ||
if (prop === 'current') { | ||
return refElement; | ||
} | ||
return target[prop]; | ||
}, | ||
set(target, prop, value) { | ||
if (prop === 'current') { | ||
setRefElement(value); | ||
} | ||
else { | ||
target[prop] = value; | ||
} | ||
return true; | ||
} | ||
}), [refElement]); | ||
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) | ||
return; | ||
if (skipResize.current) { | ||
skipResize.current = false; | ||
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 dimensions = getDimensions(entry, box); | ||
setSize(prevSize => { | ||
if (!shouldSetSize(prevSize, dimensions)) | ||
return prevSize; | ||
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({ | ||
width: dimensions.width, | ||
height: dimensions.height, | ||
entry | ||
}); | ||
return dimensions; | ||
}); | ||
}); | ||
}, [handleWidth, handleHeight, skipResize, box]); | ||
// Throttle/Debounce the resize event if refreshMode is configured | ||
const resizeHandler = React.useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [ | ||
resizeCallback, | ||
refreshMode, | ||
refreshRate, | ||
refreshOptions | ||
]); | ||
// Attach ResizeObserver to the element | ||
React.useEffect(() => { | ||
let resizeObserver; | ||
if (refElement) { | ||
resizeObserver = new window.ResizeObserver(resizeHandler); | ||
resizeObserver.observe(refElement, observerOptions); | ||
} | ||
// 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 () => { | ||
var _a, _b, _c; | ||
(_a = resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect) === null || _a === void 0 ? void 0 : _a.call(resizeObserver); | ||
(_c = (_b = resizeHandler).cancel) === null || _c === void 0 ? void 0 : _c.call(_b); | ||
}; | ||
}, [resizeHandler, refElement]); | ||
return Object.assign({ ref: refProxy }, size); | ||
}exports.useResizeDetector=useResizeDetector;//# sourceMappingURL=index.js.map | ||
export { default as useResizeDetector } from './useResizeDetector.js'; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "react-resize-detector", | ||
"version": "11.0.1", | ||
"version": "12.0.0", | ||
"description": "React resize detector", | ||
"main": "build/index.js", | ||
"module": "build/index.esm.js", | ||
"type": "module", | ||
"exports": "./build/index.js", | ||
"types": "./build/index.d.ts", | ||
"files": [ | ||
"build" | ||
], | ||
"types": "build/types/index.d.ts", | ||
"repository": { | ||
@@ -28,21 +28,21 @@ "type": "git", | ||
"devDependencies": { | ||
"@rollup/plugin-commonjs": "^25.0.8", | ||
"@rollup/plugin-node-resolve": "^15.2.3", | ||
"@rollup/plugin-typescript": "^11.1.6", | ||
"@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", | ||
"@rollup/plugin-commonjs": "^28.0.1", | ||
"@rollup/plugin-node-resolve": "^15.3.0", | ||
"@rollup/plugin-typescript": "^12.1.1", | ||
"@types/lodash": "^4.17.13", | ||
"@types/react": "^19.0.1", | ||
"@types/react-dom": "^19.0.2", | ||
"@typescript-eslint/eslint-plugin": "^7.18.0", | ||
"@typescript-eslint/parser": "^7.18.0", | ||
"eslint": "^8.57.1", | ||
"eslint-config-prettier": "^9.1.0", | ||
"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" | ||
"eslint-plugin-react": "^7.37.2", | ||
"prettier": "^3.4.2", | ||
"rollup": "^4.28.1", | ||
"rollup-plugin-node-externals": "^7.1.3", | ||
"tslib": "^2.8.1", | ||
"typescript": "^5.7.2" | ||
}, | ||
"peerDependencies": { | ||
"react": "^18.0.0", | ||
"react-dom": "^18.0.0" | ||
"react": "^18.0.0 || ^19.0.0" | ||
}, | ||
@@ -49,0 +49,0 @@ "author": "Vitalii Maslianok <maslianok@gmail.com> (https://github.com/maslianok)", |
@@ -5,3 +5,3 @@ # Handle element resizes like it's 2024! | ||
#### [Live demo](http://maslianok.github.io/react-resize-detector/) | ||
#### [Live demo](https://react-resize-detector.vercel.app/) | ||
@@ -8,0 +8,0 @@ Modern browsers now have native support for detecting element size changes through [ResizeObservers](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver). This library utilizes ResizeObservers to facilitate managing element size changes in React applications. |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
63334
2
21
682
Yes
16