92 lines
2.9 KiB
JavaScript
92 lines
2.9 KiB
JavaScript
/**
|
|
* Copyright (c) 2019-present Tomek Wójcik <tomek@bthlabs.pl>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
import ClassName from 'classnames';
|
|
import PropTypes from 'prop-types';
|
|
import React from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
|
|
export const Popup = (props) => {
|
|
const className = ClassName('bthlabs-react-custom-popup', props.className, {
|
|
'bthlabs-rcp-visible': props.visible
|
|
});
|
|
|
|
let layout = [0, 0];
|
|
const body = document.body;
|
|
const innerStyle = {};
|
|
if (props.visible && props.anchor && props.anchor.current) {
|
|
const box = props.anchor.current.getBoundingClientRect();
|
|
const document_ = document.documentElement;
|
|
|
|
const scrollTop = (
|
|
window.pageYOffset || document_.scrollTop || body.scrollTop
|
|
);
|
|
const scrollLeft = (
|
|
window.pageXOffset || document_.scrollLeft || body.scrollLeft
|
|
);
|
|
|
|
const clientTop = document_.clientTop || body.clientTop || 0;
|
|
const clientLeft = document_.clientLeft || body.clientLeft || 0;
|
|
|
|
layout[0] = box.left + scrollLeft - clientLeft;
|
|
layout[1] = box.top + scrollTop - clientTop;
|
|
}
|
|
|
|
if (props.visible) {
|
|
if (typeof props.onLayout === 'function') {
|
|
layout = props.onLayout(layout);
|
|
}
|
|
|
|
innerStyle.left = `${layout[0]}px`;
|
|
innerStyle.top = `${layout[1]}px`;
|
|
|
|
if (layout[2]) {
|
|
innerStyle.width = `${layout[2]}px`;
|
|
}
|
|
|
|
if (layout[3]) {
|
|
innerStyle.height = `${layout[3]}px`;
|
|
}
|
|
}
|
|
|
|
return ReactDOM.createPortal(
|
|
<div className={className}>
|
|
{!props.hideOverlay &&
|
|
<div className="bthlabs-rcp-overlay" onClick={props.onOverlayClick} />
|
|
}
|
|
<div className="bthlabs-rcp-inner" style={innerStyle}>
|
|
{props.children}
|
|
</div>
|
|
</div>,
|
|
props.domNode || body
|
|
);
|
|
};
|
|
|
|
Popup.propTypes = {
|
|
anchor: PropTypes.object,
|
|
className: PropTypes.string,
|
|
hideOverlay: PropTypes.bool,
|
|
visible: PropTypes.bool.isRequired,
|
|
onLayout: PropTypes.func,
|
|
onOverlayClick: PropTypes.func
|
|
};
|