@kubit-ui-web/react-components
Version:
Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience
127 lines • 6.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getClippingRect = exports.getClippingElementAncestors = exports.hasFixedPositionAncestor = exports.getClientRectFromClippingAncestor = exports.getInnerBoundingClientRect = void 0;
const getBoundingClientRect_1 = require("./getBoundingClientRect");
const getDocumentRect_1 = require("./getDocumentRect");
const getOverflowAncestors_1 = require("./getOverflowAncestors");
const getParentNode_1 = require("./getParentNode");
const getViewportRect_1 = require("./getViewportRect");
const is_utils_1 = require("./is.utils");
const node_1 = require("./node");
const rectToClientRect_1 = require("./rectToClientRect");
/**
* Get the client inner rect (with borders)
*/
const getInnerBoundingClientRect = (element, strategy) => {
const clientRect = (0, getBoundingClientRect_1.getBoundingClientRect)(element, strategy === 'fixed');
const top = clientRect.top + element.clientTop;
const left = clientRect.left + element.clientLeft;
const width = element.clientWidth;
const height = element.clientHeight;
const x = left;
const y = top;
return {
width,
height,
x,
y,
};
};
exports.getInnerBoundingClientRect = getInnerBoundingClientRect;
const getClientRectFromClippingAncestor = (clippingAncestor, strategy) => {
let rect;
if (clippingAncestor === 'viewport') {
rect = (0, getViewportRect_1.getViewportRect)(strategy);
}
else if (clippingAncestor === 'document') {
rect = (0, getDocumentRect_1.getDocumentRect)(window.document.documentElement);
}
else if ((0, is_utils_1.isElement)(clippingAncestor)) {
rect = (0, exports.getInnerBoundingClientRect)(clippingAncestor, strategy);
}
else {
const mutableRect = { ...clippingAncestor };
if ((0, is_utils_1.isClientRectVisualViewportBased)()) {
mutableRect.x -= window.visualViewport?.offsetLeft || 0;
mutableRect.y -= window.visualViewport?.offsetTop || 0;
}
rect = mutableRect;
}
return (0, rectToClientRect_1.rectToClientRect)(rect);
};
exports.getClientRectFromClippingAncestor = getClientRectFromClippingAncestor;
const hasFixedPositionAncestor = (element, stopNode) => {
const parentNode = (0, getParentNode_1.getParentNode)(element);
if (parentNode === stopNode || !(0, is_utils_1.isElement)(parentNode) || (0, is_utils_1.isLastTraversableNode)(parentNode)) {
return false;
}
return (window.getComputedStyle(parentNode).position === 'fixed' ||
(0, exports.hasFixedPositionAncestor)(parentNode, stopNode));
};
exports.hasFixedPositionAncestor = hasFixedPositionAncestor;
/**
* A "clipping ancestor" is an `overflow` element with the characteristic of
* clipping (or hiding) child elements. This returns all clipping ancestors
* of the given element up the tree.
*/
const getClippingElementAncestors = (element) => {
let result = (0, getOverflowAncestors_1.getOverflowAncestors)(element).filter(el => (0, is_utils_1.isElement)(el) && (0, node_1.getNodeName)(el) !== 'body');
let currentContainingBlockComputedStyle = null;
const elementIsFixed = window.getComputedStyle(element).position === 'fixed';
let currentNode = elementIsFixed ? (0, getParentNode_1.getParentNode)(element) : element;
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
while ((0, is_utils_1.isElement)(currentNode) && !(0, is_utils_1.isLastTraversableNode)(currentNode)) {
const computedStyle = window.getComputedStyle(currentNode);
const currentNodeIsContaining = (0, is_utils_1.isContainingBlock)(currentNode);
if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
currentContainingBlockComputedStyle = null;
}
const shouldDropCurrentNode = elementIsFixed
? !currentNodeIsContaining && !currentContainingBlockComputedStyle
: (!currentNodeIsContaining &&
computedStyle.position === 'static' &&
!!currentContainingBlockComputedStyle &&
['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position)) ||
((0, is_utils_1.isOverflowElement)(currentNode) &&
!currentNodeIsContaining &&
(0, exports.hasFixedPositionAncestor)(element, currentNode));
if (shouldDropCurrentNode) {
// Drop non-containing blocks.
result = result.filter(ancestor => ancestor !== currentNode);
}
else {
// Record last containing block for next iteration.
currentContainingBlockComputedStyle = computedStyle;
}
currentNode = (0, getParentNode_1.getParentNode)(currentNode);
}
return result;
};
exports.getClippingElementAncestors = getClippingElementAncestors;
/**
* Gets the maximum area that the element is visible in due to any number of clipping ancestors.
* A "clipping ancestor" is an `overflow` element with the characteristic of
* clipping (or hiding) child elements. This returns all clipping ancestors
* of the given element up the tree.
*/
const getClippingRect = ({ element, boundary, rootBoundary, strategy, }) => {
const elementClippingAncestors = boundary === 'clippingAncestors' ? (0, exports.getClippingElementAncestors)(element) : [...boundary];
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
const firstClippingAncestor = clippingAncestors[0];
const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
const rect = (0, exports.getClientRectFromClippingAncestor)(clippingAncestor, strategy);
accRect.top = Math.max(rect.top, accRect.top);
accRect.right = Math.min(rect.right, accRect.right);
accRect.bottom = Math.min(rect.bottom, accRect.bottom);
accRect.left = Math.max(rect.left, accRect.left);
return accRect;
}, (0, exports.getClientRectFromClippingAncestor)(firstClippingAncestor, strategy));
return {
width: clippingRect.right - clippingRect.left,
height: clippingRect.bottom - clippingRect.top,
x: clippingRect.left,
y: clippingRect.top,
};
};
exports.getClippingRect = getClippingRect;
//# sourceMappingURL=getClippinRect.js.map