UNPKG

@etsoo/react

Version:

TypeScript ReactJs UI Independent Framework

99 lines (98 loc) 3.69 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useDimensions = useDimensions; const shared_1 = require("@etsoo/shared"); const react_1 = __importDefault(require("react")); const useDelayedExecutor_1 = require("./useDelayedExecutor"); /** * Calculate element(s) dimensions * @param elements Observed elments count * @param updateCallback Update callback * @param miliseconds Miliseconds to wait before update * @param equalCallback Equall callback */ function useDimensions(elements, updateCallback, miliseconds = 50, equalCallback = shared_1.DomUtils.dimensionEqual) { // State const [state, setState] = react_1.default.useState({ count: 0, indices: [] }); // Dimentions const dimensions = react_1.default.useRef(null); if (dimensions.current == null) { // Init const init = []; for (let e = 0; e < elements; e++) { init.push(((index) => { return [ (instance) => { if (instance != null) { // Current element const currentElement = init[index][1]; if (currentElement != null) { // Same target, return if (currentElement == instance) return; // Cancel observation resizeObserver.unobserve(currentElement); } // Update element init[index][1] = instance; // Start observe resizeObserver.observe(instance); } } ]; })(e)); } dimensions.current = init; } const delayed = (0, useDelayedExecutor_1.useDelayedExecutor)(setState, miliseconds); // Observer const resizeObserver = new ResizeObserver((entries) => { // Update Rect const indices = []; const init = dimensions.current; entries.forEach((entry) => { const index = init.findIndex((item) => item[1] === entry.target); if (index !== -1) { // Previous rect const pre = init[index][2]; // New rect const rect = entry.target.getBoundingClientRect(); // Check equal if (!equalCallback(pre, rect)) { // Update callback if (updateCallback) { // Return false means no further push if (updateCallback(entry.target, rect) === false) return; } // Update rect init[index][2] = rect; // Push for update indices.push(index); } } }); // Update state if (indices.length > 0) { // Count only for unique update const update = { count: state.count + 1, indices }; delayed.call(undefined, update); } }); // Layout ready react_1.default.useEffect(() => { return () => { // Clear the observer resizeObserver.disconnect(); delayed.clear(); }; }, []); // Return return { dimensions: dimensions.current, state }; }