UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

931 lines 51.1 kB
/** @component event-overlay */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import omit from 'lodash/omit';
import { FocusScope } from '@react-aria/focus';
var defaultDims = {
    offsetTop: 0,
    bottom: 0,
    center: 0,
    height: 0,
    left: 0,
    middle: 0,
    right: 0,
    top: 0,
    width: 0,
};
function eventPath(evt) {
    var _a;
    var path = (evt.composedPath && evt.composedPath()) || evt.path, target = evt.target;
    var isPathInShadowRoot = false;
    var pathElementsInShadowRootToDelete = 0;
    // check if any of the elements in the next 3 elements in the path are a shadow root
    // this is a work around to make the deprecated EventOverlay to work with the Shadow DOM
    if ((path === null || path === void 0 ? void 0 : path.length) > 1) {
        for (var i = 1; i < 4; i++) {
            if (((_a = path[i]) === null || _a === void 0 ? void 0 : _a.toString()) === '[object ShadowRoot]') {
                isPathInShadowRoot = true;
                pathElementsInShadowRootToDelete = i + 1;
                break;
            }
        }
    }
    if (isPathInShadowRoot) {
        // if path is in shadowroot, then we need to get rid of the first 2 elements in the path
        path = path.slice(pathElementsInShadowRootToDelete);
    }
    if (path != null) {
        // Safari doesn't include Window, and it should.
        path = path.indexOf(window) < 0 ? path.concat([window]) : path;
        return path;
    }
    if (target === window) {
        return [window];
    }
    function getParents(node, memo) {
        memo = memo || [];
        var parentNode = node !== undefined ? node.parentNode : false;
        if (!parentNode) {
            return memo;
        }
        else {
            return getParents(parentNode, memo.concat([parentNode]));
        }
    }
    return [target].concat(getParents(target)).concat([window]);
}
/**
 * @deprecated - Components in the legacy folder (/src/legacy) are deprecated. Please use a component from the components folder (/src/components) instead. Legacy components may not follow accessibility standards.
 **/
var EventOverlay = /** @class */ (function (_super) {
    __extends(EventOverlay, _super);
    function EventOverlay() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            absoluteParent: null,
            containerParent: null,
            isOpen: false,
            scrollParent: null,
            transformParent: null,
            visibleDirection: _this.props.direction,
        };
        _this.componentDidMount = function () {
            _this.props.isOpen && _this.forceUpdate();
            _this.addHandlers();
        };
        _this.componentDidUpdate = function (prevProps, prevState) {
            var direction = _this.props.direction;
            var isOpen = _this.state.isOpen;
            if ((isOpen && prevState.isOpen !== isOpen) || prevProps.direction !== direction) {
                return _this.forceUpdate(function () { return _this.isVisible(); });
            }
            else if (!isOpen && prevState.isOpen !== isOpen) {
                _this.focusOnAnchorNode();
            }
        };
        _this.componentWillUnmount = function () {
            _this.removeHandlers();
        };
        _this.addHandlers = function () {
            var _a = _this.props, absoluteParentID = _a.absoluteParentID, allowClickAway = _a.allowClickAway, boundingParentID = _a.boundingParentID, checkOverflow = _a.checkOverflow, closeOnClick = _a.closeOnClick, isContained = _a.isContained, scrollParentID = _a.scrollParentID, transformParentID = _a.transformParentID;
            _this.handleResize = _this.isVisible;
            _this.handleScroll = _this.isVisible;
            var element = ReactDOM.findDOMNode(_this.container);
            var elementParent = element && element.parentElement;
            var elementParents = elementParent && _this.findParents(elementParent);
            var scrollParent;
            if (allowClickAway) {
                document.addEventListener('click', _this.handleAllowClickAway, true);
                document.addEventListener('keydown', _this.handleKeyDown, false);
            }
            closeOnClick && document.addEventListener('click', _this.handleCloseOnClick, false);
            window.addEventListener('resize', _this.handleResize, false);
            document.addEventListener('scroll', _this.handleScroll, false);
            if (scrollParentID) {
                scrollParent = document.getElementById(scrollParentID);
                scrollParent && scrollParent.addEventListener('scroll', _this.handleScroll, false);
            }
            if (checkOverflow) {
                scrollParent =
                    !scrollParent &&
                        elementParents &&
                        _this.findScrollParent(elementParents, ['overflow', 'overflow-y', 'overflow-x']);
                scrollParent && scrollParent.addEventListener('scroll', _this.handleScroll, false);
            }
            var transformParent = transformParentID
                ? document.getElementById(transformParentID)
                : elementParents && _this.findTransformParent(elementParents, ['transform'], 1);
            var absoluteParent = absoluteParentID
                ? document.getElementById(absoluteParentID)
                : elementParents && _this.findAbsoluteParent(elementParents, ['position'], 1);
            var containerParent = (isContained && document.getElementById(boundingParentID)) || scrollParent;
            _this.observer = new MutationObserver(_this.isVisible);
            _this.observer.observe(document.body, {
                attributes: false,
                characterData: false,
                childList: true,
                subtree: true,
                attributeOldValue: false,
                characterDataOldValue: false,
            });
            _this.setState({
                absoluteParent: absoluteParent,
                containerParent: containerParent,
                scrollParent: scrollParent,
                transformParent: transformParent,
            }, function () { return _this.isVisible(); });
        };
        _this.findOverflow = function (node, searchProps) {
            return searchProps.reduce(function (agg, prop) {
                var overflowElement = window.getComputedStyle(ReactDOM.findDOMNode(node))[prop];
                return !overflowElement || agg.includes(overflowElement) ? agg : (agg += overflowElement);
            }, '');
        };
        _this.findParents = function (ele, tempParentArr) {
            if (tempParentArr === void 0) { tempParentArr = []; }
            return !ele.parentElement
                ? tempParentArr
                : _this.findParents(ele.parentElement, tempParentArr.concat(ele));
        };
        _this.findAbsoluteParent = function (elementParents, searchProps, startIndex) {
            var absoluteElement;
            var idx = startIndex;
            while (!absoluteElement && elementParents[idx]) {
                var currentAbsoluteElement = _this.findOverflow(elementParents[idx], searchProps);
                if (/(absolute)/.test(currentAbsoluteElement)) {
                    return (absoluteElement = elementParents[idx]);
                }
                idx++;
            }
            return absoluteElement ? absoluteElement : null;
        };
        _this.findScrollParent = function (elementParents, searchProps) {
            var overflowElement = null;
            var idx = 1;
            while (!overflowElement && elementParents[idx]) {
                var currentOverflowElement = _this.findOverflow(elementParents[idx], searchProps);
                if (/(auto|scroll|hidden)/.test(currentOverflowElement)) {
                    return (overflowElement = elementParents[idx]);
                }
                idx++;
            }
            return overflowElement ? overflowElement : null;
        };
        _this.findTransformParent = function (elementParents, searchProps, startIndex) {
            var transformElement = null;
            var idx = startIndex;
            while (!transformElement && elementParents[idx]) {
                var potentialTransformElement = _this.findOverflow(elementParents[idx], ['will-change']);
                var currentTransformElement = _this.findOverflow(elementParents[idx], searchProps);
                if (/(transform)/.test(potentialTransformElement) || currentTransformElement !== 'none') {
                    return (transformElement = elementParents[idx]);
                }
                idx++;
            }
            return transformElement ? transformElement : null;
        };
        _this.focusOnAnchorNode = function () {
            var anchorNode = _this.props.anchorNode;
            if (anchorNode) {
                var domAnchorNode = (anchorNode.props ? anchorNode.props.onClick : false) && ReactDOM.findDOMNode(anchorNode);
                if (domAnchorNode) {
                    domAnchorNode.focus();
                }
                else if (anchorNode.focus) {
                    // handle fallback for MRv2 trigger elements (functional components)
                    anchorNode.focus();
                }
            }
        };
        _this.getAnchorPosition = function (node) {
            var transformParent = _this.state.transformParent;
            var rect = node.getBoundingClientRect();
            var transformParentDims = transformParent && _this.getElementPosition(transformParent);
            var parentRect = transformParentDims || defaultDims;
            var anchorPosition = {
                top: rect.top - parentRect.top,
                left: rect.left - parentRect.left,
                width: node.offsetWidth,
                height: node.offsetHeight,
            };
            anchorPosition.right =
                (rect.right || anchorPosition.left + anchorPosition.width) - parentRect.left;
            anchorPosition.bottom =
                (rect.bottom || anchorPosition.top + anchorPosition.height) - parentRect.top;
            anchorPosition.middle = anchorPosition.left + (anchorPosition.right - anchorPosition.left) / 2;
            anchorPosition.center = anchorPosition.top + (anchorPosition.bottom - anchorPosition.top) / 2;
            return anchorPosition;
        };
        _this.getAbsoluteAnchorPosition = function (node, absoluteParentDims) {
            var scrollParent = _this.state.scrollParent;
            var rect = node.getBoundingClientRect();
            var parentRect = absoluteParentDims;
            var scrollAdjust = (scrollParent && scrollParent.scrollTop) || 0;
            var anchorPosition = {
                top: absoluteParentDims.offsetTop
                    ? absoluteParentDims.offsetTop + node.offsetTop - scrollAdjust
                    : rect.top - parentRect.top,
                left: absoluteParentDims.offsetLeft
                    ? absoluteParentDims.offsetLeft - node.offsetLeft
                    : rect.left - parentRect.left,
                width: node.offsetWidth,
                height: node.offsetHeight,
            };
            anchorPosition.right =
                (rect.right || anchorPosition.left + anchorPosition.width) - parentRect.left;
            anchorPosition.bottom = anchorPosition.top + anchorPosition.height;
            anchorPosition.middle = anchorPosition.left + (anchorPosition.right - anchorPosition.left) / 2;
            anchorPosition.center = anchorPosition.top + (anchorPosition.bottom - anchorPosition.top) / 2;
            return anchorPosition;
        };
        _this.getElementPosition = function (element) {
            var elementRect = element.getBoundingClientRect();
            return {
                offsetTop: element.offsetTop,
                offsetLeft: element.offsetLeft,
                bottom: elementRect.bottom,
                top: elementRect.top,
                left: elementRect.left,
                height: elementRect.height,
                width: elementRect.width,
                hasAbsParent: element.offsetTop !== elementRect.top || element.offsetLeft !== elementRect.left,
            };
        };
        _this.getOrigin = function () {
            var side = _this.state.visibleDirection.split('-')[0];
            var alignment = _this.props.direction.split('-')[1];
            var origin = {
                anchor: {},
                target: {},
            };
            if (side === 'top' || side === 'bottom') {
                origin.anchor.vertical = side;
                origin.anchor.horizontal = alignment === 'center' ? 'middle' : alignment;
                origin.target.vertical = side === 'top' ? 'bottom' : 'top';
                origin.target.horizontal = alignment === 'center' ? 'middle' : alignment;
            }
            if (side === 'left' || side === 'right') {
                origin.anchor.vertical = alignment;
                origin.anchor.horizontal = side;
                origin.target.vertical = alignment;
                origin.target.horizontal = side === 'left' ? 'right' : 'left';
            }
            return origin;
        };
        _this.getTargetPosition = function (targetNode) {
            return {
                top: 0,
                center: targetNode.offsetHeight / 2,
                bottom: targetNode.offsetHeight,
                left: 0,
                middle: targetNode.offsetWidth / 2,
                right: targetNode.offsetWidth,
            };
        };
        _this.handleAllowClickAway = function (e) {
            if (!_this.props.isOpen)
                return;
            var eventTarget = eventPath(e)[0];
            var anchorNode = ReactDOM.findDOMNode(_this.props.anchorNode);
            return (_this.container &&
                !anchorNode.contains(eventTarget) &&
                !ReactDOM.findDOMNode(_this.container).contains(eventTarget) &&
                _this.handleClickAway(e));
        };
        _this.handleClickAway = function (e) {
            var close = _this.props.close;
            _this.focusOnAnchorNode();
            close && close(e);
        };
        _this.handleCloseOnClick = function (e) {
            if (!_this.props.isOpen)
                return;
            var eventTarget = eventPath(e)[0];
            var closeOnClick = _this.props.closeOnClick;
            return (closeOnClick &&
                _this.container &&
                ReactDOM.findDOMNode(_this.container).contains(eventTarget) &&
                _this.handleClickAway(e));
        };
        _this.handleKeyDown = function (e) {
            var _a = _this.props, isOpen = _a.isOpen, disableCloseOnEnterOrSpaceKey = _a.disableCloseOnEnterOrSpaceKey;
            if (!isOpen)
                return;
            if (e.keyCode === 27)
                return _this.handleClickAway(e);
            if (!disableCloseOnEnterOrSpaceKey ||
                (disableCloseOnEnterOrSpaceKey && e.which !== 13 && e.which !== 32)) {
                var eventTarget = eventPath(e)[0];
                var anchorNode = ReactDOM.findDOMNode(_this.props.anchorNode);
                return (_this.container &&
                    anchorNode &&
                    !anchorNode.contains(eventTarget) &&
                    !ReactDOM.findDOMNode(_this.container).contains(eventTarget) &&
                    _this.handleClickAway(e));
            }
        };
        _this.isVisible = function () {
            var _a = _this.props, anchorNode = _a.anchorNode, direction = _a.direction, isOpen = _a.isOpen, isDynamic = _a.isDynamic;
            if (!isOpen)
                return;
            if (!isDynamic)
                return _this.setPlacement();
            var anchorElement = ReactDOM.findDOMNode(anchorNode);
            var element = ReactDOM.findDOMNode(_this.container);
            var side = direction.split('-')[0];
            var alignment = direction.split('-')[1];
            var anchorDims = anchorElement && anchorElement.getBoundingClientRect();
            var elementBoundingRect = element.getBoundingClientRect();
            var elementParent = element.parentElement;
            ['top', 'bottom'].includes(side)
                ? _this.setVerticalClass(alignment, anchorDims, elementBoundingRect, elementParent)
                : _this.setHorizontalClass(alignment, anchorDims, elementBoundingRect, elementParent);
        };
        _this.removeHandlers = function () {
            var scrollParent = _this.state.scrollParent;
            document.removeEventListener('click', _this.handleAllowClickAway, true);
            document.removeEventListener('click', _this.handleCloseOnClick, false);
            document.removeEventListener('keydown', _this.handleKeyDown, false);
            window.removeEventListener('resize', _this.handleResize, false);
            document.removeEventListener('scroll', _this.handleScroll, false);
            scrollParent && scrollParent.removeEventListener('scroll', _this.handleScroll, false);
            _this.observer && _this.observer.disconnect() && _this.observer.takeRecords();
        };
        _this.setArrowPlacement = function (anchor, container) {
            var arrow = _this.arrow;
            var targetOffset = _this.props.targetOffset;
            var visibleDirection = _this.state.visibleDirection;
            var side = visibleDirection.split('-')[0];
            var verticalOffset = targetOffset.vertical || 0;
            var horizontalOffset = targetOffset.horizontal || 0;
            var isAnchorWider = anchor.width > container.right;
            var isAnchorTaller = anchor.height > container.bottom;
            var arrowLeft = isAnchorWider && !visibleDirection.includes('center')
                ? visibleDirection.includes('left')
                    ? container.middle + anchor.left
                    : anchor.right - container.middle
                : anchor.middle;
            var arrowTop = isAnchorTaller && !visibleDirection.includes('center')
                ? visibleDirection.includes('top')
                    ? container.center + anchor.top
                    : anchor.bottom - container.center
                : anchor.center;
            switch (side) {
                case 'top':
                    arrow.style.left = "".concat(arrowLeft, "px");
                    arrow.style.top = "".concat(anchor.top - verticalOffset, "px");
                    break;
                case 'bottom':
                    arrow.style.left = "".concat(arrowLeft, "px");
                    arrow.style.top = "".concat(anchor.bottom + verticalOffset, "px");
                    break;
                case 'left':
                    arrow.style.left = "".concat(anchor.left - horizontalOffset, "px");
                    arrow.style.top = "".concat(arrowTop, "px");
                    break;
                case 'right':
                    arrow.style.left = "".concat(anchor.right + horizontalOffset, "px");
                    arrow.style.top = "".concat(arrowTop, "px");
                    break;
            }
        };
        _this.setBoundingBox = function (side, targetNode, anchorPosition) {
            var _a = _this.props, checkOverflow = _a.checkOverflow, isContained = _a.isContained, maxHeight = _a.maxHeight, maxWidth = _a.maxWidth, showArrow = _a.showArrow, targetOffset = _a.targetOffset;
            var _b = _this.state, absoluteParent = _b.absoluteParent, scrollParent = _b.scrollParent, transformParent = _b.transformParent;
            var arrowDims = showArrow && ReactDOM.findDOMNode(_this.arrow).getBoundingClientRect();
            var checkVertical = isContained === 'vertical';
            var checkHorizontal = isContained === 'horizontal';
            var element = ReactDOM.findDOMNode(_this.container);
            var documentScrollTop = document.documentElement.scrollTop;
            var documentBottom = document.documentElement.scrollHeight;
            var windowBottom = window.pageXOffset + window.innerHeight;
            var documentRight = Math.max(document.documentElement.offsetWidth, document.documentElement.clientWidth);
            var arrowHeight = (arrowDims && arrowDims.height) || 0;
            var arrowWidth = (arrowDims && arrowDims.width) || 0;
            var offsetHeight = targetOffset.vertical || 0;
            var offsetWidth = targetOffset.horizontal || 0;
            var elementDims = element.getBoundingClientRect();
            var elementVerticalHeight = elementDims.height + offsetHeight;
            var elementVerticalWidth = elementDims.width + offsetWidth;
            var getAvailableTopSpace = function (top) {
                return top + anchorPosition.top - (_this.elementHeight + arrowHeight);
            };
            var scrollParentDimsv2 = _this.setBoundingContainer(scrollParent);
            var scrollParentDims = scrollParent ? scrollParent.getBoundingClientRect() : defaultDims;
            var absoluteParentDims = absoluteParent && _this.getElementPosition(absoluteParent);
            var transformParentDims = transformParent && _this.getElementPosition(transformParent);
            var scrollParentScrollTop = (scrollParent && scrollParent.offsetTop) || 0;
            if (targetNode && targetNode.style && !targetNode.style.bottom && elementVerticalHeight) {
                _this.elementHeight = elementVerticalHeight;
                _this.elementBottom = elementDims.bottom;
            }
            if (targetNode && targetNode.style && !targetNode.style.right && elementVerticalWidth) {
                _this.elementWidth = elementVerticalWidth;
                _this.elementLeft = elementDims.left;
                _this.elementRight = elementDims.right;
            }
            switch (side) {
                case 'top':
                    if (!scrollParent && !transformParentDims) {
                        if (!checkHorizontal) {
                            targetNode.style.bottom = "".concat(windowBottom - anchorPosition.top + arrowHeight + offsetHeight, "px");
                            if (getAvailableTopSpace(documentScrollTop) < 0) {
                                targetNode.style.top = "".concat(arrowHeight - documentScrollTop, "px");
                            }
                        }
                        if (!checkVertical) {
                            if (elementDims.right > documentRight || _this.elementWidth > documentRight) {
                                targetNode.style.right = '0px';
                                if (_this.elementWidth < documentRight) {
                                    targetNode.style.left = "".concat(documentRight - _this.elementWidth, "px");
                                }
                            }
                            if (_this.elementLeft < 0) {
                                targetNode.style.left = '0px';
                            }
                        }
                    }
                    else {
                        if (transformParentDims) {
                            targetNode.style.bottom = "".concat(transformParentDims.height - anchorPosition.top + arrowHeight + offsetHeight, "px");
                            if (anchorPosition.top - scrollParentScrollTop - _this.elementHeight - arrowHeight < 0) {
                                targetNode.style.top = "".concat(scrollParentScrollTop + arrowHeight, "px");
                                targetNode.style.maxHeight = "".concat(maxHeight || transformParentDims.height, "px");
                            }
                            if (!checkVertical) {
                                if (_this.elementWidth > transformParentDims.width ||
                                    _this.elementRight > transformParentDims.right) {
                                    targetNode.style.right = "".concat(0, "px");
                                    if (_this.elementWidth > transformParentDims.width) {
                                        targetNode.style.left = "0px";
                                    }
                                    else {
                                        targetNode.style.left = "".concat(_this.elementWidth, "px");
                                    }
                                }
                                if (_this.elementLeft < transformParentDims.left) {
                                    targetNode.style.left = "".concat(0, "px");
                                }
                            }
                            if (arrowDims &&
                                (arrowDims.top - (scrollParent ? scrollParentDims.top : transformParentDims.top) <
                                    0 ||
                                    arrowDims.bottom + 1 >
                                        (scrollParent ? scrollParentDims.bottom : transformParentDims.bottom))) {
                                _this.arrow.style.visibility = 'hidden';
                            }
                            else if (arrowDims) {
                                _this.arrow.style.visibility = 'visible';
                            }
                        }
                        else {
                            targetNode.style.bottom = "".concat(windowBottom - anchorPosition.top + arrowHeight + offsetHeight, "px");
                            if (!checkHorizontal) {
                                if (anchorPosition.top - scrollParentDimsv2.top - _this.elementHeight - arrowHeight <
                                    0) {
                                    targetNode.style.top = "".concat(scrollParentDimsv2.top + arrowHeight, "px");
                                    targetNode.style.maxHeight = "".concat(maxHeight || scrollParentDimsv2.height, "px");
                                }
                            }
                            if (!checkVertical) {
                                if (_this.elementWidth > scrollParentDimsv2.width ||
                                    _this.elementRight > scrollParentDimsv2.right) {
                                    targetNode.style.right = "".concat(documentRight - scrollParentDimsv2.right, "px");
                                }
                                if (_this.elementLeft < scrollParentDimsv2.left) {
                                    targetNode.style.left = "".concat(scrollParentDimsv2.left, "px");
                                }
                            }
                            if (arrowDims &&
                                (arrowDims.top < scrollParentDims.top ||
                                    arrowDims.bottom + 1 > scrollParentDims.bottom)) {
                                _this.arrow.style.visibility = 'hidden';
                            }
                            else if (arrowDims) {
                                _this.arrow.style.visibility = 'visible';
                            }
                        }
                    }
                    break;
                case 'bottom':
                    if (!scrollParentDims.bottom && !transformParentDims) {
                        if (_this.elementHeight + arrowHeight + anchorPosition.bottom + documentScrollTop >
                            documentBottom) {
                            targetNode.style.bottom = "".concat(documentScrollTop + windowBottom - documentBottom, "px");
                        }
                        if (elementDims.right >= documentRight || _this.elementWidth > documentRight) {
                            targetNode.style.right = '0px';
                            if (_this.elementWidth < documentRight) {
                                targetNode.style.left = 'inherit';
                            }
                        }
                        if (elementDims.left < 0) {
                            targetNode.style.left = '0px';
                        }
                    }
                    else if (scrollParentDims.bottom && !transformParentDims) {
                        targetNode.style.bottom = 'auto';
                        if (anchorPosition.bottom + arrowHeight - scrollParentDims.top < 0) {
                            targetNode.style.top = "".concat(scrollParentDims.top - arrowHeight, "px");
                        }
                        if (_this.elementHeight + arrowHeight + anchorPosition.bottom > scrollParentDims.bottom) {
                            targetNode.style.bottom = "".concat(windowBottom - scrollParentDims.bottom, "px");
                            targetNode.style.maxHeight = "".concat(maxHeight || scrollParentDims.height, "px");
                        }
                        if (_this.elementWidth > scrollParentDims.width ||
                            _this.elementRight > scrollParentDims.right) {
                            targetNode.style.right = "".concat(documentRight - scrollParentDims.right, "px");
                        }
                        if (_this.elementLeft < scrollParentDims.left) {
                            targetNode.style.left = "".concat(scrollParentDims.left, "px");
                        }
                        if (arrowDims &&
                            (arrowDims.top < scrollParentDims.top || arrowDims.bottom + 1 > scrollParentDims.bottom)) {
                            _this.arrow.style.visibility = 'hidden';
                        }
                        else if (arrowDims) {
                            _this.arrow.style.visibility = 'visible';
                        }
                    }
                    else {
                        if (anchorPosition.bottom + arrowHeight + offsetHeight <
                            scrollParentDims.top - transformParentDims.top) {
                            targetNode.style.top = "".concat(scrollParentDims.top - transformParentDims.top - arrowHeight, "px");
                        }
                        if (_this.elementHeight + arrowHeight + anchorPosition.bottom >
                            transformParentDims.height + ((absoluteParentDims && absoluteParentDims.offsetTop) || 0)) {
                            targetNode.style.bottom = "0px";
                        }
                        if (_this.elementLeft < transformParentDims.left) {
                            targetNode.style.left = "0px";
                        }
                        if (_this.elementWidth > transformParentDims.width ||
                            _this.elementRight > transformParentDims.right) {
                            targetNode.style.right = "0px";
                            if (_this.elementWidth > transformParentDims.width) {
                                targetNode.style.left = "0px";
                            }
                            else {
                                targetNode.style.left = "".concat(transformParentDims.width - _this.elementWidth, "px");
                            }
                        }
                        if (arrowDims &&
                            (arrowDims.top < (checkOverflow ? scrollParentDims.top : transformParentDims.top) ||
                                arrowDims.bottom + 1 >
                                    (checkOverflow ? scrollParentDims.bottom : transformParentDims.bottom))) {
                            _this.arrow.style.visibility = 'hidden';
                        }
                        else if (arrowDims) {
                            _this.arrow.style.visibility = 'visible';
                        }
                    }
                    break;
                case 'left':
                    if (!scrollParentDims.left && !transformParentDims) {
                        targetNode.style.right = "".concat(documentRight - anchorPosition.left + arrowWidth + offsetWidth, "px");
                        if (elementDims.left - arrowWidth < 0) {
                            targetNode.style.left = "".concat(arrowWidth, "px");
                        }
                        else {
                            targetNode.style.left = 'inherit';
                        }
                        if (getAvailableTopSpace(documentScrollTop) < 0) {
                            targetNode.style.top = "".concat(-documentScrollTop, "px");
                        }
                        if (_this.elementHeight + arrowHeight + anchorPosition.bottom + documentScrollTop >
                            documentBottom) {
                            targetNode.style.bottom = "".concat(documentScrollTop + windowBottom - documentBottom, "px");
                        }
                    }
                    else if (scrollParentDims.left && !transformParentDims) {
                        if (anchorPosition.left - scrollParentDims.left < _this.elementWidth + arrowWidth) {
                            targetNode.style.left = "".concat(scrollParentDims.left + arrowWidth, "px");
                            targetNode.style.right = "".concat(documentRight - anchorPosition.left + arrowWidth + offsetWidth, "px");
                            targetNode.style.maxWidth = "".concat(maxWidth || scrollParentDims.width, "px");
                        }
                        if (anchorPosition.top - scrollParentDims.top - _this.elementHeight < 0) {
                            targetNode.style.top = "".concat(scrollParentDims.top, "px");
                        }
                        if (_this.elementHeight + anchorPosition.bottom > scrollParentDims.bottom) {
                            targetNode.style.bottom = "".concat(windowBottom - scrollParentDims.bottom, "px");
                        }
                        if (arrowDims &&
                            (arrowDims.top < scrollParentDims.top || arrowDims.bottom > scrollParentDims.bottom)) {
                            _this.arrow.style.visibility = 'hidden';
                        }
                        else if (arrowDims) {
                            _this.arrow.style.visibility = 'visible';
                        }
                    }
                    break;
                case 'right':
                    if (!scrollParentDims.right && !transformParentDims) {
                        if (arrowWidth + offsetWidth + elementDims.width + anchorPosition.right > documentRight) {
                            targetNode.style.right = '0px';
                        }
                        if (getAvailableTopSpace(documentScrollTop) < 0) {
                            targetNode.style.top = "".concat(-documentScrollTop, "px");
                        }
                        if (_this.elementHeight + arrowHeight + anchorPosition.bottom + documentScrollTop >
                            documentBottom) {
                            targetNode.style.bottom = "".concat(documentScrollTop + windowBottom - documentBottom, "px");
                        }
                    }
                    else if (scrollParentDims.right && !transformParentDims) {
                        if (anchorPosition.right + _this.elementWidth + arrowWidth > scrollParentDims.right) {
                            targetNode.style.left = "".concat(anchorPosition.right + offsetWidth, "px");
                            targetNode.style.right = transformParentDims
                                ? "".concat(scrollParentDims.width, "px")
                                : "".concat(documentRight - scrollParentDims.right, "px");
                            targetNode.style.maxWidth = "".concat(maxWidth || scrollParentDims.width, "px");
                        }
                        if (anchorPosition.top - scrollParentDims.top - _this.elementHeight < 0) {
                            targetNode.style.top = "".concat(scrollParentDims.top, "px");
                        }
                        if (_this.elementHeight + anchorPosition.bottom > scrollParentDims.bottom) {
                            targetNode.style.bottom = "".concat(windowBottom - scrollParentDims.bottom, "px");
                        }
                        if (arrowDims &&
                            (arrowDims.top < scrollParentDims.top || arrowDims.bottom > scrollParentDims.bottom)) {
                            _this.arrow.style.visibility = 'hidden';
                        }
                        else if (arrowDims) {
                            _this.arrow.style.visibility = 'visible';
                        }
                    }
                    break;
            }
        };
        _this.setBoundingContainer = function (containerNode) {
            var _a = _this.props, boundingParentID = _a.boundingParentID, isContained = _a.isContained;
            var containerParent = _this.state.containerParent;
            var containerNodeDims = (containerNode && containerNode.getBoundingClientRect()) || defaultDims;
            var containerParentDims = (containerParent && containerParent.getBoundingClientRect()) || defaultDims;
            var checkVertical = isContained === true || isContained === 'vertical';
            var checkHorizontal = isContained === true || isContained === 'horizontal';
            return {
                bottom: checkVertical && boundingParentID ? containerParentDims.bottom : containerNodeDims.bottom,
                center: 0,
                height: checkVertical && boundingParentID ? containerParentDims.height : containerNodeDims.height,
                left: checkHorizontal && boundingParentID ? containerParentDims.left : containerNodeDims.left,
                middle: 0,
                right: checkHorizontal && boundingParentID ? containerParentDims.right : containerNodeDims.right,
                top: checkVertical && boundingParentID ? containerParentDims.top : containerNodeDims.top,
                width: checkHorizontal && boundingParentID ? containerParentDims.width : containerNodeDims.width,
            };
        };
        _this.setHorizontalClass = function (alignment, anchor, elementBoundingRect, elementParent) {
            var _a = _this.props, showArrow = _a.showArrow, checkOverflow = _a.checkOverflow, targetOffset = _a.targetOffset, scrollParentID = _a.scrollParentID;
            var windowRight = window.pageYOffset + window.innerWidth;
            var elementWidth = elementBoundingRect.width;
            var anchorRight = anchor.right;
            var arrowWidth = showArrow
                ? ReactDOM.findDOMNode(_this.arrow).getBoundingClientRect().width
                : 0;
            var offsetWidth = targetOffset.horizontal || 0;
            var totalWidth = anchorRight + elementWidth + arrowWidth + offsetWidth;
            var elementParents = _this.findParents(elementParent);
            var scrollParent = scrollParentID
                ? React.findDOMNode(scrollParentID)
                : _this.findScrollParent(elementParents, ['overflow', 'overflow-x']);
            var parentRight = (checkOverflow &&
                !!scrollParent.getBoundingClientRect &&
                scrollParent.getBoundingClientRect().right) ||
                windowRight;
            return totalWidth < parentRight && totalWidth < windowRight
                ? _this.setState({ visibleDirection: "right-".concat(alignment) }, function () { return _this.setPlacement(); })
                : _this.setState({ visibleDirection: "left-".concat(alignment) }, function () { return _this.setPlacement(); });
        };
        _this.setPlacement = function () {
            var _a = _this.props, anchorNode = _a.anchorNode, isOpen = _a.isOpen, isContained = _a.isContained, showArrow = _a.showArrow, targetOffset = _a.targetOffset;
            var _b = _this.state, visibleDirection = _b.visibleDirection, absoluteParent = _b.absoluteParent, transformParent = _b.transformParent;
            if (!isOpen)
                return;
            var anchorElement = ReactDOM.findDOMNode(anchorNode);
            var side = visibleDirection.split('-')[0];
            var targetNode = _this.container;
            var verticalOffset = targetOffset.vertical || 0;
            var horizontalOffset = targetOffset.horizontal || 0;
            var absoluteParentDims = absoluteParent && _this.getElementPosition(absoluteParent);
            if (!targetNode || !anchorElement)
                return;
            anchorElement.link = _this.state.id;
            var anchorPosition = !!transformParent && absoluteParentDims && absoluteParentDims.hasAbsParent
                ? _this.getAbsoluteAnchorPosition(anchorElement, absoluteParentDims)
                : _this.getAnchorPosition(anchorElement);
            var targetPosition = _this.getTargetPosition(targetNode);
            var origin = _this.getOrigin();
            var anchorOrigin = origin.anchor;
            var targetOrigin = origin.target;
            var targetNodePosition = {
                top: anchorPosition[anchorOrigin.vertical] -
                    targetPosition[targetOrigin.vertical] +
                    (side === 'top' ? -verticalOffset : verticalOffset),
                left: anchorPosition[anchorOrigin.horizontal] -
                    targetPosition[targetOrigin.horizontal] +
                    (side === 'left' ? -horizontalOffset : horizontalOffset),
            };
            targetNode.style.top = "".concat(targetNodePosition.top, "px");
            targetNode.style.left = "".concat(targetNodePosition.left, "px");
            showArrow && _this.setArrowPlacement(anchorPosition, targetPosition);
            isContained && _this.setBoundingBox(side, targetNode, anchorPosition);
        };
        _this.setVerticalClass = function (alignment, anchor, elementBoundingRect, elementParent) {
            var _a = _this.props, showArrow = _a.showArrow, checkOverflow = _a.checkOverflow, targetOffset = _a.targetOffset, scrollParentID = _a.scrollParentID;
            var windowBottom = window.pageXOffset + window.innerHeight;
            var elementHeight = elementBoundingRect.height;
            var anchorBottom = anchor.bottom;
            var arrowHeight = showArrow
                ? ReactDOM.findDOMNode(_this.arrow).getBoundingClientRect().height
                : 0;
            var offsetHeight = targetOffset.vertical || 0;
            var totalHeight = anchorBottom + elementHeight + arrowHeight + offsetHeight;
            var elementParents = _this.findParents(elementParent);
            var scrollParent = scrollParentID
                ? React.findDOMNode(scrollParentID)
                : _this.findScrollParent(elementParents, ['overflow', 'overflow-x']);
            var parentBottom = (checkOverflow &&
                !!scrollParent.getBoundingClientRect &&
                scrollParent.getBoundingClientRect().bottom) ||
                windowBottom;
            return totalHeight < parentBottom && totalHeight < windowBottom
                ? _this.setState({ visibleDirection: "bottom-".concat(alignment) }, function () { return _this.setPlacement(); })
                : _this.setState({ visibleDirection: "top-".concat(alignment) }, function () { return _this.setPlacement(); });
        };
        return _this;
    }
    EventOverlay.getDerivedStateFromProps = function (_a, state) {
        var isOpen = _a.isOpen;
        return __assign(__assign({}, state), { isOpen: isOpen });
    };
    EventOverlay.prototype.render = function () {
        var _this = this;
        var _a = this.props, children = _a.children, className = _a.className, focusLockProps = _a.focusLockProps, isOpen = _a.isOpen, maxHeight = _a.maxHeight, maxWidth = _a.maxWidth, portalNode = _a.portalNode, shouldLockFocus = _a.shouldLockFocus, showArrow = _a.showArrow, style = _a.style, props = __rest(_a, ["children", "className", "focusLockProps", "isOpen", "maxHeight", "maxWidth", "portalNode", "shouldLockFocus", "showArrow", "style"]);
        var side = this.state.visibleDirection.split('-')[0];
        var otherProps = omit(__assign({}, props), [
            'absoluteParentID',
            'allowClickAway',
            'anchorNode',
            'boundingParentID',
            'checkOverflow',
            'close',
            'closeOnClick',
            'direction',
            'disableCloseOnEnterOrSpaceKey',
            'isDynamic',
            'isContained',
            'scrollParentID',
            'targetOffset',
            'transformParentID',
        ]);
        var contentNodes = isOpen && (React.createElement("div", { className: 'md-event-overlay' +
                "".concat((showArrow && " md-event-overlay--arrow") || '') +
                "".concat((side && " md-event-overlay--".concat(side)) || '') +
                "".concat((className && " ".concat(className)) || '') },
            showArrow && React.createElement("div", { ref: function (ref) { return (_this.arrow = ref); }, className: "md-event-overlay__arrow" }),
            React.createElement("div", __assign({ className: "md-event-overlay__children", ref: function (ref) { return (_this.container = ref); }, style: __assign(__assign(__assign({}, (maxWidth && { maxWidth: "".concat(maxWidth, "px") })), (maxHeight && { maxHeight: "".concat(maxHeight, "px") })), style) }, otherProps), children)));
        var withFocusLock = function (content) {
            return shouldLockFocus ? (React.createElement(FocusScope, __assign({}, focusLockProps, { contain: true }), content)) : (content);
        };
        var withPortal = function (content) {
            return portalNode ? ReactDOM.createPortal(content, portalNode) : content;
        };
        return withFocusLock(withPortal(contentNodes));
    };
    return EventOverlay;
}(React.Component));
EventOverlay.defaultProps = {
    absoluteParentID: null,
    allowClickAway: true,
    anchorNode: null,
    boundingParentID: null,
    children: null,
    checkOverflow: false,
    className: '',
    close: null,
    direction: 'bottom-left',
    disableCloseOnEnterOrSpaceKey: false,
    focusLockProps: null,
    isContained: '',
    isDynamic: false,
    isOpen: false,
    maxHeight: null,
    maxWidth: null,
    portalNode: null,
    scrollParentID: null,
    shouldLockFocus: false,
    showArrow: false,
    style: null,
    targetOffset: {
        horizontal: 0,
        vertical: 0,
    },
    transformParentID: null,
};
EventOverlay.propTypes = {
    /** @prop Set the id of the absoluteParent | null */
    absoluteParentID: PropTypes.string,
    /** @prop Allows user to click outside of EventOverlay | true */
    allowClickAway: PropTypes.bool,
    /** @prop Node which serves as basis of dom positioning | null */
    anchorNode: PropTypes.object,
    /** @prop Set the id of the boundingParent | null */
    boundingParentID: PropTypes.string,
    /** @prop Set to determine if dom ancestors have overflow property | false */
    checkOverflow: PropTypes.bool,
    /** @prop Children nodes to render inside the EventOverlay | null */
    children: PropTypes.node,
    /** @prop Optional css class string | '' */
    className: PropTypes.string,
    /** @prop Function to close EventOverlay | null */
    close: PropTypes.func,
    /** @prop Determines if the EventOverlay should close when clicked on | true */
    closeOnClick: PropTypes.bool,
    /** @prop Sets the direction in which the EventOverlay extends | 'bottom-left' */
    direction: PropTypes.oneOf([
        'top-center',
        'left-center',
        'right-center',
        'bottom-center',
        'top-left',
        'top-right',
        'bottom-left',
        'bottom-right',
        'left-top',
        'left-bottom',
        'right-top',
        'right-bottom',
    ]),
    /** @prop Prevent closing on ENTER or SPACE keydown event | false */
    disableCloseOnEnterOrSpaceKey: PropTypes.bool,
    /** @prop Props to be passed to focus lock component | null */
    focusLockProps: PropTypes.object,
    /** @prop Determines if the overlay is contained in bounding ancestor | '' */
    isContained: PropTypes.oneOf([true, false, 'horizontal', 'vertical', 'both', '']),
    /** @prop When true, will flip children based on space available (does not work with isContained) | false */
    isDynamic: PropTypes.bool,
    /** @prop Sets the visibility of the EventOverlay | false */
    isOpen: PropTypes.bool,
    /** @prop Sets the max height of the EventOverlay | null */
    maxHeight: PropTypes.number,
    /** @prop Sets the max width of the EventOverlay | null */
    maxWidth: PropTypes.number,
    /** @prop Node/ReactElement where overlay should be appended using ReactDOM portal | null */
    portalNode: PropTypes.oneOfType([PropTypes.node, PropTypes.element]),
    /** @prop Set the id of the scrollParent | null */
    scrollParentID: PropTypes.string,
    /** @prop Determines if focus should be locked to overlay | false */
    shouldLockFocus: PropTypes.bool,
    /** @prop Determines if the EventOverlay should show the open/close arrow | false */
    showArrow: PropTypes.bool,
    /** @prop Optional css styling | null */
    style: PropTypes.object,
    /** @prop Sets the target offset from anchorNode | { horizontal: 0, vertical: 0 } */
    targetOffset: PropTypes.shape({
        horizontal: PropTypes.number,
        vertical: PropTypes.number,
    }),
    /** @prop Set the id of the transformParent | null */
    transformParentID: PropTypes.string,
};
EventOverlay.displayName = 'EventOverlay';
export default EventOverlay;
//# sourceMappingURL=index.js.map