UNPKG

@momentum-ui/react

Version:

Cisco Momentum UI framework for ReactJs applications

155 lines (135 loc) 4.13 kB
/** @component modal */ import React from 'react'; import PropTypes from 'prop-types'; // Library that manages Tabbing and Accessibility for Modal https://github.com/davidtheclark/react-aria-modal import AriaModal from 'react-aria-modal'; class Modal extends React.Component { static childContextTypes = { handleClose: PropTypes.func }; state = { animationClass: this.props.show ? 'in' : '', }; getChildContext = () => { return { handleClose: e => this.closeModal(e) }; }; componentDidUpdate(prevProps) { prevProps.show !== this.props.show && this.props.show && this.setAnimationState(true); } componentWillUnmount() { this.hideTimerId && clearTimeout(this.hideTimerId); this.hideTimerId = null; } closeModal = e => { this.setAnimationState(); this.hideTimerId && clearTimeout(this.hideTimerId); this.hideTimerId = setTimeout(() => { this.props.onHide(e); }, 300); } setAnimationState = isOpen => { this.setState({ animationClass: isOpen ? 'in' : '' }); } render() { const { applicationId, backdrop, backdropClickExit, children, className, escapeExits, focusDialog, htmlId, renderTo, show, size, ...props } = this.props; const modalContent = ( <div className="md-modal__content"> <div className="md-modal__flex-container"> {children} </div> </div> ); const RenderModal = renderTo ? AriaModal.renderTo(`#${renderTo}`) : AriaModal; const getModal = () => { return show && <RenderModal onExit={this.closeModal} getApplicationNode={() => document.querySelector(`#${applicationId}`)} dialogClass={ `md-modal` + ` md-modal--${size}` + ` ${this.state.animationClass}` + `${(className && ` ${className}`) || ''}` } includeDefaultStyles={false} titleId={htmlId} underlayClass={ backdrop ? `md-modal__backdrop fade` + ` ${this.state.animationClass}` : '' } underlayClickExits={backdropClickExit} escapeExits={escapeExits} focusDialog={focusDialog} {...props} > {modalContent} </RenderModal>; }; return ( getModal() ); } } Modal.propTypes = { /** @prop application DOM id, used to set aria-hidden to true when modal is open */ applicationId: PropTypes.string.isRequired, /** @prop Determines the visibility and ability to edit the backdrop of the Modal | true */ backdrop: PropTypes.bool, /** @prop To enable/disable clicking on underlay to exit modal | false */ backdropClickExit: PropTypes.bool, /** @prop Children nodes to render inside the Modal | null */ children: PropTypes.node, /** @prop Optional css class names | '' */ className: PropTypes.string, /** @prop To enable/disable escape to exit modal | true */ escapeExits: PropTypes.bool, /** @prop To set focus to the entire modal rather than elements within modal | true */ focusDialog: PropTypes.bool, /** @prop Unique HTML ID used for tying label to HTML input for automated testing */ htmlId: PropTypes.string.isRequired, /** @prop Icon node to be rendered for Dialog | null */ icon: PropTypes.element, /** @prop Callback function invoked when user clicks on cross button or esc key */ onHide: PropTypes.func.isRequired, /** @prop To render to an element other than the browser window | null */ renderTo: PropTypes.string, /** @prop Show/hide modal */ show: PropTypes.bool.isRequired, /** @prop Size of the modal | 'default' */ size: PropTypes.oneOf(['large', 'medium', 'default', 'small', 'full', 'dialog']), }; Modal.defaultProps = { backdrop: true, backdropClickExit: false, children: null, className: '', escapeExits: true, focusDialog: true, icon: null, renderTo: null, show: false, size: 'default', }; Modal.displayName = 'Modal'; export default Modal;