@shopgate/engage
Version:
Shopgate's ENGAGE library.
90 lines (86 loc) • 2.95 kB
JavaScript
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;