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