carbon-components-angular
Version:
Next generation components
81 lines • 13 kB
JavaScript
import { map } from "rxjs/operators";
import { fromEvent, merge } from "rxjs";
/**
* Checks if a given element is scrollable.
* If the element has an overflow set as part of its computed style it can scroll.
* @param element the element to check scrollability
*/
export const isScrollableElement = (element) => {
const computedStyle = getComputedStyle(element);
return (computedStyle.overflow === "auto" ||
computedStyle.overflow === "scroll" ||
computedStyle["overflow-y"] === "auto" ||
computedStyle["overflow-y"] === "scroll" ||
computedStyle["overflow-x"] === "auto" ||
computedStyle["overflow-x"] === "scroll");
};
/**
* Checks if an element is visible within a container
* @param element the element to check
* @param container the container to check
*/
export const isVisibleInContainer = (element, container) => {
const elementRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
// If there exists `height: 100%` on the `html` or `body` tag of an application,
// it causes the calculation to return true if you need to scroll before the element is seen.
// In that case we calculate its visibility based on the window viewport.
if (container.tagName === "BODY" || container.tagName === "HTML") {
// This checks if element is within the top, bottom, left and right of viewport, ie. if the element is visible in
// the screen. This also takes into account partial visibility of an element.
const isAboveViewport = elementRect.top < 0 && (elementRect.top + element.clientHeight) < 0;
const isLeftOfViewport = elementRect.left < 0;
const isBelowViewport = (elementRect.bottom - element.clientHeight) > (window.innerHeight || document.documentElement.clientHeight);
const isRightOfViewport = elementRect.right > (window.innerWidth || document.documentElement.clientWidth);
const isVisibleInViewport = !(isAboveViewport || isBelowViewport || isLeftOfViewport || isRightOfViewport);
return isVisibleInViewport;
}
return (
// This also accounts for partial visibility. It will still return true if the element is partially visible inside the container.
(elementRect.bottom - element.clientHeight) <= (containerRect.bottom + (container.offsetHeight - container.clientHeight) / 2) &&
elementRect.top >= (-element.clientHeight));
};
export const getScrollableParents = (node) => {
const elements = [document.body];
while (node.parentElement && node !== document.body) {
if (isScrollableElement(node)) {
elements.push(node);
}
node = node.parentElement;
}
return elements;
};
export const hasScrollableParents = (node) => {
while (node.parentElement && node !== document.body) {
if (isScrollableElement(node)) {
return true;
}
node = node.parentElement;
}
return false;
};
/**
* Returns an observable that emits whenever any scrollable parent element scrolls
*
* @param node root element to start finding scrolling parents from
*/
export const scrollableParentsObservable = (node) => {
const windowScroll = fromEvent(window, "scroll", { passive: true }).pipe(map(event =>
// update the event target to be something useful. In this case `body` is a sensible replacement
Object.assign({}, event, { target: document.body })));
let observables = [windowScroll];
// walk the parents and subscribe to all the scroll events we can
while (node.parentElement && node !== document.body) {
if (isScrollableElement(node)) {
observables.push(fromEvent(node, "scroll", { passive: true }));
}
node = node.parentElement;
}
return merge(...observables);
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL3Njcm9sbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckMsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFHcEQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLENBQUMsT0FBb0IsRUFBRSxFQUFFO0lBQzNELE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2hELE9BQU8sQ0FDTixhQUFhLENBQUMsUUFBUSxLQUFLLE1BQU07UUFDakMsYUFBYSxDQUFDLFFBQVEsS0FBSyxRQUFRO1FBQ25DLGFBQWEsQ0FBQyxZQUFZLENBQUMsS0FBSyxNQUFNO1FBQ3RDLGFBQWEsQ0FBQyxZQUFZLENBQUMsS0FBSyxRQUFRO1FBQ3hDLGFBQWEsQ0FBQyxZQUFZLENBQUMsS0FBSyxNQUFNO1FBQ3RDLGFBQWEsQ0FBQyxZQUFZLENBQUMsS0FBSyxRQUFRLENBQ3hDLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxPQUFvQixFQUFFLFNBQXNCLEVBQUUsRUFBRTtJQUNwRixNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUNwRCxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUN4RCxnRkFBZ0Y7SUFDaEYsNkZBQTZGO0lBQzdGLHlFQUF5RTtJQUN6RSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEtBQUssTUFBTSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEtBQUssTUFBTSxFQUFFO1FBQ2pFLGlIQUFpSDtRQUNqSCw2RUFBNkU7UUFDN0UsTUFBTSxlQUFlLEdBQUcsV0FBVyxD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Q0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztTQUMvRDtRQUNELElBQUksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO0tBQzFCO0lBRUQsT0FBTyxLQUFLLENBQUMsR0FBRyxXQUFXLENBQUMsQ0FBQztBQUM5QixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBtYXAgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcbmltcG9ydCB7IGZyb21FdmVudCwgbWVyZ2UsIE9ic2VydmFibGUgfSBmcm9tIFwicnhqc1wiO1xuXG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgZ2l2ZW4gZWxlbWVudCBpcyBzY3JvbGxhYmxlLlxuICogSWYgdGhlIGVsZW1lbnQgaGFzIGFuIG92ZXJmbG93IHNldCBhcyBwYXJ0IG9mIGl0cyBjb21wdXRlZCBzdHlsZSBpdCBjYW4gc2Nyb2xsLlxuICogQHBhcmFtIGVsZW1lbnQgdGhlIGVsZW1lbnQgdG8gY2hlY2sgc2Nyb2xsYWJpbGl0eVxuICovXG5leHBvcnQgY29uc3QgaXNTY3JvbGxhYmxlRWxlbWVudCA9IChlbGVtZW50OiBIVE1MRWxlbWVudCkgPT4ge1xuXHRjb25zdCBjb21wdXRlZFN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcblx0cmV0dXJuIChcblx0XHRjb21wdXRlZFN0eWxlLm92ZXJmbG93ID09PSBcImF1dG9cIiB8fFxuXHRcdGNvbXB1dGVkU3R5bGUub3ZlcmZsb3cgPT09IFwic2Nyb2xsXCIgfHxcblx0XHRjb21wdXRlZFN0eWxlW1wib3ZlcmZsb3cteVwiXSA9PT0gXCJhdXRvXCIgfHxcblx0XHRjb21wdXRlZFN0eWxlW1wib3ZlcmZsb3cteVwiXSA9PT0gXCJzY3JvbGxcIiB8fFxuXHRcdGNvbXB1dGVkU3R5bGVbXCJvdmVyZmxvdy14XCJdID09PSBcImF1dG9cIiB8fFxuXHRcdGNvbXB1dGVkU3R5bGVbXCJvdmVyZmxvdy14XCJdID09PSBcInNjcm9sbFwiXG5cdCk7XG59O1xuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBlbGVtZW50IGlzIHZpc2libGUgd2l0aGluIGEgY29udGFpbmVyXG4gKiBAcGFyYW0gZWxlbWVudCB0aGUgZWxlbWVudCB0byBjaGVja1xuICogQHBhcmFtIGNvbnRhaW5lciB0aGUgY29udGFpbmVyIHRvIGNoZWNrXG4gKi9cbmV4cG9ydCBjb25zdCBpc1Zpc2libGVJbkNvbnRhaW5lciA9IChlbGVtZW50OiBIVE1MRWxlbWVudCwgY29udGFpbmVyOiBIVE1MRWxlbWVudCkgPT4ge1xuXHRjb25zdCBlbGVtZW50UmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdGNvbnN0IGNvbnRhaW5lclJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdC8vIElmIHRoZXJlIGV4aXN0cyBgaGVpZ2h0OiAxMDAlYCBvbiB0aGUgYGh0bWxgIG9yIGBib2R5YCB0YWcgb2YgYW4gYXBwbGljYXRpb24sXG5cdC8vIGl0IGNhdXNlcyB0aGUgY2FsY3VsYXRpb24gdG8gcmV0dXJuIHRydWUgaWYgeW91IG5lZWQgdG8gc2Nyb2xsIGJlZm9yZSB0aGUgZWxlbWVudCBpcyBzZWVuLlxuXHQvLyBJbiB0aGF0IGNhc2Ugd2UgY2FsY3VsYXRlIGl0cyB2aXNpYmlsaXR5IGJhc2VkIG9uIHRoZSB3aW5kb3cgdmlld3BvcnQuXG5cdGlmIChjb250YWluZXIudGFnTmFtZSA9PT0gXCJCT0RZXCIgfHwgY29udGFpbmVyLnRhZ05hbWUgPT09IFwiSFRNTFwiKSB7XG5cdFx0Ly8gVGhpcyBjaGVja3MgaWYgZWxlbWVudCBpcyB3aXRoaW4gdGhlIHRvcCwgYm90dG9tLCBsZWZ0IGFuZCByaWdodCBvZiB2aWV3cG9ydCwgaWUuIGlmIHRoZSBlbGVtZW50IGlzIHZpc2libGUgaW5cblx0XHQvLyB0aGUgc2NyZWVuLiBUaGlzIGFsc28gdGFrZXMgaW50byBhY2NvdW50IHBhcnRpYWwgdmlzaWJpbGl0eSBvZiBhbiBlbGVtZW50LlxuXHRcdGNvbnN0IGlzQWJvdmVWaWV3cG9ydCA9IGVsZW1lbnRSZWN0LnRvcCA8IDAgJiYgKGVsZW1lbnRSZWN0LnRvcCArIGVsZW1lbnQuY2xpZW50SGVpZ2h0KSA8IDA7XG5cdFx0Y29uc3QgaXNMZWZ0T2ZWaWV3cG9ydCA9IGVsZW1lbnRSZWN0LmxlZnQgPCAwO1xuXHRcdGNvbnN0IGlzQmVsb3dWaWV3cG9ydCA9XG5cdFx0XHQoZWxlbWVudFJlY3QuYm90dG9tIC0gZWxlbWVudC5jbGllbnRIZWlnaHQpID4gKHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KTtcblx0XHRjb25zdCBpc1JpZ2h0T2ZWaWV3cG9ydCA9IGVsZW1lbnRSZWN0LnJpZ2h0ID4gKHdpbmRvdy5pbm5lcldpZHRoIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCk7XG5cblx0XHRjb25zdCBpc1Zpc2libGVJblZpZXdwb3J0ID0gIShpc0Fib3ZlVmlld3BvcnQgfHwgaXNCZWxvd1ZpZXdwb3J0IHx8IGlzTGVmdE9mVmlld3BvcnQgfHwgaXNSaWdodE9mVmlld3BvcnQpO1xuXG5cdFx0cmV0dXJuIGlzVmlzaWJsZUluVmlld3BvcnQ7XG5cdH1cblx0cmV0dXJuIChcblx0XHQvLyBUaGlzIGFsc28gYWNjb3VudHMgZm9yIHBhcnRpYWwgdmlzaWJpbGl0eS4gSXQgd2lsbCBzdGlsbCByZXR1cm4gdHJ1ZSBpZiB0aGUgZWxlbWVudCBpcyBwYXJ0aWFsbHkgdmlzaWJsZSBpbnNpZGUgdGhlIGNvbnRhaW5lci5cblx0XHQoZWxlbWVudFJlY3QuYm90dG9tIC0gZWxlbWVudC5jbGllbnRIZWlnaHQpIDw9IChjb250YWluZXJSZWN0LmJvdHRvbSArIChjb250YWluZXIub2Zmc2V0SGVpZ2h0IC0gY29udGFpbmVyLmNsaWVudEhlaWdodCkgLyAyKSAmJlxuXHRcdGVsZW1lbnRSZWN0LnRvcCA+PSAoLSBlbGVtZW50LmNsaWVudEhlaWdodClcblx0KTtcbn07XG5cblxuZXhwb3J0IGNvbnN0IGdldFNjcm9sbGFibGVQYXJlbnRzID0gKG5vZGU6IEhUTUxFbGVtZW50KSA9PiB7XG5cdGNvbnN0IGVsZW1lbnRzID0gW2RvY3VtZW50LmJvZHldO1xuXHR3aGlsZSAobm9kZS5wYXJlbnRFbGVtZW50ICYmIG5vZGUgIT09IGRvY3VtZW50LmJvZHkpIHtcblx0XHRpZiAoaXNTY3JvbGxhYmxlRWxlbWVudChub2RlKSkge1xuXHRcdFx0ZWxlbWVudHMucHVzaChub2RlKTtcblx0XHR9XG5cdFx0bm9kZSA9IG5vZGUucGFyZW50RWxlbWVudDtcblx0fVxuXHRyZXR1cm4gZWxlbWVudHM7XG59O1xuXG5leHBvcnQgY29uc3QgaGFzU2Nyb2xsYWJsZVBhcmVudHMgPSAobm9kZTogSFRNTEVsZW1lbnQpID0+IHtcblx0d2hpbGUgKG5vZGUucGFyZW50RWxlbWVudCAmJiBub2RlICE9PSBkb2N1bWVudC5ib2R5KSB7XG5cdFx0aWYgKGlzU2Nyb2xsYWJsZUVsZW1lbnQobm9kZSkpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRub2RlID0gbm9kZS5wYXJlbnRFbGVtZW50O1xuXHR9XG5cdHJldHVybiBmYWxzZTtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhbiBvYnNlcnZhYmxlIHRoYXQgZW1pdHMgd2hlbmV2ZXIgYW55IHNjcm9sbGFibGUgcGFyZW50IGVsZW1lbnQgc2Nyb2xsc1xuICpcbiAqIEBwYXJhbSBub2RlIHJvb3QgZWxlbWVudCB0byBzdGFydCBmaW5kaW5nIHNjcm9sbGluZyBwYXJlbnRzIGZyb21cbiAqL1xuZXhwb3J0IGNvbnN0IHNjcm9sbGFibGVQYXJlbnRzT2JzZXJ2YWJsZSA9IChub2RlOiBIVE1MRWxlbWVudCk6IE9ic2VydmFibGU8RXZlbnQ+ID0+IHtcblx0Y29uc3Qgd2luZG93U2Nyb2xsID0gZnJvbUV2ZW50KHdpbmRvdywgXCJzY3JvbGxcIiwgeyBwYXNzaXZlOiB0cnVlIH0pLnBpcGUobWFwKGV2ZW50ID0+IChcblx0XHQvLyB1cGRhdGUgdGhlIGV2ZW50IHRhcmdldCB0byBiZSBzb21ldGhpbmcgdXNlZnVsLiBJbiB0aGlzIGNhc2UgYGJvZHlgIGlzIGEgc2Vuc2libGUgcmVwbGFjZW1lbnRcblx0XHRPYmplY3QuYXNzaWduKHt9LCBldmVudCwgeyB0YXJnZXQ6IGRvY3VtZW50LmJvZHkgfSkgYXMgRXZlbnRcblx0KSkpO1xuXHRsZXQgb2JzZXJ2YWJsZXMgPSBbd2luZG93U2Nyb2xsXTtcblx0Ly8gd2FsayB0aGUgcGFyZW50cyBhbmQgc3Vic2NyaWJlIHRvIGFsbCB0aGUgc2Nyb2xsIGV2ZW50cyB3ZSBjYW5cblx0d2hpbGUgKG5vZGUucGFyZW50RWxlbWVudCAmJiBub2RlICE9PSBkb2N1bWVudC5ib2R5KSB7XG5cdFx0aWYgKGlzU2Nyb2xsYWJsZUVsZW1lbnQobm9kZSkpIHtcblx0XHRcdG9ic2VydmFibGVzLnB1c2goZnJvbUV2ZW50KG5vZGUsIFwic2Nyb2xsXCIsIHsgcGFzc2l2ZTogdHJ1ZSB9KSk7XG5cdFx0fVxuXHRcdG5vZGUgPSBub2RlLnBhcmVudEVsZW1lbnQ7XG5cdH1cblxuXHRyZXR1cm4gbWVyZ2UoLi4ub2JzZXJ2YWJsZXMpO1xufTtcbiJdfQ==