UNPKG

@shopify/polaris

Version:

Shopify’s product component library

58 lines (57 loc) 2.14 kB
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() { }