UNPKG

@shopgate/engage

Version:
90 lines (86 loc) 2.95 kB
import React, { useMemo, useRef } from 'react'; import PropTypes from 'prop-types'; import { makeStyles } from '@shopgate/engage/styles'; import { useRoute, useThemeWidgets } from '@shopgate/engage/core/hooks'; import { PAGE_PREVIEW_PATTERN } from '@shopgate/engage/page/constants'; import { ConditionalWrapper } from '@shopgate/engage/components'; import WidgetsPreviewProvider from "./WidgetsPreviewProvider"; import Widget from "./Widget"; import Overlay from "./Overlay"; import { checkScheduled } from "./helpers"; import { usePreviewIframeCommunication } from "./hooks"; /** * @typedef {import('./types').WidgetDefinition} WidgetDefinition */ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const PLACEHOLDER_COMPONENT = '@shopgate/widgetsInternal/Placeholder'; const useStyles = makeStyles()({ preview: { '& *': { scrollbarWidth: 'thin' } } }); /** * The Widgets component renders a list of widgets. * @param {Object} props The component props. * @param {Array<WidgetDefinition>} props.widgets The list of widgets to render. * @returns {JSX.Element} */ const Widgets = ({ widgets: widgetsProp = [] }) => { const { classes, cx } = useStyles(); const { pattern } = useRoute(); const widgetsRef = useRef(null); const isPreview = pattern === PAGE_PREVIEW_PATTERN; const widgetComponents = useThemeWidgets('v2'); usePreviewIframeCommunication(isPreview); // Create sanitized widgets array that only includes widgets with valid components. const widgets = useMemo(() => { if (isPreview) { // All widgets are allowed in preview mode. return widgetsProp; } // Remove widgets that do not have a valid component. return widgetsProp.filter(widget => !!widgetComponents[widget.widgetConfigDefinitionCode] && checkScheduled({ from: widget?.visibility.scheduleStartDate, to: widget?.visibility.scheduleEndDate }).isActive); }, [isPreview, widgetComponents, widgetsProp]); if (!Array.isArray(widgets) || widgets.length === 0) { return null; } return /*#__PURE__*/_jsx(ConditionalWrapper, { condition: isPreview, wrapper: children => /*#__PURE__*/_jsxs(WidgetsPreviewProvider, { children: [children, /*#__PURE__*/_jsx(Overlay, { containerRef: widgetsRef })] }), children: /*#__PURE__*/_jsx("div", { className: cx('engage__widgets', { [classes.preview]: isPreview }), ref: widgetsRef, children: widgets.map(widget => { const component = widgetComponents[widget.widgetConfigDefinitionCode] || widgetComponents[PLACEHOLDER_COMPONENT]; return /*#__PURE__*/_jsx(Widget, { definition: widget, isPreview: isPreview, component: component, isCustomLegacyWidget: widget.isCustomLegacyWidget }, widget.code); }) }) }); }; Widgets.defaultProps = { widgets: null }; export default Widgets;