All files / components/Portal Portal.jsx

100% Statements 14/14
50% Branches 1/2
100% Functions 1/1
100% Lines 14/14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68          121x               121x                 121x                                 42x       40x   40x 40x 40x 40x 40x   40x 40x     40x     42x                  
import React from 'react';
import ReactDOM from 'react-dom';
import { createClass, omitProps } from '../../util/component-types';
import { lucidClassNames } from '../../util/style-helpers';
 
const cx = lucidClassNames.bind('&-Portal');
 
const {
	PropTypes: {
		any,
		node,
		string,
	},
} = React;
 
/**
 *
 * {"categories": ["utility"]}
 *
 * A Portal component is used to render content in a container that is appended
 * to `document.body`.
 */
const Portal = createClass({
	displayName: 'Portal',
	propTypes: {
		/**
		 * any valid React children
		 */
		children: node,
		/**
		 * Appended to the component-specific class names set on the root
		 * element. Value is run through the `classnames` library.
		 */
		className: any,
		/**
		 * The `id` of the portal element that is appended to `document.body`.
		 */
		portalId: string.isRequired,
	},
	render: () => null,
	componentDidMount() {
		const {
			portalId,
		} = this.props;
 
		let portalElement = window.document.getElementById(portalId);
		Eif (!portalElement) {
			portalElement = window.document.createElement('div');
			portalElement.id = portalId;
			window.document.body.appendChild(portalElement);
		}
		this.portalElement = portalElement;
		this.componentDidUpdate();
	},
	componentWillUnmount() {
		window.document.body.removeChild(this.portalElement);
	},
	componentDidUpdate() {
		ReactDOM.render((
			<div {...omitProps(this.props, Portal)} className={cx('&', this.props.className)}>
				{this.props.children}
			</div>
		), this.portalElement);
	},
});
 
export default Portal;