UNPKG

@shopgate/pwa-common

Version:

Common library for the Shopgate Connect PWA.

153 lines (147 loc) 4.21 kB
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose"; import React, { PureComponent, Suspense } from 'react'; import PropTypes from 'prop-types'; import { logger } from '@shopgate/pwa-core/helpers'; import Loading from "../Loading"; import portalCollection from "../../helpers/portals/portalCollection"; import { componentsConfig } from "../../helpers/config"; /** * The Portal component. */ import { jsx as _jsx } from "react/jsx-runtime"; let Portal = /*#__PURE__*/function (_PureComponent) { /** * Constructor. * @param {Object} props The component props. */ function Portal(_props) { var _this; _this = _PureComponent.call(this, _props) || this; /** * Returns the portal components. * @param {Object} props - The props to pass to the component. * @return {Array} */ _this.getRenderedComponents = props => { const { props: propsFromProps, ...reducedProps } = props; const componentProps = { ...propsFromProps, ...reducedProps }; return _this.components.map(({ PortalComponent, key }) => /*#__PURE__*/_jsx(Suspense, { fallback: /*#__PURE__*/_jsx(Loading, {}), children: /*#__PURE__*/_jsx(PortalComponent, { ...componentProps }) }, key)); }; /** * Returns the portal components. * @param {string} name Name of the portal position * @return {Array} */ _this.getPortalComponents = name => { const components = []; const portals = portalCollection.getPortals(); if (!portals) { return components; } let config = portalCollection.getConfig(); if (!config) { config = componentsConfig.portals; } // Loop over the portal keys. Object.keys(config).forEach((key, index) => { const { target: sourceTarget } = config[key]; const portalTarget = Array.isArray(sourceTarget) ? sourceTarget : [sourceTarget]; if (portalTarget.length === 0) { return; } portalTarget.forEach(target => { // Stop if there is no key that matches the given name (prop). if (target !== name) { return; } const PortalComponent = portals[key]; // Check that the component is valid. if (PortalComponent) { const componentKey = `${key}-${index}`; components.push({ key: componentKey, PortalComponent }); } }); }); return components; }; _this.state = { hasError: false }; _this.components = _this.getPortalComponents(_props.name); return _this; } /** * Catches errors. * @param {Error} error The caught error. * @param {Object} info The stacktrace info. */ _inheritsLoose(Portal, _PureComponent); var _proto = Portal.prototype; _proto.componentDidCatch = function componentDidCatch(error, info) { this.setState({ hasError: true }); logger.error(error, info); }; /** * Renders the component. * @return {JSX} */ _proto.render = function render() { const { children } = this.props; const { hasError } = this.state; const renderedComponents = this.getRenderedComponents(this.props); const hasComponents = renderedComponents.length > 0; /** * Render nothing if there are no children, matching components * via name or an error occurred. */ if (hasError || !(hasComponents || children)) { return null; } /** * If there is a child component then we treat the match as an override * and we render the last match only. */ if (hasComponents) { /** * If there is a child component then we treat the match as an override * and we render the last match only. */ if (children) { return renderedComponents[renderedComponents.length - 1]; } return renderedComponents; } return children; }; return Portal; }(PureComponent); Portal.defaultProps = { children: null, props: null }; export default Portal;