1
0
Fork 0
react-custom-popup/src/Popup.js

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
};