@shopgate/engage 7.27.3-alpha.6 → 7.27.3-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/components/ResponsiveContainer/breakpoints.js +2 -2
  2. package/components/View/components/Content/style.js +1 -1
  3. package/components/View/context.js +1 -1
  4. package/core/constants/index.js +1 -7
  5. package/core/contexts/ThemeResourcesContext.d.ts +1 -10
  6. package/core/contexts/ThemeResourcesContext.js +1 -1
  7. package/core/helpers/scrollContainer.js +2 -2
  8. package/core/hocs/withThemeResources.js +1 -4
  9. package/core/hooks/events/index.js +1 -1
  10. package/core/hooks/useThemeResources.js +5 -6
  11. package/core/providers/ThemeResourcesProvider.js +5 -9
  12. package/locations/subscriptions.js +2 -2
  13. package/package.json +7 -9
  14. package/page/components/index.js +1 -1
  15. package/page/constants/index.js +1 -5
  16. package/page/index.js +2 -1
  17. package/page/selectors/index.js +2 -48
  18. package/product/components/index.js +1 -1
  19. package/styles/helpers/index.js +1 -1
  20. package/styles/helpers/setPageBackgroundColor.js +2 -2
  21. package/styles/index.js +1 -1
  22. package/tracking/selectors/cookieConsent.js +2 -2
  23. package/core/hooks/events/usePressHandler.js +0 -38
  24. package/page/action-creators/index.js +0 -22
  25. package/page/components/Widgets/Overlay.js +0 -51
  26. package/page/components/Widgets/Tooltip.js +0 -22
  27. package/page/components/Widgets/Widget.js +0 -15
  28. package/page/components/Widgets/WidgetContext.d.ts +0 -42
  29. package/page/components/Widgets/WidgetContext.js +0 -9
  30. package/page/components/Widgets/WidgetProvider.js +0 -8
  31. package/page/components/Widgets/Widgets.js +0 -11
  32. package/page/components/Widgets/WidgetsPreviewContext.js +0 -9
  33. package/page/components/Widgets/WidgetsPreviewProvider.js +0 -8
  34. package/page/components/Widgets/constants.js +0 -4
  35. package/page/components/Widgets/events.js +0 -23
  36. package/page/components/Widgets/helpers.js +0 -23
  37. package/page/components/Widgets/hooks.js +0 -69
  38. package/page/components/Widgets/index.js +0 -1
  39. package/page/components/Widgets/types.d.ts +0 -127
  40. package/page/constants/actionTypes.js +0 -1
  41. package/page/hooks/index.d.ts +0 -60
  42. package/page/hooks/index.js +0 -25
  43. package/page/reducers/index.js +0 -6
  44. package/page/subscriptions/index.js +0 -4
  45. package/page/widgets/Placeholder/Placeholder.js +0 -5
  46. package/page/widgets/Placeholder/hooks.js +0 -12
  47. package/page/widgets/Placeholder/index.js +0 -1
  48. package/page/widgets/ProductList/ProductList.js +0 -5
  49. package/page/widgets/ProductList/hooks.js +0 -25
  50. package/page/widgets/ProductList/index.js +0 -1
  51. package/page/widgets/index.js +0 -1
  52. package/page/widgets/widgets.json +0 -8
  53. package/product/components/ProductGrid/components/Item/components/ItemDetails/index.js +0 -8
  54. package/product/components/ProductGrid/components/Item/components/ItemDetails/spec.js +0 -1
  55. package/product/components/ProductGrid/components/Item/components/ItemDiscount/index.js +0 -5
  56. package/product/components/ProductGrid/components/Item/components/ItemFavoritesButton/index.js +0 -5
  57. package/product/components/ProductGrid/components/Item/components/ItemFavoritesButton/spec.js +0 -1
  58. package/product/components/ProductGrid/components/Item/components/ItemImage/index.js +0 -5
  59. package/product/components/ProductGrid/components/Item/components/ItemImage/spec.js +0 -1
  60. package/product/components/ProductGrid/components/Item/components/ItemName/index.js +0 -5
  61. package/product/components/ProductGrid/components/Item/components/ItemName/spec.js +0 -1
  62. package/product/components/ProductGrid/components/Item/components/ItemPrice/index.js +0 -5
  63. package/product/components/ProductGrid/components/Item/components/ItemPrice/spec.js +0 -1
  64. package/product/components/ProductGrid/components/Item/index.js +0 -7
  65. package/product/components/ProductGrid/components/Iterator/index.js +0 -5
  66. package/product/components/ProductGrid/components/Layout/index.js +0 -5
  67. package/product/components/ProductGrid/index.js +0 -22
  68. package/product/components/ProductGrid/spec.js +0 -1
  69. package/styles/helpers/color.js +0 -23
  70. package/styles/index.d.ts +0 -17
  71. package/styles/theme/createTheme/createBreakpoints.d.ts +0 -114
  72. package/styles/theme/createTheme/createBreakpoints.js +0 -41
  73. package/styles/theme/createTheme/createSpacing.d.ts +0 -23
  74. package/styles/theme/createTheme/createSpacing.js +0 -14
  75. package/styles/theme/createTheme/index.d.ts +0 -19
  76. package/styles/theme/createTheme/index.js +0 -5
  77. package/styles/theme/createTheme/transitions.d.ts +0 -100
  78. package/styles/theme/createTheme/transitions.js +0 -26
  79. package/styles/theme/createTheme/zIndex.d.ts +0 -12
  80. package/styles/theme/createTheme/zIndex.js +0 -3
  81. package/styles/theme/hooks/index.d.ts +0 -4
  82. package/styles/theme/hooks/index.js +0 -1
  83. package/styles/theme/hooks/useActiveBreakpoint.d.ts +0 -18
  84. package/styles/theme/hooks/useActiveBreakpoint.js +0 -4
  85. package/styles/theme/hooks/useMediaQuery.d.ts +0 -33
  86. package/styles/theme/hooks/useMediaQuery.js +0 -20
  87. package/styles/theme/hooks/useResponsiveValue.d.ts +0 -27
  88. package/styles/theme/hooks/useResponsiveValue.js +0 -4
  89. package/styles/theme/hooks/useTheme.d.ts +0 -8
  90. package/styles/theme/hooks/useTheme.js +0 -4
  91. package/styles/theme/index.d.ts +0 -8
  92. package/styles/theme/index.js +0 -1
  93. package/styles/theme/providers/ActiveBreakpointProvider.d.ts +0 -21
  94. package/styles/theme/providers/ActiveBreakpointProvider.js +0 -13
  95. package/styles/theme/providers/ThemeProvider.d.ts +0 -18
  96. package/styles/theme/providers/ThemeProvider.js +0 -7
  97. package/styles/tss/index.js +0 -3
@@ -1,42 +0,0 @@
1
- import { type Context } from 'react';
2
- import {
3
- type WidgetDefinitionLayout,
4
- type WidgetDefinitionVisibility,
5
- type WidgetDefinition,
6
- } from './types'
7
-
8
- export { WidgetDefinition } from './types';
9
-
10
- export interface WidgetContextType<C = Record<string, any>> {
11
- /**
12
- * The unique code of the widget instance
13
- */
14
- code: string;
15
- /**
16
- * The name of the widget
17
- */
18
- name: string;
19
- /**
20
- * The widget configuration
21
- */
22
- config: C;
23
- /**
24
- * The widget layout settings
25
- */
26
- layout: WidgetDefinitionLayout;
27
- /**
28
- * The widget visibility settings
29
- */
30
- visibility: WidgetDefinitionVisibility;
31
- /**
32
- * Whether the widget is rendered in preview mode
33
- */
34
- isPreview: boolean;
35
- }
36
-
37
- /**
38
- * React context for widgets.
39
- */
40
- declare const WidgetContext: Context<WidgetContextType>;
41
-
42
- export default WidgetContext;
@@ -1,9 +0,0 @@
1
- import{createContext}from'react';/**
2
- * @typedef {import('./Widgets.jsx').WidgetDefinition} WidgetDefinition
3
- */ /**
4
- * @typedef {Object} WidgetContextType
5
- * @property {WidgetDefinition['code']} code The unique widget code.
6
- * @property {WidgetDefinition['widgetConfig']} config The widget configuration.
7
- * @property {WidgetDefinition['layout']} layout The widget layout settings.
8
- * @property {WidgetDefinition['visibility']} visibility The widget visibility settings.
9
- */ /** @type {React.Context<WidgetContextType>} */export var WidgetContext=createContext({});
@@ -1,8 +0,0 @@
1
- import React,{useMemo}from'react';import PropTypes from'prop-types';import{WidgetContext}from"./WidgetContext";/** @typedef {import('./WidgetContext').WidgetContextType} WidgetContextType */ /** @typedef {import('./WidgetContext').WidgetDefinition} WidgetDefinition */ /**
2
- * The WidgetProvider component provides the context for a single widget.
3
- * @param {Object} props The component props.
4
- * @param {WidgetDefinition} props.definition The widget definition data.
5
- * @param {boolean} props.isPreview Whether the widget is in preview mode.
6
- * @param {React.ReactNode} props.children The child components to render.
7
- * @returns {JSX.Element}
8
- */var WidgetProvider=function WidgetProvider(_ref){var children=_ref.children,definition=_ref.definition,isPreview=_ref.isPreview;/** @type {WidgetContextType} */var value=useMemo(function(){var widgetConfig=definition.widgetConfig,layout=definition.layout,visibility=definition.visibility,code=definition.code,widgetConfigDefinitionCode=definition.widgetConfigDefinitionCode;return{code:code,name:widgetConfigDefinitionCode,config:widgetConfig,layout:layout,visibility:visibility,isPreview:isPreview};},[definition,isPreview]);return React.createElement(WidgetContext.Provider,{value:value},children);};export default WidgetProvider;
@@ -1,11 +0,0 @@
1
- function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}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{usePreviewIframeCommunication}from"./hooks";/**
2
- * @typedef {import('./types').WidgetDefinition} WidgetDefinition
3
- */var PLACEHOLDER_COMPONENT='@shopgate/widgetsInternal/Placeholder';var useStyles=makeStyles()({preview:{'& *':{scrollbarWidth:'thin'}}});/**
4
- * The Widgets component renders a list of widgets.
5
- * @param {Object} props The component props.
6
- * @param {Array<WidgetDefinition>} props.widgets The list of widgets to render.
7
- * @returns {JSX.Element}
8
- */var Widgets=function Widgets(_ref){var _ref$widgets=_ref.widgets,widgetsProp=_ref$widgets===void 0?[]:_ref$widgets;var _useStyles=useStyles(),classes=_useStyles.classes,cx=_useStyles.cx;var _useRoute=useRoute(),pattern=_useRoute.pattern;var widgetsRef=useRef(null);var isPreview=pattern===PAGE_PREVIEW_PATTERN;var widgetComponents=useThemeWidgets('v2');usePreviewIframeCommunication(isPreview);// Create sanitized widgets array that only includes widgets with valid components.
9
- var widgets=useMemo(function(){if(isPreview){// All widgets are allowed in preview mode.
10
- return widgetsProp;}// Remove widgets that do not have a valid component.
11
- return widgetsProp.filter(function(widget){return!!widgetComponents[widget.widgetConfigDefinitionCode];});},[isPreview,widgetComponents,widgetsProp]);if(!Array.isArray(widgets)||widgets.length===0){return null;}return React.createElement(ConditionalWrapper,{condition:isPreview,wrapper:function wrapper(children){return React.createElement(WidgetsPreviewProvider,null,children,React.createElement(Overlay,{containerRef:widgetsRef}));}},React.createElement("div",{className:cx('engage__widgets',_defineProperty({},classes.preview,isPreview)),ref:widgetsRef},widgets.map(function(widget){var component=widgetComponents[widget.widgetConfigDefinitionCode]||widgetComponents[PLACEHOLDER_COMPONENT];return React.createElement(Widget,{key:widget.code,definition:widget,isPreview:isPreview,component:component});})));};Widgets.defaultProps={widgets:null};export default Widgets;
@@ -1,9 +0,0 @@
1
- import _noop from"lodash/noop";import{createContext}from'react';/**
2
- * @callback SetActiveWidget
3
- * @param {string} code The code of the widget to set as active.
4
- * @param {boolean} [highlight=false] Whether to highlight the widget after setting it as active.
5
- */ /**
6
- * @typedef {Object} WidgetsPreviewContextType
7
- * @property {string} activeWidget The code of the currently active widget.
8
- * @property {SetActiveWidget} setActiveWidget A function to set the active widget code
9
- */ /** @type {React.Context<WidgetsPreviewContextType>} */export var WidgetsPreviewContext=createContext({activeWidget:null,setActiveWidget:_noop});
@@ -1,8 +0,0 @@
1
- function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}import React,{useMemo,useState,useCallback}from'react';import PropTypes from'prop-types';import{useWidgetPreviewEvent,dispatchWidgetPreviewEvent}from"./events";import{WidgetsPreviewContext}from"./WidgetsPreviewContext";/**
2
- * The WidgetsPreviewProvider component is used by the Widgets component when it's rendered
3
- * in preview mode. It provides functionality for the Widget component that's needed when
4
- * the widgets are rendered in the preview iframe.
5
- * @param {Object} props The component props.
6
- * @param {React.ReactNode} props.children The child components to render.
7
- * @returns {JSX.Element}
8
- */var WidgetsPreviewProvider=function WidgetsPreviewProvider(_ref){var children=_ref.children;var _useState=useState(null),_useState2=_slicedToArray(_useState,2),activeWidget=_useState2[0],setActiveWidget=_useState2[1];useWidgetPreviewEvent('set-active-widget-id',function(e){setActiveWidget(e.detail.widgetCode);});var handleSetActiveWidget=useCallback(function(code){var highlight=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;setActiveWidget(code);if(highlight){dispatchWidgetPreviewEvent('highlight-widget',code);}},[]);var value=useMemo(function(){return{activeWidget:activeWidget,setActiveWidget:handleSetActiveWidget};},[activeWidget,handleSetActiveWidget]);return React.createElement(WidgetsPreviewContext.Provider,{value:value},children);};export default WidgetsPreviewProvider;
@@ -1,4 +0,0 @@
1
- /**
2
- * List of allowed origins for cms page preview iFrame communication.
3
- */export var ALLOWED_PAGE_PREVIEW_ORIGINS=['https://next.admin.shopgatedev.com','https://next.admin.shopgatepg.com','https://next.admin.shopgate.com','https://next.us.admin.shopgate.com','http://localhost:1337'];// Whether to consider vertical margins when calculating the overlay position.
4
- export var CONSIDER_CONTAINER_MARGINS_ON_SCROLL_DEFAULT=false;
@@ -1,23 +0,0 @@
1
- import{useEffect}from'react';/**
2
- * @typedef {"highlight-widget"|"widget-clicked"|"set-active-widget-id"} WidgetPreviewEventName
3
- */ /**
4
- * @typedef {Object} WidgetPreviewEventDetail
5
- * @property {string} widgetCode The code of the widget related to the event.
6
- * @property {any} [payload] Optional payload data related to the event.
7
- */ /**
8
- * @callback WidgetPreviewEventHandler
9
- * @param {CustomEvent<WidgetPreviewEventDetail>} event The custom event dispatched for the widget
10
- * preview.
11
- */ /**
12
- * Hook to listen for widget preview events.
13
- * These events are dispatched in the context of iFrame communication at the widget preview.
14
- * @param {WidgetPreviewEventName} eventName Name of the listened event
15
- * @param {WidgetPreviewEventHandler} handler A callback function to handle the event
16
- */export var useWidgetPreviewEvent=function useWidgetPreviewEvent(eventName,handler){useEffect(function(){window.addEventListener("widget-preview-".concat(eventName),handler);return function(){window.removeEventListener("widget-preview-".concat(eventName),handler);};},[eventName,handler]);};/**
17
- * Dispatches widget preview related events.
18
- * Used to trigger iFrame postMessage events to the parent window or to react on incoming
19
- * postMessage events from the parent window.
20
- * @param {WidgetPreviewEventName} eventName Name of the event to dispatch
21
- * @param {string} widgetCode Code of the widget to dispatch the event for
22
- * @param {Object} [payload] Optional payload to include with the event
23
- */export var dispatchWidgetPreviewEvent=function dispatchWidgetPreviewEvent(eventName,widgetCode){var payload=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var event=new CustomEvent("widget-preview-".concat(eventName),{detail:{widgetCode:widgetCode,payload:payload}});window.dispatchEvent(event);};
@@ -1,23 +0,0 @@
1
- import{PAGE_PREVIEW_PATTERN}from'@shopgate/engage/page/constants';/**
2
- * Retrieves the scroll container for the current page. Depending on the PWA mode this can be
3
- * a scrollable article element or the window.
4
- * @returns {HTMLElement|null}
5
- */export var getScrollContainer=function getScrollContainer(){return document.querySelector(".route__".concat(PAGE_PREVIEW_PATTERN.replace(/^\/+/,'')));};/**
6
- * @typedef {Object} ScheduledParams
7
- * @param {string} [from] The start date of the scheduling in ISO format.
8
- * @param {string} [to] The end date of the scheduling in ISO format.
9
- * @param {number} [timezoneOffset] The timezone offset in minutes. If not provided, the local
10
- * timezone offset will be used.
11
- */ /**
12
- * @typedef {Object} ScheduledStatus
13
- * @param {boolean} isScheduled Indicates if the widget is scheduled.
14
- * @param {boolean} isActive Indicates if the widget is currently active within the
15
- * scheduled time frame.
16
- * @param {boolean} isExpired Indicates if the scheduled time frame has expired.
17
- */ /**
18
- * Retrieves the scheduling status of a widget based on the provided parameters.
19
- * @param {ScheduledParams} params The parameters for the function.
20
- * @returns {ScheduledStatus} An object containing the scheduling status.
21
- */export function checkScheduled(){var _ref=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{},from=_ref.from,to=_ref.to,timezoneOffset=_ref.timezoneOffset;var now=new Date();// Convert current time to provided or local timezone
22
- var localOffset=timezoneOffset!==null&&timezoneOffset!==void 0?timezoneOffset:-now.getTimezoneOffset();// in minutes
23
- var offsetMs=localOffset*60*1000;var localNow=new Date(now.getTime()+offsetMs);var fromDate=from?new Date(from):null;var toDate=to?new Date(to):null;var isActive=(!fromDate||localNow>=new Date(fromDate.getTime()+offsetMs))&&(!toDate||localNow<=new Date(toDate.getTime()+offsetMs));var isExpired=!!toDate&&localNow>new Date(toDate.getTime()+offsetMs);var isScheduled=!!fromDate||!!toDate;return{isScheduled:isScheduled,isActive:isActive,isExpired:isExpired};}
@@ -1,69 +0,0 @@
1
- import{useEffect,useCallback,useRef,useContext,useMemo}from'react';import{logger}from'@shopgate/engage/core/helpers';import{useDispatch}from'react-redux';import{useRoute}from'@shopgate/engage/core/hooks';import{receivePageConfigV2}from'@shopgate/engage/page/action-creators';import{PAGE_PREVIEW_SLUG}from'@shopgate/engage/page/constants';import{ALLOWED_PAGE_PREVIEW_ORIGINS,CONSIDER_CONTAINER_MARGINS_ON_SCROLL_DEFAULT}from"./constants";import{getScrollContainer}from"./helpers";import{WidgetsPreviewContext}from"./WidgetsPreviewContext";import{dispatchWidgetPreviewEvent,useWidgetPreviewEvent}from"./events";/**
2
- * @typedef {Object} MessageData
3
- * @property {string} type Identifier for the kind of message
4
- * @property {any} [payload] Optional data payload for this message
5
- */ /**
6
- * @typedef {Object} IframeMessengerResult
7
- * @property {function(MessageData, string=): void} sendToParent
8
- * - Send data up to window.parent. If targetOrigin is omitted, uses the
9
- * most recently seen origin (from an incoming message). If none seen yet,
10
- * falls back to parentOrigins[0] or "*".
11
- */ /**
12
- * Hook for postMessage communication when your component is inside an iframe.
13
- *
14
- * Listens on window for "message" events from any origin in parentOrigins,
15
- * and only calls onMessage(data, rawEvent) if both origin and source match.
16
- *
17
- * @param {function(MessageData, any): void} onMessage
18
- * Callback invoked when a trusted message arrives. Receives data and the
19
- * raw event (so you can inspect origin, source, etc.).
20
- * @param {string[]} parentOrigins
21
- * Array of allowed parent origin strings (e.g.
22
- * ['https://a.example.com','https://b.example.com']).
23
- * @returns {IframeMessengerResult}
24
- * An object with a single method:
25
- * • sendToParent(data, [targetOrigin]): void
26
- * – Posts data up to window.parent. By default it uses the most recently
27
- * seen origin (from an incoming message). If none, uses parentOrigins[0].
28
- */function useIframeMessenger(onMessage,parentOrigins){// Keep a ref to the latest onMessage callback so the listener always has it.
29
- var onMessageRef=useRef(onMessage);useEffect(function(){onMessageRef.current=onMessage;},[onMessage]);// Keep track of the last allowed origin we heard from
30
- var lastOriginRef=useRef(null);/**
31
- * Send a message up to the parent window.
32
- * @param {MessageData} data - The data object to post.
33
- * @param {string} [targetOrigin]
34
- * Optional override for the origin to post to. Must be one of
35
- * parentOrigins. If omitted, uses the last seen origin (lastOriginRef),
36
- * or parentOrigins[0], or "*" if array is empty.
37
- */var sendToParent=useCallback(function(data,targetOrigin){// Determine which origin to use: explicit, then last seen, then first, then "*".
38
- var originToUse=typeof targetOrigin==='string'?targetOrigin:lastOriginRef.current||new URL(document.referrer).origin||parentOrigins[0]||'*';if(!originToUse){logger.warn('useIframeMessenger: no targetOrigin available. '+'Provide parentOrigins or pass targetOrigin.');return;}window.parent.postMessage(data,originToUse);},[parentOrigins]);// Attach / detach the "message" listener.
39
- useEffect(function(){/**
40
- * Handler for incoming postMessage events.
41
- * @param {any} rawEvent – The original MessageEvent object.
42
- */function handler(rawEvent){// Only proceed if the origin is in our whitelist.
43
- if(!parentOrigins.includes(rawEvent.origin))return;// Ensure the message actually came from window.parent.
44
- if(rawEvent.source!==window.parent)return;// Record this origin as most recently seen.
45
- lastOriginRef.current=rawEvent.origin;// Forward the event.data and the raw event to the callback.
46
- onMessageRef.current(rawEvent.data,rawEvent);}window.addEventListener('message',handler);return function(){window.removeEventListener('message',handler);};},[parentOrigins,sendToParent]);return{sendToParent:sendToParent};}/**
47
- * Hook to handle communication with the parent window in a page preview iframe.
48
- * @param {boolean} isActive Whether the preview communication is active.
49
- */export var usePreviewIframeCommunication=function usePreviewIframeCommunication(){var isActive=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;var dispatch=useDispatch();var _useRoute=useRoute(),considerContainerMarginsOnScroll=_useRoute.query.considerContainerMarginsOnScroll;// Detect if container margins should be considered at scroll to widget.
50
- var considerVerticalMargins=useMemo(function(){if(!considerContainerMarginsOnScroll){return CONSIDER_CONTAINER_MARGINS_ON_SCROLL_DEFAULT;}return considerContainerMarginsOnScroll==='true';},[considerContainerMarginsOnScroll]);var _useIframeMessenger=useIframeMessenger(function(data){var _data$payload;if(data.type==='receivePageConfig'){// Page preview config received from the parent window.
51
- dispatch(receivePageConfigV2({type:'cms',slug:PAGE_PREVIEW_SLUG,data:data.payload}));}else if(data.type==='scrollToWidget'&&((_data$payload=data.payload)===null||_data$payload===void 0?void 0:_data$payload.widgetCode)){// Parent window requested to scroll to a specific widget.
52
- var scrollContainer=getScrollContainer();var target=scrollContainer.querySelector("#widget-code-".concat(data.payload.widgetCode));if(scrollContainer&&target){var marginTop=0;if(considerVerticalMargins){var styles=window.getComputedStyle(target);marginTop=parseFloat(styles.marginTop);}var containerTop=scrollContainer.getBoundingClientRect().top;var targetTop=target.getBoundingClientRect().top;var scrollOffset=targetTop-containerTop+scrollContainer.scrollTop-marginTop;var maxScrollTop=scrollContainer.scrollHeight-scrollContainer.clientHeight;var actualScrollTop=Math.min(scrollOffset,maxScrollTop);// Register the target element as the active widget.
53
- dispatchWidgetPreviewEvent('set-active-widget-id',data.payload.widgetCode);/**
54
- * Callback to highlight the widget after scrolling.
55
- */var highlightWidget=function highlightWidget(){dispatchWidgetPreviewEvent('highlight-widget',data.payload.widgetCode);};// Add listener to onScrollEnd if available, otherwise use scroll event.
56
- if('onscrollend'in scrollContainer){/**
57
- * Callback for the scrollend event.
58
- */var onEnded=function onEnded(){scrollContainer.removeEventListener('scrollend',onEnded);highlightWidget();};scrollContainer.addEventListener('scrollend',onEnded,{once:true});scrollContainer.scrollTo({top:actualScrollTop,behavior:'smooth'});return;}// Fallback: listen for scroll events until scrollTop ≈ actualScrollTop
59
- /**
60
- * Callback for the scroll event.
61
- */var onScroll=function onScroll(){// Allow a 1 px leeway for subpixel rendering
62
- if(Math.abs(scrollContainer.scrollTop-actualScrollTop)<1){scrollContainer.removeEventListener('scroll',onScroll);highlightWidget();}};scrollContainer.addEventListener('scroll',onScroll);scrollContainer.scrollTo({top:actualScrollTop,behavior:'smooth'});}}},ALLOWED_PAGE_PREVIEW_ORIGINS),sendToParent=_useIframeMessenger.sendToParent;useWidgetPreviewEvent('widget-clicked',function(e){if(!isActive){return;}sendToParent({type:'widgetClicked',payload:{widgetCode:e.detail.widgetCode}});});};/**
63
- * @typedef {import('./WidgetsPreviewContext.js').WidgetsPreviewContextType}
64
- * WidgetsPreviewContextType
65
- */ /**
66
- * The useWidgetsPreview hook provides access to the context that is wrapped around the Widgets
67
- * component when it's rendered in preview mode.
68
- * @returns {WidgetsPreviewContextType} The widget context.
69
- */export var useWidgetsPreview=function useWidgetsPreview(){return useContext(WidgetsPreviewContext);};
@@ -1 +0,0 @@
1
- export{default}from"./Widgets";export{WidgetContext}from"./WidgetContext";
@@ -1,127 +0,0 @@
1
- /**
2
- * Visibility settings for a widget.
3
- */
4
- export interface WidgetDefinitionVisibility {
5
- /**
6
- * Whether the widget is hidden.
7
- */
8
- isHidden: boolean;
9
- /**
10
- * Start date for scheduled widgets.
11
- */
12
- scheduleStartDate: string;
13
- /**
14
- * End date for scheduled widgets.
15
- */
16
- scheduleEndDate: string
17
- }
18
-
19
- /**
20
- * Layout settings for a widget.
21
- */
22
- export interface WidgetDefinitionLayout {
23
- /**
24
- * Top margin for the widget.
25
- */
26
- marginTop: number;
27
- /**
28
- * Bottom margin for the widget.
29
- */
30
- marginBottom: number;
31
- /**
32
- * Left margin for the widget.
33
- */
34
- marginLeft: number;
35
- /**
36
- * Right margin for the widget.
37
- */
38
- marginRight: number;
39
- }
40
-
41
- /**
42
- * Definition of a API widget
43
- */
44
- export interface WidgetDefinition {
45
- /**
46
- * Unique code for the widget.
47
- */
48
- code: string;
49
- /**
50
- * Name of the widget
51
- */
52
- widgetConfigDefinitionCode: string;
53
- /**
54
- * Individual configuration for the widget.
55
- */
56
- widgetConfig: Record<string, any>;
57
- /**
58
- * Visibility settings for the widget.
59
- */
60
- visibility: WidgetDefinitionVisibility;
61
- /**
62
- * Layout settings for the widget.
63
- */
64
- layout: WidgetDefinitionLayout;
65
- /**
66
- * Optional metadata for the widget (only available in preview mode)
67
- */
68
- meta?: {
69
- /**
70
- * Hidden state related data
71
- */
72
- hidden: {
73
- /**
74
- * Whether the widget is hidden.
75
- */
76
- isHidden: boolean;
77
- /**
78
- * Tooltip text for hidden related UI elements.
79
- */
80
- tooltip: string;
81
- /**
82
- * Label text for hidden related UI elements.
83
- */
84
- label: string;
85
- };
86
- /**
87
- * Scheduled state related data
88
- */
89
- scheduled: {
90
- /**
91
- * Indicates if the widget is scheduled.
92
- */
93
- isScheduled: boolean;
94
- /**
95
- * Indicates that the widget schedule time frame is currently active.
96
- */
97
- isActive: boolean;
98
- /**
99
- * Indicates if the scheduled time frame has expired
100
- */
101
- isExpired: boolean;
102
- /**
103
- * Tooltip text for schedule related UI elements.
104
- */
105
- tooltip: string;
106
- /**
107
- * Label text for schedule related UI elements.
108
- */
109
- label: string;
110
- };
111
- }
112
- }
113
-
114
- export interface ScheduledStatus {
115
- /**
116
- * Indicates if the widget is scheduled.
117
- */
118
- isScheduled: boolean;
119
- /**
120
- * Indicates if the widget is currently hidden based on the scheduling
121
- */
122
- isHidden: boolean;
123
- /**
124
- * Indicates if the scheduled time frame has expired.
125
- */
126
- isExpired: boolean;
127
- }
@@ -1 +0,0 @@
1
- export var REQUEST_PAGE_CONFIG_V2='REQUEST_PAGE_CONFIG_V2';export var RECEIVE_PAGE_CONFIG_V2='RECEIVE_PAGE_CONFIG_V2';export var ERROR_PAGE_CONFIG_V2='ERROR_PAGE_CONFIG_V2';
@@ -1,60 +0,0 @@
1
- import type { WidgetContextType } from '../components/Widgets/WidgetContext';
2
-
3
- /**
4
- * The useWidget hook provides access to the context that is wrapped around a widget.
5
- * @returns The widget context.
6
- */
7
- export declare function useWidget<C = Record<string, any>>(): WidgetContextType<C>
8
-
9
-
10
- export type UseWidgetProductsOptions = {
11
- /**
12
- * The search value to use for the product search
13
- */
14
- value: string;
15
- /**
16
- * The type of product search to perform.
17
- */
18
- type: 'searchTerm' | 'itemNumbers' | 'brand' | 'category' | 'highlights';
19
- /**
20
- * The number of products to return per page.
21
- * @default 32
22
- */
23
- limit?: number;
24
- /**
25
- * Sort order for the products
26
- * @default 'relevance'
27
- */
28
- sort?: 'relevance' | 'priceAsc' | 'priceDesc' | 'nameAsc' | 'nameDesc';
29
- };
30
-
31
- export type UseWidgetProductsResult = {
32
- /**
33
- * Function to fetch the next page of products.
34
- */
35
- fetchNext: () => void;
36
- /**
37
- * Whether there are more products to fetch.
38
- */
39
- hasNext: boolean;
40
- /**
41
- * Whether the products are currently being fetched.
42
- */
43
- isFetching: boolean;
44
- /**
45
- * Number of products available in the current result set.
46
- */
47
- totalResultCount: number;
48
- /**
49
- * Array of product results.
50
- */
51
- results: Object[];
52
- }
53
-
54
- /**
55
- * The useWidgetProducts hook provides an easy way to retrieve products based on a search term or
56
- * other criteria.
57
- */
58
- export declare function useWidgetProducts(
59
- options: UseWidgetProductsOptions
60
- ): UseWidgetProductsResult;
@@ -1,25 +0,0 @@
1
- import _regeneratorRuntime from"@babel/runtime/regenerator";function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{Promise.resolve(value).then(_next,_throw);}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value);}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err);}_next(undefined);});};}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import{useContext,useMemo,useCallback,useEffect,useState}from'react';import{useSelector,useDispatch}from'react-redux';import{WidgetContext}from'@shopgate/engage/page/components/Widgets';import{showInventoryInLists}from'@shopgate/engage/locations/helpers';import{ITEMS_PER_LOAD}from'@shopgate/engage/core/constants';import{transformDisplayOptions}from'@shopgate/engage/core/helpers';import{fetchProductsByQuery}from'@shopgate/engage/product';import{makeGetWidgetProducts}from"../selectors";/**
2
- * @typedef {import('../components/Widgets/WidgetContext').WidgetContextType WidgetContextType}
3
- */ /**
4
- * @typedef {import('./index').UseWidgetProductsOptions} UseWidgetProductsOptions
5
- */ /**
6
- * @typedef {import('./index').UseWidgetProductsResult} UseWidgetProductsResult
7
- */ /**
8
- * The useWidget hook provides access to the context that is wrapped around a widget.
9
- * @returns {WidgetContextType} The widget context.
10
- */export var useWidget=function useWidget(){return useContext(WidgetContext);};var REQUEST_TYPE_MAPPING={highlights:1,searchTerm:2,brand:3,itemNumbers:4,category:5};/**
11
- * Retrieves the products for the current widget.
12
- * @param {UseWidgetProductsOptions} options Hook options
13
- * @returns {UseWidgetProductsResult} The products and a function to fetch more products.
14
- */export var useWidgetProducts=function useWidgetProducts(){var options=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var type=options.type,value=options.value,_options$limit=options.limit,limit=_options$limit===void 0?ITEMS_PER_LOAD:_options$limit,_options$sort=options.sort,sort=_options$sort===void 0?'relevance':_options$sort;var dispatch=useDispatch();var _useWidget=useWidget(),_useWidget$code=_useWidget.code,code=_useWidget$code===void 0?"".concat(type,"_").concat(value,"_").concat(limit,"_").concat(sort):_useWidget$code;// ###### Products selection ######
15
- var showInventoryInProductLists=useSelector(showInventoryInLists);var selectorOptions=useMemo(function(){return _extends({sort:transformDisplayOptions(sort),value:value,useDefaultRequestForProductIds:true},showInventoryInProductLists&&{useDefaultRequestForProductIds:true});},[showInventoryInProductLists,sort,value]);var getWidgetProducts=useMemo(function(){return makeGetWidgetProducts(type,selectorOptions,code);},[code,selectorOptions,type]);var widgetProducts=useSelector(getWidgetProducts);// ###### Products request ######
16
- var _useState=useState(true),_useState2=_slicedToArray(_useState,2),hasNext=_useState2[0],setHasNext=_useState2[1];var _useState3=useState(0),_useState4=_slicedToArray(_useState3,2),offset=_useState4[0],setOffset=_useState4[1];var isFetching=widgetProducts.isFetching;var baseRequestOptions=useMemo(function(){return _extends({limit:limit,sort:transformDisplayOptions(sort),useDefaultRequestForProductIds:true},showInventoryInProductLists&&{useDefaultRequestForProductIds:true});},[limit,showInventoryInProductLists,sort]);/**
17
- * Callback to dispatch the initial fetch request for products when the hook mounts,
18
- * or when its parameters change.
19
- */var fetchInitial=useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(){var initialOptions,result;return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:if(value){_context.next=3;break;}setHasNext(false);return _context.abrupt("return");case 3:// Initial request needs to start at offset 0
20
- initialOptions=_extends({},baseRequestOptions,{offset:0});_context.next=6;return dispatch(fetchProductsByQuery(REQUEST_TYPE_MAPPING[type],value,initialOptions,code));case 6:result=_context.sent;// Re-initialize offset and hasNext based on the result
21
- setOffset(limit);setHasNext(result.totalProductCount>limit);case 9:case"end":return _context.stop();}},_callee);})),[code,dispatch,type,value,limit,baseRequestOptions]);// Effect to trigger the initial fetch when the component mounts or the parameters change.
22
- useEffect(function(){fetchInitial();},[fetchInitial]);/**
23
- * Callback to fetch the next chunk of products when e.g. users interacted with a "Load More"
24
- * button.
25
- */var fetchNext=useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(){var nextOptions,result;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:if(!(!hasNext||isFetching||!value)){_context2.next=2;break;}return _context2.abrupt("return");case 2:nextOptions=_extends({},baseRequestOptions,{offset:offset});_context2.next=5;return dispatch(fetchProductsByQuery(REQUEST_TYPE_MAPPING[type],value,nextOptions,code));case 5:result=_context2.sent;setOffset(offset+limit);setHasNext(result.totalProductCount>offset+limit);case 8:case"end":return _context2.stop();}},_callee2);})),[code,dispatch,hasNext,isFetching,value,offset,limit,baseRequestOptions,type]);return{fetchNext:fetchNext,hasNext:hasNext,isFetching:isFetching,results:widgetProducts.products.slice(0,offset),totalResultCount:widgetProducts.totalProductCount};};
@@ -1,6 +0,0 @@
1
- import{produce}from'immer';import{REQUEST_PAGE_CONFIG_V2,RECEIVE_PAGE_CONFIG_V2,ERROR_PAGE_CONFIG_V2,PAGE_STATE_LIFETIME}from"../constants";var defaultState={};/**
2
- * Stores state of the v2 implementation of pages.
3
- * @param {Object} [state={}] The current state.
4
- * @param {Object} action The action object.
5
- * @returns {Object} The new state.
6
- */export function pageV2(){var state=arguments.length>0&&arguments[0]!==undefined?arguments[0]:defaultState;var action=arguments.length>1?arguments[1]:undefined;/* eslint-disable no-param-reassign */var producer=produce(function(draft){switch(action.type){case REQUEST_PAGE_CONFIG_V2:{var pageType=action.pageType,pageSlug=action.pageSlug;draft[pageType]=draft[pageType]||{};draft[pageType][pageSlug]={data:null,isFetching:true,expires:0};break;}case RECEIVE_PAGE_CONFIG_V2:{var _pageType=action.pageType,_pageSlug=action.pageSlug,data=action.data;draft[_pageType]=draft[_pageType]||{};draft[_pageType][_pageSlug]={data:data,isFetching:false,expires:Date.now()+PAGE_STATE_LIFETIME};break;}case ERROR_PAGE_CONFIG_V2:{var _pageType2=action.pageType,_pageSlug2=action.pageSlug;draft[_pageType2]=draft[_pageType2]||{};draft[_pageType2][_pageSlug2]={data:null,isFetching:false};break;}default:break;}});/* eslint-enable no-param-reassign */return producer(state);}
@@ -1,4 +0,0 @@
1
- import{appWillStart$}from'@shopgate/engage/core/streams';/**
2
- * Page subscriptions.
3
- * @param {Function} subscribe The subscribe function.
4
- */export default function page(subscribe){subscribe(appWillStart$,function(){});}
@@ -1,5 +0,0 @@
1
- import React from'react';import{makeStyles}from'@shopgate/engage/styles';import{usePlaceholderWidget}from"./hooks";var useStyles=makeStyles()(function(theme){return{root:{padding:theme.spacing(2),minHeight:200},name:{fontSize:14},pre:{background:'#f7f9fc',border:'1px solid #dbdde2',borderRadius:8,color:'#000',fontSize:10,overflowY:'auto',padding:theme.spacing(1)}};});/**
2
- * The PlaceholderWidget component is used to display a placeholder for widget types that
3
- * are not implemented yet.
4
- * @returns {JSX.Element}
5
- */var PlaceholderWidget=function PlaceholderWidget(){var _useStyles=useStyles(),classes=_useStyles.classes;var _usePlaceholderWidget=usePlaceholderWidget(),code=_usePlaceholderWidget.code,name=_usePlaceholderWidget.name,config=_usePlaceholderWidget.config,layout=_usePlaceholderWidget.layout,visibility=_usePlaceholderWidget.visibility;return React.createElement("div",{className:classes.root},React.createElement("div",{className:classes.name},name),React.createElement("pre",{className:classes.pre},JSON.stringify({code:code,config:config,layout:layout,visibility:visibility},null,2)));};export default PlaceholderWidget;
@@ -1,12 +0,0 @@
1
- import{useWidget}from'@shopgate/engage/page/hooks';/**
2
- * @typedef {Object} PlaceholderWidgetConfig
3
- * @property {string} foo Example property for the widget configuration.
4
- * @property {number} bar Another example property for the widget configuration.
5
- */ /**
6
- * @typedef {ReturnType< typeof import('@shopgate/engage/page/hooks')
7
- * .useWidget<PlaceholderWidgetConfig> >} HookReturnType
8
- */ /**
9
- * Local example hook to demonstrate how to extend the useWidget hook with a custom type for
10
- * the widget configuration.
11
- * @returns {HookReturnType}
12
- */export var usePlaceholderWidget=function usePlaceholderWidget(){return useWidget();};
@@ -1 +0,0 @@
1
- export{default}from"./Placeholder";
@@ -1,5 +0,0 @@
1
- import React from'react';import{ActionButton,I18n}from'@shopgate/engage/components';import{ProductGrid}from'@shopgate/engage/product/components';import{useWidgetProducts}from'@shopgate/engage/page/hooks';import{makeStyles}from'@shopgate/engage/styles';import{useProductListWidget}from"./hooks";var useStyles=makeStyles()({root:{// Prevent that the ActionButton margin messes with the layout of the sibling widgets
2
- overflow:'hidden'},grid:{'&&':{marginTop:0}}});/**
3
- * The ProductListWidget is used to display product lists.
4
- * @returns {JSX.Element}
5
- */var ProductListWidget=function ProductListWidget(){var _useStyles=useStyles(),classes=_useStyles.classes;var _useProductListWidget=useProductListWidget(),productsSearchType=_useProductListWidget.productsSearchType,productsSearchValue=_useProductListWidget.productsSearchValue,sort=_useProductListWidget.sort,productCount=_useProductListWidget.productCount,showLoadMore=_useProductListWidget.showLoadMore,flags=_useProductListWidget.flags;var _useWidgetProducts=useWidgetProducts({type:productsSearchType,value:productsSearchValue,limit:productCount,sort:sort}),fetchNext=_useWidgetProducts.fetchNext,hasNext=_useWidgetProducts.hasNext,isFetching=_useWidgetProducts.isFetching,results=_useWidgetProducts.results;return React.createElement("div",{className:classes.root},React.createElement(ProductGrid,{products:results,flags:flags,scope:"widgets",infiniteLoad:false,className:classes.grid}),hasNext&&showLoadMore&&React.createElement(ActionButton,{loading:isFetching,onClick:fetchNext},React.createElement(I18n.Text,{string:"common.load_more"})));};export default ProductListWidget;
@@ -1,25 +0,0 @@
1
- import _camelCase from"lodash/camelCase";import{useMemo}from'react';import{useWidget}from'@shopgate/engage/page/hooks';/**
2
- * @typedef {Object} ProductListWidgetProducts
3
- * @property {"searchTerm" | "brand" | "category" | "itemNumbers"} productSelectorType Source type
4
- * for the product list.
5
- * @property {string} productsSearchTerm A search term to filter products by
6
- * @property {string} productsBrand A brand to filter products by
7
- * @property {string} productsCategory A category to filter products by
8
- * @property {string} productsItemNumbers A comma-separated list of item numbers to filter products
9
- * by
10
- */ /**
11
- * @typedef {Object} ProductListWidgetConfig
12
- * @property {ProductListWidgetProducts} products The products configuration for the widget.
13
- * @property {number} productCount The number of products to display in the widget
14
- * @property {"relevance" | "PriceDesc" | "PriceDesc"} sort Sort order for the products
15
- * @property {boolean} loadMoreButton Whether to display a "Load more" button
16
- * @property {boolean} showName Whether to display product names
17
- * @property {boolean} showPrice Whether to display product prices
18
- * @property {boolean} showRating Whether to display product ratings
19
- */ /**
20
- * @typedef {ReturnType< typeof import('@shopgate/engage/page/hooks')
21
- * .useWidget<ProductListWidgetConfig> >} UseWidgetReturnType
22
- */ // eslint-disable-next-line valid-jsdoc
23
- /**
24
- * Hook to access the Product List widget configuration.
25
- */export var useProductListWidget=function useProductListWidget(){/** @type {UseWidgetReturnType} */var _useWidget=useWidget(),config=_useWidget.config;var products=config.products,productCount=config.productCount,sort=config.sort,_config$loadMoreButto=config.loadMoreButton,loadMoreButton=_config$loadMoreButto===void 0?false:_config$loadMoreButto,_config$showName=config.showName,showName=_config$showName===void 0?false:_config$showName,_config$showPrice=config.showPrice,showPrice=_config$showPrice===void 0?false:_config$showPrice,_config$showRating=config.showRating,showRating=_config$showRating===void 0?false:_config$showRating;var productSelectorType=products.productSelectorType,productsBrand=products.productsBrand,productsCategory=products.productsCategory,productsItemNumbers=products.productsItemNumbers,productsSearchTerm=products.productsSearchTerm;var value=useMemo(function(){switch(productSelectorType){case'brand':return productsBrand;case'category':return productsCategory;case'itemNumbers':return productsItemNumbers.split(',').map(function(item){return item.trim();});case'searchTerm':default:return productsSearchTerm;}},[productSelectorType,productsBrand,productsCategory,productsItemNumbers,productsSearchTerm]);var flags=useMemo(function(){return{name:showName,price:showPrice,reviews:showRating};},[showName,showPrice,showRating]);return{productsSearchType:productSelectorType,productsSearchValue:value,sort:_camelCase(sort),productCount:productCount,showLoadMore:loadMoreButton,flags:flags};};
@@ -1 +0,0 @@
1
- export{default}from"./ProductList";
@@ -1 +0,0 @@
1
- export{default as PlaceholderWidget}from"./Placeholder";export{default as ProductListWidget}from"./ProductList";
@@ -1,8 +0,0 @@
1
- {
2
- "@shopgate/widgets/productListWidget": {
3
- "path": "@shopgate/engage/page/widgets/ProductList"
4
- },
5
- "@shopgate/widgetsInternal/Placeholder": {
6
- "path": "@shopgate/engage/page/widgets/Placeholder"
7
- }
8
- }
@@ -1,8 +0,0 @@
1
- function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import React,{useMemo,memo}from'react';import PropTypes from'prop-types';import{MapPriceHint,OrderQuantityHint,EffectivityDates,Swatches,AVAILABILITY_STATE_OK,AVAILABILITY_STATE_ALERT,getProductRoute}from'@shopgate/engage/product';import{hasNewServices as checkHasNewServices,i18n}from'@shopgate/engage/core/helpers';import{Availability,Link}from'@shopgate/engage/components';import{StockInfoLists}from'@shopgate/engage/locations/components';import{makeStyles}from'@shopgate/engage/styles';import ItemName from"../ItemName";import ItemPrice from"../ItemPrice";var useStyles=makeStyles()({root:{lineHeight:1.2,':not(:empty)':{padding:'12px 0 16px'}},quantityHint:{paddingTop:8}});/**
2
- * The Product Grid Item Detail component.
3
- * @param {Object} props The component props.
4
- * @param {Object} props.product The product.
5
- * @param {Object} props.display The display object.
6
- * @param {Object} [props.productListTypeMeta] Optional meta object with data from the product list
7
- * @returns {JSX.Element}
8
- */var ItemDetails=function ItemDetails(_ref){var product=_ref.product,display=_ref.display,productListTypeMeta=_ref.productListTypeMeta;var productId=product.id,_product$name=product.name,name=_product$name===void 0?null:_product$name,_product$stock=product.stock,stock=_product$stock===void 0?null:_product$stock;var _useStyles=useStyles(),classes=_useStyles.classes,cx=_useStyles.cx;var hasNewServices=useMemo(function(){return checkHasNewServices();},[]);if(display&&!display.name&&!display.price&&!display.reviews){return null;}return React.createElement(Link,{className:cx(classes.root,'theme__product-grid__item__item-details'),tabIndex:0,href:getProductRoute(productId),state:_extends({title:product.name},productListTypeMeta)},React.createElement(Swatches,{productId:productId}),React.createElement(ItemName,{display:display,productId:productId,name:name}),React.createElement(MapPriceHint,{productId:productId}),React.createElement(OrderQuantityHint,{productId:productId,className:classes.quantityHint}),React.createElement(EffectivityDates,{productId:productId}),hasNewServices&&React.createElement(React.Fragment,null,React.createElement(Availability,{state:!stock||stock.orderable?AVAILABILITY_STATE_OK:AVAILABILITY_STATE_ALERT,text:i18n.text('product.available.not'),showWhenAvailable:false}),React.createElement(StockInfoLists,{product:product})),React.createElement(ItemPrice,{product:product,display:display}));};ItemDetails.defaultProps={display:null,productListTypeMeta:null};export default memo(ItemDetails);
@@ -1 +0,0 @@
1
- function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import React from'react';import{shallow}from'enzyme';import{hasNewServices}from'@shopgate/engage/core/helpers';import{Availability}from'@shopgate/engage/components';import{StockInfoLists}from'@shopgate/engage/locations/components';import ItemDetails from"./index";jest.mock('@shopgate/engage/product',function(){return{MapPriceHint:function MapPriceHint(){return null;},OrderQuantityHint:function OrderQuantityHint(){return null;},EffectivityDates:function EffectivityDates(){return null;},Swatches:function Swatches(){return null;},AVAILABILITY_STATE_OK:'AVAILABILITY_STATE_OK',AVAILABILITY_STATE_ALERT:'AVAILABILITY_STATE_ALERT',getProductRoute:jest.fn(function(productId){return"link-to-product/".concat(productId);})};});jest.mock('@shopgate/engage/locations/components',function(){return{StockInfoLists:function StockInfoLists(){return null;}};});jest.mock('@shopgate/engage/core/helpers',function(){return{hasNewServices:jest.fn().mockReturnValue(false),i18n:{text:function text(str){return str;}}};});jest.mock('@shopgate/engage/components');jest.mock('@shopgate/engage/core',function(){return{isIOSTheme:jest.fn().mockReturnValue(true),hasWebBridge:jest.fn().mockReturnValue(false),i18n:{text:function text(_text){return _text;}}};});jest.mock("../ItemName");jest.mock("../ItemPrice");describe('<ItemDetails />',function(){var props={product:{id:'1234',name:'Foo',price:{}}};var display={name:false,price:false,reviews:false};it('should render with minimal props',function(){var wrapper=shallow(React.createElement(ItemDetails,props));expect(wrapper).toMatchSnapshot();expect(wrapper.find(Availability).exists()).toBe(false);expect(wrapper.find(StockInfoLists).exists()).toBe(false);});it('should render additional components with new services',function(){hasNewServices.mockReturnValueOnce(true);var wrapper=shallow(React.createElement(ItemDetails,props));expect(wrapper).toMatchSnapshot();expect(wrapper.find(Availability).exists()).toBe(true);expect(wrapper.find(StockInfoLists).exists()).toBe(true);});it('should not render with display props set',function(){var wrapper=shallow(React.createElement(ItemDetails,_extends({},props,{display:display})));expect(wrapper).toBeEmptyRender();});});
@@ -1,5 +0,0 @@
1
- import React,{memo,useMemo}from'react';import PropTypes from'prop-types';import{SurroundPortals,DiscountBadge}from'@shopgate/engage/components';import{PRODUCT_ITEM_DISCOUNT}from'@shopgate/engage/category';import{makeStyles}from'@shopgate/engage/styles';var useStyles=makeStyles()({root:{minWidth:40}});/**
2
- * The item discount component
3
- * @param {Object} props The component props.
4
- * @returns {JSX.Element|null}
5
- */var ItemDiscount=function ItemDiscount(_ref){var productId=_ref.productId,discount=_ref.discount;var _useStyles=useStyles(),classes=_useStyles.classes,cx=_useStyles.cx;var portalProps=useMemo(function(){return{productId:productId};},[productId]);if(!discount){return null;}return React.createElement("div",{className:cx(classes.root,'theme__product-grid__item__item-discount')},React.createElement(SurroundPortals,{portalName:PRODUCT_ITEM_DISCOUNT,portalProps:portalProps},React.createElement(DiscountBadge,{text:"-".concat(discount,"%")})));};ItemDiscount.defaultProps={discount:null};export default memo(ItemDiscount);
@@ -1,5 +0,0 @@
1
- import React,{memo,useMemo}from'react';import PropTypes from'prop-types';import{useSelector}from'react-redux';import{SurroundPortals,FavoritesButton}from'@shopgate/engage/components';import{PRODUCT_ITEM_FAVORITES_BUTTON}from'@shopgate/engage/category';import{isRelativeProductOnList}from'@shopgate/engage/favorites';import{getLoadWishlistOnAppStartEnabled}from'@shopgate/engage/core';import{makeStyles}from'@shopgate/engage/styles';var useStyles=makeStyles()({root:{position:'absolute',top:0,right:16,left:'auto',transform:'translate3d(0, -50%, 0)'}});/**
2
- * The item favorites button component.
3
- * @param {Object} props The component props.
4
- * @returns {JSX.Element}
5
- */var ItemFavoritesButton=function ItemFavoritesButton(_ref){var productId=_ref.productId;var _useStyles=useStyles(),classes=_useStyles.classes;var loadWishlistOnAppStartEnabled=useSelector(getLoadWishlistOnAppStartEnabled);var isOnWishlist=useSelector(function(state){return isRelativeProductOnList(state,{productId:productId});});var isFavorite=useMemo(function(){return!loadWishlistOnAppStartEnabled?false:isOnWishlist;},[isOnWishlist,loadWishlistOnAppStartEnabled]);var portalProps=useMemo(function(){return{productId:productId};},[productId]);return React.createElement(SurroundPortals,{portalName:PRODUCT_ITEM_FAVORITES_BUTTON,portalProps:portalProps},React.createElement("div",{className:classes.root,"data-test-id":"favorites"},React.createElement(FavoritesButton,{active:isFavorite,productId:productId,noShadow:true,removeWithRelatives:true})));};export default memo(ItemFavoritesButton);
@@ -1 +0,0 @@
1
- import React from'react';import{shallow}from'enzyme';import{combineReducers}from'redux';import{Provider}from'react-redux';import{createMockStore}from'@shopgate/pwa-common/store';import favorites from'@shopgate/pwa-common-commerce/favorites/reducers';import ItemFavoritesButton from"./index";jest.mock('@shopgate/engage/components');var store=createMockStore(combineReducers({favorites:favorites}));describe('<ItemFavoritesButton />',function(){it('should not render when its not a favorite',function(){var wrapper=shallow(React.createElement(Provider,{store:store},React.createElement(ItemFavoritesButton,{productId:"1234"})));expect(wrapper).toMatchSnapshot();});it('should render if its a favorite',function(){var wrapper=shallow(React.createElement(Provider,{store:store},React.createElement(ItemFavoritesButton,{productId:"1234",isFavorite:true})));expect(wrapper).toMatchSnapshot();});});
@@ -1,5 +0,0 @@
1
- import React,{useMemo,memo}from'react';import PropTypes from'prop-types';import{SurroundPortals}from'@shopgate/engage/components';import{PRODUCT_ITEM_IMAGE}from'@shopgate/engage/category/constants';import{getProductImageSettings,ProductImage}from'@shopgate/engage/product';var _getProductImageSetti=getProductImageSettings(),gridResolutions=_getProductImageSetti.ListImage;/**
2
- * The item image component.
3
- * @param {Object} props The component props.
4
- * @returns {JSX.Element}
5
- */var ItemImage=function ItemImage(_ref){var productId=_ref.productId,name=_ref.name,imageUrl=_ref.imageUrl;var portalProps=useMemo(function(){return{productId:productId};},[productId]);return React.createElement(SurroundPortals,{portalName:PRODUCT_ITEM_IMAGE,portalProps:portalProps},React.createElement(ProductImage,{alt:name,src:imageUrl,resolutions:gridResolutions,itemProp:"image"}));};ItemImage.defaultProps={imageUrl:null,name:null};export default memo(ItemImage);
@@ -1 +0,0 @@
1
- import React from'react';import{shallow}from'enzyme';import ItemImage from"./index";jest.mock('@shopgate/engage/components',function(){return{ProductImage:function ProductImage(){return null;}};});describe('<ItemImage />',function(){it('should render',function(){var wrapper=shallow(React.createElement(ItemImage,{productId:"1234",imageUrl:"http://www.google.com",name:"FooBar"}));expect(wrapper).toMatchSnapshot();});});