@shopgate/engage
Version:
Shopgate's ENGAGE library.
144 lines (140 loc) • 4.57 kB
JavaScript
import React, { Suspense, useCallback } from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@shopgate/engage/styles';
import { VisibilityOffIcon, TimeIcon, Loading } from '@shopgate/engage/components';
import { usePressHandler } from '@shopgate/engage/core/hooks';
import WidgetProvider from "./WidgetProvider";
import { dispatchWidgetPreviewEvent } from "./events";
import { useWidgetsPreview } from "./hooks";
import Tooltip from "./Tooltip";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const useStyles = makeStyles()((theme, {
marginTop,
marginLeft
}) => ({
root: {
position: 'relative'
},
widgetInfo: {
zIndex: 12,
position: 'absolute',
top: -marginTop + (theme.spacing(0.5) + 1),
left: -marginLeft + theme.spacing(0.5),
fontSize: 24,
padding: theme.spacing(0.5),
display: 'flex',
gap: theme.spacing(1),
background: '#fff',
borderRadius: 4,
border: '1px solid rgba(0, 0, 0, 0.23)',
':empty': {
display: 'none'
}
},
preview: {
cursor: 'pointer'
},
visibilityIcon: {
color: '#f44336'
},
scheduledIcon: {
color: '#347DD3'
},
scheduledIconExpired: {
color: '#f44336'
}
}));
/**
* @typedef {import('./types').WidgetDefinition} WidgetDefinition
*/
/**
* @typedef {import('./types').ScheduledStatus} ScheduledStatus
*/
/**
* The Widget component.
* @param {Object} props The component props.
* @param {React.ComponentType} props.component The widget component to render.
* @param {WidgetDefinition} props.definition The widget definition data.
* @param {boolean} props.isPreview Whether the widget is in preview mode.
* @param {boolean} props.isCustomLegacyWidget Whether the widget is a legacy custom widget provided
* by an extension that's configured via an HTML comment inside a HTML widget.
* @returns {JSX.Element}
*/
const Widget = ({
component: Component,
definition,
isPreview,
isCustomLegacyWidget
}) => {
const {
classes,
cx
} = useStyles({
marginTop: definition?.layout?.marginTop ?? 0,
marginBottom: definition?.layout?.marginBottom ?? 0,
marginLeft: definition?.layout?.marginLeft ?? 0,
marginRight: definition?.layout?.marginRight ?? 0
});
const {
setActiveWidget,
activeWidget
} = useWidgetsPreview();
// Handle clicks on the widget container in preview mode. Take care that highlighting only happens
// when the widget is not already active, otherwise it would be confusing when users want to
// interact with widget elements.
const handleInteraction = useCallback(() => {
setActiveWidget(definition.code, activeWidget !== definition.code);
dispatchWidgetPreviewEvent('widget-clicked', definition.code);
}, [activeWidget, definition.code, setActiveWidget]);
const handlers = usePressHandler(handleInteraction);
if (!Component) {
return null;
}
return /*#__PURE__*/_jsxs("section", {
id: `widget-code-${definition.code}`,
className: cx(classes.root, {
[classes.preview]: isPreview
}),
style: {
marginTop: definition?.layout?.marginTop,
marginBottom: definition?.layout?.marginBottom,
marginLeft: definition?.layout?.marginLeft,
marginRight: definition?.layout?.marginRight
},
"data-widget-name": definition.widgetConfigDefinitionCode,
...(isPreview && {
...handlers
}),
children: [isPreview && definition?.meta && /*#__PURE__*/_jsxs("div", {
className: classes.widgetInfo,
children: [definition.meta?.scheduled?.isScheduled && /*#__PURE__*/_jsx(Tooltip, {
text: definition.meta?.scheduled?.tooltip,
children: /*#__PURE__*/_jsx(TimeIcon, {
className: cx(classes.scheduledIcon, {
[classes.scheduledIconExpired]: definition.meta?.scheduled?.isExpired
})
})
}), definition.meta?.hidden?.isHidden && /*#__PURE__*/_jsx(Tooltip, {
text: definition.meta?.hidden?.tooltip,
children: /*#__PURE__*/_jsx(VisibilityOffIcon, {
className: classes.visibilityIcon
})
})]
}), /*#__PURE__*/_jsx(WidgetProvider, {
definition: definition,
isPreview: isPreview,
children: /*#__PURE__*/_jsx(Suspense, {
fallback: /*#__PURE__*/_jsx(Loading, {}),
children: /*#__PURE__*/_jsx(Component, {
...(isCustomLegacyWidget ? {
settings: definition.widgetConfig
} : {})
})
})
})]
});
};
Widget.defaultProps = {
isCustomLegacyWidget: false
};
export default Widget;