MyCrypto/common/components/ui/Modal.jsx

133 lines
3.0 KiB
JavaScript

// @flow
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import closeIcon from 'assets/images/icon-x.svg';
import './Modal.scss';
type Props = {
isOpen?: boolean,
title: string,
buttons: {
text: string,
type?:
| 'default'
| 'primary'
| 'success'
| 'info'
| 'warning'
| 'danger'
| 'link',
onClick: () => void
}[],
handleClose: () => void,
children: any
};
export default class Modal extends Component {
props: Props;
static propTypes = {
isOpen: PropTypes.bool,
title: PropTypes.node.isRequired,
children: PropTypes.node,
buttons: PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.node.isRequired,
type: PropTypes.oneOf([
'default',
'primary',
'success',
'info',
'warning',
'danger',
'link'
]),
onClick: PropTypes.func.isRequired
})
),
handleClose: PropTypes.func.isRequired
};
componentDidMount() {
this.updateBodyClass();
document.addEventListener('keydown', this._escapeListner);
}
componentDidUpdate() {
this.updateBodyClass();
}
updateBodyClass() {
// $FlowFixMe
document.body.classList.toggle('no-scroll', !!this.props.isOpen);
}
componentWillUnmount() {
document.removeEventListener('keydown', this._escapeListner);
// $FlowFixMe
document.body.classList.remove('no-scroll');
}
_escapeListner = (ev: KeyboardEvent) => {
// Don't trigger if they hit escape while on an input
if (ev.target) {
if (
ev.target.tagName === 'INPUT' ||
ev.target.tagName === 'SELECT' ||
ev.target.tagName === 'TEXTAREA' ||
ev.target.isContentEditable
) {
return;
}
}
if (ev.key === 'Escape' || ev.keyCode === 27) {
this.props.handleClose();
}
};
_renderButtons() {
return this.props.buttons.map((btn, idx) => {
let btnClass = 'Modal-footer-btn btn';
if (btn.type) {
btnClass += ` btn-${btn.type}`;
}
return (
<button className={btnClass} onClick={btn.onClick} key={idx}>
{btn.text}
</button>
);
});
}
render() {
const { isOpen, title, children, buttons, handleClose } = this.props;
const hasButtons = buttons && buttons.length;
return (
<div>
<div className={`Modalshade ${isOpen ? 'is-open' : ''}`} />
<div className={`Modal ${isOpen ? 'is-open' : ''}`}>
<div className="Modal-header">
<h2 className="Modal-header-title">
{title}
</h2>
<button className="Modal-header-close" onClick={handleClose}>
<img className="Modal-header-close-icon" src={closeIcon} />
</button>
</div>
<div className="Modal-content">
{isOpen && children}
</div>
{hasButtons &&
<div className="Modal-footer">
{this._renderButtons()}
</div>}
</div>
</div>
);
}
}