@momentum-ui/react
Version:
Cisco Momentum UI framework for ReactJs applications
1,032 lines (829 loc) • 43.3 kB
JavaScript
"use strict";
exports.__esModule = true;
exports.default = void 0;
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _omit = _interopRequireDefault(require("lodash/omit"));
var _reactFocusLock = _interopRequireDefault(require("react-focus-lock"));
var _excluded = ["children", "className", "focusLockProps", "isOpen", "maxHeight", "maxWidth", "portalNode", "shouldLockFocus", "showArrow", "style"];
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var defaultDims = {
offsetTop: 0,
bottom: 0,
center: 0,
height: 0,
left: 0,
middle: 0,
right: 0,
top: 0,
width: 0
};
function eventPath(evt) {
var path = evt.composedPath && evt.composedPath() || evt.path,
target = evt.target;
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]);
}
var EventOverlay = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(EventOverlay, _React$Component);
function EventOverlay() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || 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 _this$props = _this.props,
absoluteParentID = _this$props.absoluteParentID,
allowClickAway = _this$props.allowClickAway,
boundingParentID = _this$props.boundingParentID,
checkOverflow = _this$props.checkOverflow,
closeOnClick = _this$props.closeOnClick,
isContained = _this$props.isContained,
scrollParentID = _this$props.scrollParentID,
transformParentID = _this$props.transformParentID;
_this.handleResize = _this.isVisible;
_this.handleScroll = _this.isVisible;
var element = _reactDom.default.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.default.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;
var domAnchorNode = anchorNode && (anchorNode.props ? anchorNode.props.onClick : false) && _reactDom.default.findDOMNode(anchorNode);
domAnchorNode && domAnchorNode.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.default.findDOMNode(_this.props.anchorNode);
return _this.container && !anchorNode.contains(eventTarget) && !_reactDom.default.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.default.findDOMNode(_this.container).contains(eventTarget) && _this.handleClickAway(e);
};
_this.handleKeyDown = function (e) {
var _this$props2 = _this.props,
isOpen = _this$props2.isOpen,
disableCloseOnEnterOrSpaceKey = _this$props2.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.default.findDOMNode(_this.props.anchorNode);
return _this.container && anchorNode && !anchorNode.contains(eventTarget) && !_reactDom.default.findDOMNode(_this.container).contains(eventTarget) && _this.handleClickAway(e);
}
};
_this.isVisible = function () {
var _this$props3 = _this.props,
anchorNode = _this$props3.anchorNode,
direction = _this$props3.direction,
isOpen = _this$props3.isOpen,
isDynamic = _this$props3.isDynamic;
if (!isOpen) return;
if (!isDynamic) return _this.setPlacement();
var anchorElement = _reactDom.default.findDOMNode(anchorNode);
var element = _reactDom.default.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 = arrowLeft + "px";
arrow.style.top = anchor.top - verticalOffset + "px";
break;
case 'bottom':
arrow.style.left = arrowLeft + "px";
arrow.style.top = anchor.bottom + verticalOffset + "px";
break;
case 'left':
arrow.style.left = anchor.left - horizontalOffset + "px";
arrow.style.top = arrowTop + "px";
break;
case 'right':
arrow.style.left = anchor.right + horizontalOffset + "px";
arrow.style.top = arrowTop + "px";
break;
}
};
_this.setBoundingBox = function (side, targetNode, anchorPosition) {
var _this$props4 = _this.props,
checkOverflow = _this$props4.checkOverflow,
isContained = _this$props4.isContained,
maxHeight = _this$props4.maxHeight,
maxWidth = _this$props4.maxWidth,
showArrow = _this$props4.showArrow,
targetOffset = _this$props4.targetOffset;
var _this$state = _this.state,
absoluteParent = _this$state.absoluteParent,
scrollParent = _this$state.scrollParent,
transformParent = _this$state.transformParent;
var arrowDims = showArrow && _reactDom.default.findDOMNode(_this.arrow).getBoundingClientRect();
var checkVertical = isContained === 'vertical';
var checkHorizontal = isContained === 'horizontal';
var element = _reactDom.default.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 getAvailableTopSpace(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 = windowBottom - anchorPosition.top + arrowHeight + offsetHeight + "px";
if (getAvailableTopSpace(documentScrollTop) < 0) {
targetNode.style.top = arrowHeight - documentScrollTop + "px";
}
}
if (!checkVertical) {
if (elementDims.right > documentRight || _this.elementWidth > documentRight) {
targetNode.style.right = '0px';
if (_this.elementWidth < documentRight) {
targetNode.style.left = documentRight - _this.elementWidth + "px";
}
}
if (_this.elementLeft < 0) {
targetNode.style.left = '0px';
}
}
} else {
if (transformParentDims) {
targetNode.style.bottom = transformParentDims.height - anchorPosition.top + arrowHeight + offsetHeight + "px";
if (anchorPosition.top - scrollParentScrollTop - _this.elementHeight - arrowHeight < 0) {
targetNode.style.top = scrollParentScrollTop + arrowHeight + "px";
targetNode.style.maxHeight = (maxHeight || transformParentDims.height) + "px";
}
if (!checkVertical) {
if (_this.elementWidth > transformParentDims.width || _this.elementRight > transformParentDims.right) {
targetNode.style.right = 0 + "px";
if (_this.elementWidth > transformParentDims.width) {
targetNode.style.left = "0px";
} else {
targetNode.style.left = _this.elementWidth + "px";
}
}
if (_this.elementLeft < transformParentDims.left) {
targetNode.style.left = 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 = windowBottom - anchorPosition.top + arrowHeight + offsetHeight + "px";
if (!checkHorizontal) {
if (anchorPosition.top - scrollParentDimsv2.top - _this.elementHeight - arrowHeight < 0) {
targetNode.style.top = scrollParentDimsv2.top + arrowHeight + "px";
targetNode.style.maxHeight = (maxHeight || scrollParentDimsv2.height) + "px";
}
}
if (!checkVertical) {
if (_this.elementWidth > scrollParentDimsv2.width || _this.elementRight > scrollParentDimsv2.right) {
targetNode.style.right = documentRight - scrollParentDimsv2.right + "px";
}
if (_this.elementLeft < scrollParentDimsv2.left) {
targetNode.style.left = 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 = 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 = scrollParentDims.top - arrowHeight + "px";
}
if (_this.elementHeight + arrowHeight + anchorPosition.bottom > scrollParentDims.bottom) {
targetNode.style.bottom = windowBottom - scrollParentDims.bottom + "px";
targetNode.style.maxHeight = (maxHeight || scrollParentDims.height) + "px";
}
if (_this.elementWidth > scrollParentDims.width || _this.elementRight > scrollParentDims.right) {
targetNode.style.right = documentRight - scrollParentDims.right + "px";
}
if (_this.elementLeft < scrollParentDims.left) {
targetNode.style.left = 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 = 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 = 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 = documentRight - anchorPosition.left + arrowWidth + offsetWidth + "px";
if (elementDims.left - arrowWidth < 0) {
targetNode.style.left = arrowWidth + "px";
} else {
targetNode.style.left = 'inherit';
}
if (getAvailableTopSpace(documentScrollTop) < 0) {
targetNode.style.top = -documentScrollTop + "px";
}
if (_this.elementHeight + arrowHeight + anchorPosition.bottom + documentScrollTop > documentBottom) {
targetNode.style.bottom = documentScrollTop + windowBottom - documentBottom + "px";
}
} else if (scrollParentDims.left && !transformParentDims) {
if (anchorPosition.left - scrollParentDims.left < _this.elementWidth + arrowWidth) {
targetNode.style.left = scrollParentDims.left + arrowWidth + "px";
targetNode.style.right = documentRight - anchorPosition.left + arrowWidth + offsetWidth + "px";
targetNode.style.maxWidth = (maxWidth || scrollParentDims.width) + "px";
}
if (anchorPosition.top - scrollParentDims.top - _this.elementHeight < 0) {
targetNode.style.top = scrollParentDims.top + "px";
}
if (_this.elementHeight + anchorPosition.bottom > scrollParentDims.bottom) {
targetNode.style.bottom = 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 = -documentScrollTop + "px";
}
if (_this.elementHeight + arrowHeight + anchorPosition.bottom + documentScrollTop > documentBottom) {
targetNode.style.bottom = documentScrollTop + windowBottom - documentBottom + "px";
}
} else if (scrollParentDims.right && !transformParentDims) {
if (anchorPosition.right + _this.elementWidth + arrowWidth > scrollParentDims.right) {
targetNode.style.left = anchorPosition.right + offsetWidth + "px";
targetNode.style.right = transformParentDims ? scrollParentDims.width + "px" : documentRight - scrollParentDims.right + "px";
targetNode.style.maxWidth = (maxWidth || scrollParentDims.width) + "px";
}
if (anchorPosition.top - scrollParentDims.top - _this.elementHeight < 0) {
targetNode.style.top = scrollParentDims.top + "px";
}
if (_this.elementHeight + anchorPosition.bottom > scrollParentDims.bottom) {
targetNode.style.bottom = 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 _this$props5 = _this.props,
boundingParentID = _this$props5.boundingParentID,
isContained = _this$props5.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 _this$props6 = _this.props,
showArrow = _this$props6.showArrow,
checkOverflow = _this$props6.checkOverflow,
targetOffset = _this$props6.targetOffset,
scrollParentID = _this$props6.scrollParentID;
var windowRight = window.pageYOffset + window.innerWidth;
var elementWidth = elementBoundingRect.width;
var anchorRight = anchor.right;
var arrowWidth = showArrow ? _reactDom.default.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.default.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-" + alignment
}, function () {
return _this.setPlacement();
}) : _this.setState({
visibleDirection: "left-" + alignment
}, function () {
return _this.setPlacement();
});
};
_this.setPlacement = function () {
var _this$props7 = _this.props,
anchorNode = _this$props7.anchorNode,
isOpen = _this$props7.isOpen,
isContained = _this$props7.isContained,
showArrow = _this$props7.showArrow,
targetOffset = _this$props7.targetOffset;
var _this$state2 = _this.state,
visibleDirection = _this$state2.visibleDirection,
absoluteParent = _this$state2.absoluteParent,
transformParent = _this$state2.transformParent;
if (!isOpen) return;
var anchorElement = _reactDom.default.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 = targetNodePosition.top + "px";
targetNode.style.left = targetNodePosition.left + "px";
showArrow && _this.setArrowPlacement(anchorPosition, targetPosition);
isContained && _this.setBoundingBox(side, targetNode, anchorPosition);
};
_this.setVerticalClass = function (alignment, anchor, elementBoundingRect, elementParent) {
var _this$props8 = _this.props,
showArrow = _this$props8.showArrow,
checkOverflow = _this$props8.checkOverflow,
targetOffset = _this$props8.targetOffset,
scrollParentID = _this$props8.scrollParentID;
var windowBottom = window.pageXOffset + window.innerHeight;
var elementHeight = elementBoundingRect.height;
var anchorBottom = anchor.bottom;
var arrowHeight = showArrow ? _reactDom.default.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.default.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-" + alignment
}, function () {
return _this.setPlacement();
}) : _this.setState({
visibleDirection: "top-" + alignment
}, function () {
return _this.setPlacement();
});
};
return _this;
}
EventOverlay.getDerivedStateFromProps = function getDerivedStateFromProps(_ref, state) {
var isOpen = _ref.isOpen;
return _extends({}, state, {
isOpen: isOpen
});
};
var _proto = EventOverlay.prototype;
_proto.render = function render() {
var _this2 = this;
var _this$props9 = this.props,
children = _this$props9.children,
className = _this$props9.className,
focusLockProps = _this$props9.focusLockProps,
isOpen = _this$props9.isOpen,
maxHeight = _this$props9.maxHeight,
maxWidth = _this$props9.maxWidth,
portalNode = _this$props9.portalNode,
shouldLockFocus = _this$props9.shouldLockFocus,
showArrow = _this$props9.showArrow,
style = _this$props9.style,
props = _objectWithoutPropertiesLoose(_this$props9, _excluded);
var side = this.state.visibleDirection.split('-')[0];
var otherProps = (0, _omit.default)(_extends({}, props), ['absoluteParentID', 'allowClickAway', 'anchorNode', 'boundingParentID', 'checkOverflow', 'close', 'closeOnClick', 'direction', 'disableCloseOnEnterOrSpaceKey', 'isDynamic', 'isContained', 'scrollParentID', 'targetOffset', 'transformParentID']);
var contentNodes = isOpen && /*#__PURE__*/_react.default.createElement("div", {
className: 'md-event-overlay' + ("" + (showArrow && " md-event-overlay--arrow" || '')) + ("" + (side && " md-event-overlay--" + side || '')) + ("" + (className && " " + className || ''))
}, showArrow && /*#__PURE__*/_react.default.createElement("div", {
ref: function ref(_ref2) {
return _this2.arrow = _ref2;
},
className: "md-event-overlay__arrow"
}), /*#__PURE__*/_react.default.createElement("div", _extends({
className: "md-event-overlay__children",
ref: function ref(_ref3) {
return _this2.container = _ref3;
},
style: _extends({}, maxWidth && {
maxWidth: maxWidth + "px"
}, maxHeight && {
maxHeight: maxHeight + "px"
}, style)
}, otherProps), children));
var withFocusLock = function withFocusLock(content) {
return shouldLockFocus ? /*#__PURE__*/_react.default.createElement(_reactFocusLock.default, focusLockProps, content) : content;
};
var withPortal = function withPortal(content) {
return portalNode ? /*#__PURE__*/_reactDom.default.createPortal(content, portalNode) : content;
};
return withFocusLock(withPortal(contentNodes));
};
return EventOverlay;
}(_react.default.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.default.string,
/** @prop Allows user to click outside of EventOverlay | true */
allowClickAway: _propTypes.default.bool,
/** @prop Node which serves as basis of dom positioning | null */
anchorNode: _propTypes.default.object,
/** @prop Set the id of the boundingParent | null */
boundingParentID: _propTypes.default.string,
/** @prop Set to determine if dom ancestors have overflow property | false */
checkOverflow: _propTypes.default.bool,
/** @prop Children nodes to render inside the EventOverlay | null */
children: _propTypes.default.node,
/** @prop Optional css class string | '' */
className: _propTypes.default.string,
/** @prop Function to close EventOverlay | null */
close: _propTypes.default.func,
/** @prop Determines if the EventOverlay should close when clicked on | true */
closeOnClick: _propTypes.default.bool,
/** @prop Sets the direction in which the EventOverlay extends | 'bottom-left' */
direction: _propTypes.default.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.default.bool,
/** @prop Props to be passed to focus lock component | null */
focusLockProps: _propTypes.default.object,
/** @prop Determines if the overlay is contained in bounding ancestor | '' */
isContained: _propTypes.default.oneOf([true, false, 'horizontal', 'vertical', 'both', '']),
/** @prop When true, will flip children based on space available (does not work with isContained) | false */
isDynamic: _propTypes.default.bool,
/** @prop Sets the visibility of the EventOverlay | false */
isOpen: _propTypes.default.bool,
/** @prop Sets the max height of the EventOverlay | null */
maxHeight: _propTypes.default.number,
/** @prop Sets the max width of the EventOverlay | null */
maxWidth: _propTypes.default.number,
/** @prop Node/ReactElement where overlay should be appended using ReactDOM portal | null */
portalNode: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.element]),
/** @prop Set the id of the scrollParent | null */
scrollParentID: _propTypes.default.string,
/** @prop Determines if focus should be locked to overlay | false */
shouldLockFocus: _propTypes.default.bool,
/** @prop Determines if the EventOverlay should show the open/close arrow | false */
showArrow: _propTypes.default.bool,
/** @prop Optional css styling | null */
style: _propTypes.default.object,
/** @prop Sets the target offset from anchorNode | { horizontal: 0, vertical: 0 } */
targetOffset: _propTypes.default.shape({
horizontal: _propTypes.default.number,
vertical: _propTypes.default.number
}),
/** @prop Set the id of the transformParent | null */
transformParentID: _propTypes.default.string
};
EventOverlay.displayName = 'EventOverlay';
var _default = EventOverlay;
exports.default = _default;