@vuesax-alpha/nightly
Version:
A Component Library for Vue 3
116 lines (113 loc) • 4.87 kB
JavaScript
import { concat } from 'lodash-unified';
import { createCoords, rectToClientRect, max, min } from '../../utils/index.mjs';
import { isHTMLElement, getDocumentElement, getParentNode, isLastTraversableNode, getComputedStyle, getOverflowAncestors, getNodeName, isContainingBlock, isOverflowElement } from '../../utils/dom.mjs';
import { getBoundingClientRect } from '../utils/get-bounding-client-rect.mjs';
import { getDocumentRect } from '../utils/get-document-rect.mjs';
import { getViewportRect } from '../utils/get-viewport-rect.mjs';
import { getVisualOffsets } from '../utils/get-visual-offsets.mjs';
import { getScale } from './get-scale.mjs';
import { isElement } from './is-element.mjs';
function getInnerBoundingClientRect(element, strategy) {
const clientRect = getBoundingClientRect(element, true, strategy === "fixed");
const top = clientRect.top + element.clientTop;
const left = clientRect.left + element.clientLeft;
const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
const width = element.clientWidth * scale.x;
const height = element.clientHeight * scale.y;
const x = left * scale.x;
const y = top * scale.y;
return {
width,
height,
x,
y
};
}
function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
let rect;
if (clippingAncestor === "viewport") {
rect = getViewportRect(element, strategy);
} else if (clippingAncestor === "document") {
rect = getDocumentRect(getDocumentElement(element));
} else if (isElement(clippingAncestor)) {
rect = getInnerBoundingClientRect(clippingAncestor, strategy);
} else {
const visualOffsets = getVisualOffsets(element);
rect = {
...clippingAncestor,
x: clippingAncestor.x - visualOffsets.x,
y: clippingAncestor.y - visualOffsets.y
};
}
return rectToClientRect(rect);
}
function hasFixedPositionAncestor(element, stopNode) {
const parentNode = getParentNode(element);
if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
return false;
}
return getComputedStyle(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode);
}
function getClippingElementAncestors(element, cache) {
const cachedResult = cache == null ? void 0 : cache.get(element);
if (cachedResult) {
return cachedResult;
}
let result = getOverflowAncestors(element, [], false).filter(
(el) => isElement(el) && getNodeName(el) !== "body"
);
let currentContainingBlockComputedStyle = null;
const elementIsFixed = getComputedStyle(element).position === "fixed";
let currentNode = elementIsFixed ? getParentNode(element) : element;
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
const computedStyle = getComputedStyle(currentNode);
const currentNodeIsContaining = isContainingBlock(currentNode);
if (!currentNodeIsContaining && computedStyle.position === "fixed") {
currentContainingBlockComputedStyle = null;
}
const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === "static" && !!currentContainingBlockComputedStyle && ["absolute", "fixed"].includes(
currentContainingBlockComputedStyle.position
) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
if (shouldDropCurrentNode) {
result = result.filter((ancestor) => ancestor !== currentNode);
} else {
currentContainingBlockComputedStyle = computedStyle;
}
currentNode = getParentNode(currentNode);
}
cache == null ? void 0 : cache.set(element, result);
return result;
}
function getClippingRect({
element,
boundary,
rootBoundary,
strategy
}) {
const elementClippingAncestors = boundary === "clippingAncestors" ? getClippingElementAncestors(element, this._c) : concat([], boundary);
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
const firstClippingAncestor = clippingAncestors[0];
const clippingRect = clippingAncestors.reduce(
(accRect, clippingAncestor) => {
const rect = getClientRectFromClippingAncestor(
element,
clippingAncestor,
strategy
);
accRect.top = max(rect.top, accRect.top);
accRect.right = min(rect.right, accRect.right);
accRect.bottom = min(rect.bottom, accRect.bottom);
accRect.left = max(rect.left, accRect.left);
return accRect;
},
getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy)
);
return {
width: clippingRect.right - clippingRect.left,
height: clippingRect.bottom - clippingRect.top,
x: clippingRect.left,
y: clippingRect.top
};
}
export { getClippingRect };
//# sourceMappingURL=get-clipping-rect.mjs.map