@shopify/polaris
Version:
Shopify’s product component library
58 lines (57 loc) • 2.14 kB
JavaScript
import React from 'react';
import { createPortal } from 'react-dom';
import { createUniqueIDFactory } from '@shopify/javascript-utilities/other';
import { ThemeContext } from '../../utilities/theme';
const getUniqueID = createUniqueIDFactory('portal-');
export class Portal extends React.PureComponent {
constructor() {
super(...arguments);
this.state = { isMounted: false };
this.portalId = this.props.idPrefix !== ''
? `${this.props.idPrefix}-${getUniqueID()}`
: getUniqueID();
}
componentDidMount() {
this.portalNode = document.createElement('div');
this.portalNode.setAttribute('data-portal-id', this.portalId);
if (this.context != null) {
/* eslint-disable babel/camelcase */
const { UNSTABLE_cssCustomProperties } = this.context;
if (UNSTABLE_cssCustomProperties != null) {
this.portalNode.setAttribute('style', UNSTABLE_cssCustomProperties);
}
else {
this.portalNode.removeAttribute('style');
}
}
document.body.appendChild(this.portalNode);
this.setState({ isMounted: true });
}
componentDidUpdate(_, prevState) {
const { onPortalCreated = noop } = this.props;
if (this.context != null) {
const { UNSTABLE_cssCustomProperties } = this.context;
if (UNSTABLE_cssCustomProperties != null) {
this.portalNode.setAttribute('style', UNSTABLE_cssCustomProperties);
}
else {
this.portalNode.removeAttribute('style');
}
/* eslint-enable babel/camelcase */
}
if (!prevState.isMounted && this.state.isMounted) {
onPortalCreated();
}
}
componentWillUnmount() {
document.body.removeChild(this.portalNode);
}
render() {
return this.state.isMounted
? createPortal(this.props.children, this.portalNode)
: null;
}
}
Portal.defaultProps = { idPrefix: '' };
Portal.contextType = ThemeContext;
function noop() { }