@etsoo/react
Version:
TypeScript ReactJs UI Independent Framework
99 lines (98 loc) • 3.69 kB
JavaScript
;
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 };
}