import closeIcon from 'assets/images/close.svg'; import React, { PureComponent } from 'react'; import { CSSTransition, TransitionGroup } from 'react-transition-group'; import './Modal.scss'; export interface IButton { text: string | React.ReactElement; type?: 'default' | 'primary' | 'success' | 'info' | 'warning' | 'danger' | 'link'; disabled?: boolean; onClick?(): void; } interface Props { isOpen?: boolean; title?: string | React.ReactElement; disableButtons?: boolean; children: any; buttons?: IButton[]; maxWidth?: number; handleClose?(): void; } interface ModalStyle { width?: string; maxWidth?: string; } const Fade = ({ children, ...props }) => ( {children} ); export default class Modal extends PureComponent { private modalContent: HTMLElement | null = null; public componentDidMount() { this.updateBodyClass(); document.addEventListener('keydown', this.escapeListner); } public componentDidUpdate() { this.updateBodyClass(); } public updateBodyClass() { document.body.classList.toggle('no-scroll', !!this.props.isOpen); } public componentWillUnmount() { document.removeEventListener('keydown', this.escapeListner); document.body.classList.remove('no-scroll'); } public render() { const { isOpen, title, children, buttons, handleClose, maxWidth } = this.props; const hasButtons = buttons && buttons.length; const modalStyle: ModalStyle = {}; if (maxWidth) { modalStyle.width = '100%'; modalStyle.maxWidth = `${maxWidth}px`; } return ( {isOpen && (
{title && (

{title}

)}
(this.modalContent = el)}> {isOpen && children}
{hasButtons &&
{this.renderButtons()}
}
)} ); } public scrollContentToTop = () => { if (this.modalContent) { this.modalContent.scrollTop = 0; } }; private escapeListner = (ev: KeyboardEvent) => { if (!this.props.isOpen) { return; } // Don't trigger if they hit escape while on an input if (ev.target) { if ( (ev.target as HTMLElement).tagName === 'INPUT' || (ev.target as HTMLElement).tagName === 'SELECT' || (ev.target as HTMLElement).tagName === 'TEXTAREA' || (ev.target as HTMLElement).isContentEditable ) { return; } } if (ev.key === 'Escape' || ev.keyCode === 27) { if (!this.props.handleClose) { return; } this.props.handleClose(); } }; private renderButtons = () => { const { disableButtons, buttons } = this.props; if (!buttons || !buttons.length) { return; } return buttons.map((btn, idx) => { let btnClass = 'Modal-footer-btn btn'; if (btn.type) { btnClass += ` btn-${btn.type}`; } return ( ); }); }; }