@shopgate/engage 7.32.0-beta.11 → 7.32.0-beta.12

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 (32) hide show
  1. package/package.json +7 -7
  2. package/page/components/Widgets/Widget.d.ts.map +1 -1
  3. package/page/components/Widgets/Widget.js +12 -15
  4. package/page/components/Widgets/WidgetContext.d.ts +3 -3
  5. package/page/components/Widgets/WidgetContext.d.ts.map +1 -1
  6. package/page/components/Widgets/WidgetProvider.d.ts +6 -2
  7. package/page/components/Widgets/WidgetProvider.d.ts.map +1 -1
  8. package/page/components/Widgets/WidgetProvider.js +3 -3
  9. package/page/components/Widgets/constants.d.ts +13 -0
  10. package/page/components/Widgets/constants.d.ts.map +1 -1
  11. package/page/components/Widgets/constants.js +21 -1
  12. package/page/components/Widgets/helpers.d.ts +19 -0
  13. package/page/components/Widgets/helpers.d.ts.map +1 -1
  14. package/page/components/Widgets/helpers.js +50 -0
  15. package/page/components/Widgets/types.d.ts +31 -5
  16. package/page/components/Widgets/types.d.ts.map +1 -1
  17. package/page/widget.config.schema.json +54 -0
  18. package/page/widgets/HeroBanner/config.json +6 -0
  19. package/page/widgets/Image/config.json +6 -0
  20. package/page/widgets/ImageRow/config.json +6 -0
  21. package/page/widgets/ImageSlider/config.json +6 -0
  22. package/page/widgets/ImageSlider/hooks.js +4 -2
  23. package/page/widgets/README.md +92 -0
  24. package/page/widgets/Video/config.json +6 -0
  25. package/settings/reducers/appSettings.d.ts.map +1 -1
  26. package/settings/reducers/appSettings.js +24 -1
  27. package/settings/selectors/appSettings.d.ts +8 -0
  28. package/settings/selectors/appSettings.d.ts.map +1 -1
  29. package/settings/selectors/appSettings.js +5 -0
  30. package/settings/types/appSettings.d.ts +35 -0
  31. package/settings/types/appSettings.d.ts.map +1 -1
  32. package/settings/types/appSettings.js +9 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopgate/engage",
3
- "version": "7.32.0-beta.11",
3
+ "version": "7.32.0-beta.12",
4
4
  "description": "Shopgate's ENGAGE library.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Shopgate <support@shopgate.com>",
@@ -18,12 +18,12 @@
18
18
  "dependencies": {
19
19
  "@emotion/react": "^11.14.0",
20
20
  "@shopgate/native-modules": "1.0.0-beta.34",
21
- "@shopgate/pwa-common": "7.32.0-beta.11",
22
- "@shopgate/pwa-common-commerce": "7.32.0-beta.11",
23
- "@shopgate/pwa-core": "7.32.0-beta.11",
24
- "@shopgate/pwa-ui-ios": "7.32.0-beta.11",
25
- "@shopgate/pwa-ui-material": "7.32.0-beta.11",
26
- "@shopgate/pwa-ui-shared": "7.32.0-beta.11",
21
+ "@shopgate/pwa-common": "7.32.0-beta.12",
22
+ "@shopgate/pwa-common-commerce": "7.32.0-beta.12",
23
+ "@shopgate/pwa-core": "7.32.0-beta.12",
24
+ "@shopgate/pwa-ui-ios": "7.32.0-beta.12",
25
+ "@shopgate/pwa-ui-material": "7.32.0-beta.12",
26
+ "@shopgate/pwa-ui-shared": "7.32.0-beta.12",
27
27
  "@stripe/react-stripe-js": "^1.16.5",
28
28
  "@stripe/stripe-js": "^1.44.1",
29
29
  "@virtuous/conductor": "~2.5.0",
@@ -1 +1 @@
1
- {"version":3,"file":"Widget.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/Widget.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAQlE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAiDhD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,SAAS,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC,CAAC;IAC1E;;OAEG;IACH,UAAU,EAAE,gBAAgB,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,QAAA,MAAM,MAAM,GAAI,wEAKb,WAAW,uCAqEb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Widget.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/Widget.tsx"],"names":[],"mappings":"AAAA,OAAO,EAC2B,KAAK,aAAa,EACnD,MAAM,OAAO,CAAC;AAWf,OAAO,EAAE,KAAK,gBAAgB,EAAqB,MAAM,SAAS,CAAC;AAuCnE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,SAAS,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC,CAAC;IAC1E;;OAEG;IACH,UAAU,EAAE,gBAAgB,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,QAAA,MAAM,MAAM,GAAI,wEAKb,WAAW,uCAwEb,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -1,15 +1,14 @@
1
- import { Suspense, useCallback } from 'react';
1
+ import { Suspense, useCallback, useMemo } from 'react';
2
+ import { useSelector } from 'react-redux';
2
3
  import { makeStyles } from '@shopgate/engage/styles';
3
4
  import { VisibilityOffIcon, TimeIcon, Loading } from '@shopgate/engage/components';
4
5
  import { usePressHandler } from '@shopgate/engage/core/hooks';
6
+ import { getWidgetMediaMargins } from '@shopgate/engage/settings/selectors/appSettings';
5
7
  import WidgetProvider from "./WidgetProvider";
6
8
  import { dispatchWidgetPreviewEvent } from "./events";
7
9
  import { useWidgetsPreview } from "./hooks";
10
+ import { getAppliedMediaMargins, resolveWidgetLayout } from "./helpers";
8
11
  import Tooltip from "./Tooltip";
9
-
10
- /**
11
- * Style parameters for the widget, derived from its layout margins.
12
- */
13
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
13
  const useStyles = makeStyles()((theme, {
15
14
  marginTop,
@@ -61,15 +60,12 @@ const Widget = ({
61
60
  isPreview,
62
61
  isCustomLegacyWidget = false
63
62
  }) => {
63
+ const mediaMargins = useSelector(getWidgetMediaMargins);
64
+ const layout = useMemo(() => resolveWidgetLayout(definition?.layout, getAppliedMediaMargins(definition?.widgetConfigDefinitionCode), mediaMargins), [definition, mediaMargins]);
64
65
  const {
65
66
  classes,
66
67
  cx
67
- } = useStyles({
68
- marginTop: definition?.layout?.marginTop ?? 0,
69
- marginBottom: definition?.layout?.marginBottom ?? 0,
70
- marginLeft: definition?.layout?.marginLeft ?? 0,
71
- marginRight: definition?.layout?.marginRight ?? 0
72
- });
68
+ } = useStyles(layout);
73
69
  const {
74
70
  setActiveWidget,
75
71
  activeWidget
@@ -92,10 +88,10 @@ const Widget = ({
92
88
  [classes.preview]: isPreview
93
89
  }),
94
90
  style: {
95
- marginTop: definition?.layout?.marginTop,
96
- marginBottom: definition?.layout?.marginBottom,
97
- marginLeft: definition?.layout?.marginLeft,
98
- marginRight: definition?.layout?.marginRight
91
+ marginTop: layout.marginTop || undefined,
92
+ marginBottom: layout.marginBottom || undefined,
93
+ marginLeft: layout.marginLeft || undefined,
94
+ marginRight: layout.marginRight || undefined
99
95
  },
100
96
  "data-widget-name": definition.widgetConfigDefinitionCode,
101
97
  ...(isPreview && {
@@ -119,6 +115,7 @@ const Widget = ({
119
115
  }), /*#__PURE__*/_jsx(WidgetProvider, {
120
116
  definition: definition,
121
117
  isPreview: isPreview,
118
+ layout: layout,
122
119
  children: /*#__PURE__*/_jsx(Suspense, {
123
120
  fallback: /*#__PURE__*/_jsx(Loading, {}),
124
121
  children: /*#__PURE__*/_jsx(Component, {
@@ -1,4 +1,4 @@
1
- import { type WidgetDefinitionLayout, type WidgetDefinitionVisibility } from './types';
1
+ import { type WidgetDefinitionVisibility, type WidgetLayout } from './types';
2
2
  export { type WidgetDefinition } from './types';
3
3
  /**
4
4
  * Context value provided by the {@link WidgetContext} for a single widget instance.
@@ -17,9 +17,9 @@ export interface WidgetContextType<C = Record<string, unknown>> {
17
17
  */
18
18
  config: C;
19
19
  /**
20
- * The widget layout settings.
20
+ * The resolved margins of the widget container.
21
21
  */
22
- layout: WidgetDefinitionLayout;
22
+ layout: WidgetLayout;
23
23
  /**
24
24
  * The widget visibility settings.
25
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetContext.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/WidgetContext.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAChC,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5D;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;OAEG;IACH,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;OAEG;IACH,UAAU,EAAE,0BAA0B,CAAC;IACvC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,qEAA4D,CAAC"}
1
+ {"version":3,"file":"WidgetContext.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/WidgetContext.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5D;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;OAEG;IACH,UAAU,EAAE,0BAA0B,CAAC;IACvC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,qEAA4D,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import { type WidgetDefinition } from './types';
2
+ import { type WidgetDefinition, type WidgetLayout } from './types';
3
3
  /**
4
4
  * Props of the {@link WidgetProvider} component.
5
5
  */
@@ -16,10 +16,14 @@ export interface WidgetProviderProps {
16
16
  * Whether the widget is in preview mode.
17
17
  */
18
18
  isPreview: boolean;
19
+ /**
20
+ * The resolved margins of the widget container.
21
+ */
22
+ layout: WidgetLayout;
19
23
  }
20
24
  /**
21
25
  * The WidgetProvider component provides the context for a single widget.
22
26
  */
23
- declare const WidgetProvider: ({ children, definition, isPreview }: WidgetProviderProps) => import("react").JSX.Element;
27
+ declare const WidgetProvider: ({ children, definition, isPreview, layout, }: WidgetProviderProps) => import("react").JSX.Element;
24
28
  export default WidgetProvider;
25
29
  //# sourceMappingURL=WidgetProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetProvider.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/WidgetProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,UAAU,EAAE,gBAAgB,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,QAAA,MAAM,cAAc,GAAI,qCAAqC,mBAAmB,gCAoB/E,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"WidgetProvider.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/WidgetProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,UAAU,EAAE,gBAAgB,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;GAEG;AACH,QAAA,MAAM,cAAc,GAAI,8CAErB,mBAAmB,gCAoBrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -11,12 +11,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
11
11
  const WidgetProvider = ({
12
12
  children,
13
13
  definition,
14
- isPreview
14
+ isPreview,
15
+ layout
15
16
  }) => {
16
17
  const value = useMemo(() => {
17
18
  const {
18
19
  widgetConfig,
19
- layout,
20
20
  visibility,
21
21
  code,
22
22
  widgetConfigDefinitionCode
@@ -29,7 +29,7 @@ const WidgetProvider = ({
29
29
  visibility,
30
30
  isPreview
31
31
  };
32
- }, [definition, isPreview]);
32
+ }, [definition, isPreview, layout]);
33
33
  return /*#__PURE__*/_jsx(WidgetContext.Provider, {
34
34
  value: value,
35
35
  children: children
@@ -1,5 +1,18 @@
1
+ import { type MediaMarginSettings } from '@shopgate/engage/settings/types/appSettings';
1
2
  /**
2
3
  * Whether to consider vertical margins when calculating the overlay position.
3
4
  */
4
5
  export declare const CONSIDER_CONTAINER_MARGINS_ON_SCROLL_DEFAULT = false;
6
+ /**
7
+ * The margin sides of a widget container.
8
+ */
9
+ export declare const MARGIN_SIDES: readonly ["marginTop", "marginBottom", "marginLeft", "marginRight"];
10
+ /**
11
+ * The media widget margin side that belongs to each margin of a widget container.
12
+ */
13
+ export declare const MARGIN_SIDE_SETTINGS: Record<typeof MARGIN_SIDES[number], keyof MediaMarginSettings>;
14
+ /**
15
+ * The sides of the media widget margins.
16
+ */
17
+ export declare const MEDIA_MARGIN_SIDES: (keyof MediaMarginSettings)[];
5
18
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,4CAA4C,QAAQ,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAEvF;;GAEG;AACH,eAAO,MAAM,4CAA4C,QAAQ,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,YAAY,qEAAsE,CAAC;AAEhG;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CACvC,OAAO,YAAY,CAAC,MAAM,CAAC,EAC3B,MAAM,mBAAmB,CAM1B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,+BAAsC,CAAC"}
@@ -1,4 +1,24 @@
1
1
  /**
2
2
  * Whether to consider vertical margins when calculating the overlay position.
3
3
  */
4
- export const CONSIDER_CONTAINER_MARGINS_ON_SCROLL_DEFAULT = false;
4
+ export const CONSIDER_CONTAINER_MARGINS_ON_SCROLL_DEFAULT = false;
5
+
6
+ /**
7
+ * The margin sides of a widget container.
8
+ */
9
+ export const MARGIN_SIDES = ['marginTop', 'marginBottom', 'marginLeft', 'marginRight'];
10
+
11
+ /**
12
+ * The media widget margin side that belongs to each margin of a widget container.
13
+ */
14
+ export const MARGIN_SIDE_SETTINGS = {
15
+ marginTop: 'top',
16
+ marginBottom: 'bottom',
17
+ marginLeft: 'left',
18
+ marginRight: 'right'
19
+ };
20
+
21
+ /**
22
+ * The sides of the media widget margins.
23
+ */
24
+ export const MEDIA_MARGIN_SIDES = Object.values(MARGIN_SIDE_SETTINGS);
@@ -1,3 +1,5 @@
1
+ import { type MediaMarginSettings } from '@shopgate/engage/settings/types/appSettings';
2
+ import { type AppliedMediaMargins, type WidgetDefinitionLayout, type WidgetLayout } from './types';
1
3
  /**
2
4
  * Retrieves the scroll container for the current page. Depending on the PWA mode this can be
3
5
  * a scrollable article element or the window.
@@ -47,4 +49,21 @@ export interface ScheduledStatus {
47
49
  * @returns An object containing the scheduling status.
48
50
  */
49
51
  export declare function checkScheduled({ from, to, timezoneOffset }?: ScheduledParams): ScheduledStatus;
52
+ /**
53
+ * Retrieves the sides on which a widget gets the media widget margins. Widgets declare them in a
54
+ * "config.json" inside their folder, which the build adds to the widget mapping. A widget that
55
+ * declares nothing keeps the margins of its own configuration.
56
+ * @param name The name of the widget.
57
+ * @returns The sides that get the media widget margins.
58
+ */
59
+ export declare function getAppliedMediaMargins(name: string): AppliedMediaMargins;
60
+ /**
61
+ * Resolves the margins of a widget container. The configuration of the widget instance wins over
62
+ * the media widget margin, which only applies to the sides the widget asked for.
63
+ * @param definitionLayout The layout settings of the widget instance.
64
+ * @param appliedMediaMargins The sides on which the widget gets the media widget margins.
65
+ * @param settings The media widget margins.
66
+ * @returns The resolved margins.
67
+ */
68
+ export declare function resolveWidgetLayout(definitionLayout: Partial<WidgetDefinitionLayout> | undefined, appliedMediaMargins: AppliedMediaMargins, settings: MediaMarginSettings): WidgetLayout;
50
69
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/helpers.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAO,WAAW,GAAG,IACwC,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,EAAE,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,GAAE,eAAoB,GACjD,eAAe,CAqBjB"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EACL,KAAK,mBAAmB,EAExB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAGjB;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAO,WAAW,GAAG,IACwC,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,EAAE,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,GAAE,eAAoB,GACjD,eAAe,CAqBjB;AAkBD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAgBxE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,OAAO,CAAC,sBAAsB,CAAC,GAAG,SAAS,EAC7D,mBAAmB,EAAE,mBAAmB,EACxC,QAAQ,EAAE,mBAAmB,GAC5B,YAAY,CAUd"}
@@ -1,5 +1,8 @@
1
+ import "core-js/modules/es.array.reduce.js";
1
2
  import "core-js/modules/es.string.replace.js";
3
+ import { componentsConfig } from '@shopgate/pwa-common/helpers/config';
2
4
  import { PAGE_PREVIEW_PATTERN } from '@shopgate/engage/page/constants';
5
+ import { MARGIN_SIDES, MARGIN_SIDE_SETTINGS, MEDIA_MARGIN_SIDES } from "./constants";
3
6
 
4
7
  /**
5
8
  * Retrieves the scroll container for the current page. Depending on the PWA mode this can be
@@ -45,4 +48,51 @@ export function checkScheduled({
45
48
  isActive,
46
49
  isExpired
47
50
  };
51
+ }
52
+
53
+ /**
54
+ * The widget mapping of the components config, reduced to what the layout resolution reads. The
55
+ * config itself comes from untyped JS, so the shape is described here at the consumption boundary.
56
+ */
57
+
58
+ /**
59
+ * Retrieves the sides on which a widget gets the media widget margins. Widgets declare them in a
60
+ * "config.json" inside their folder, which the build adds to the widget mapping. A widget that
61
+ * declares nothing keeps the margins of its own configuration.
62
+ * @param name The name of the widget.
63
+ * @returns The sides that get the media widget margins.
64
+ */
65
+ export function getAppliedMediaMargins(name) {
66
+ const {
67
+ widgetsV2
68
+ } = componentsConfig;
69
+ const declared = widgetsV2?.[name]?.config?.layout?.applyMediaMargins;
70
+ if (declared === true) {
71
+ return MEDIA_MARGIN_SIDES.reduce((sides, side) => ({
72
+ ...sides,
73
+ [side]: true
74
+ }), {});
75
+ }
76
+ if (declared && typeof declared === 'object') {
77
+ return declared;
78
+ }
79
+ return {};
80
+ }
81
+
82
+ /**
83
+ * Resolves the margins of a widget container. The configuration of the widget instance wins over
84
+ * the media widget margin, which only applies to the sides the widget asked for.
85
+ * @param definitionLayout The layout settings of the widget instance.
86
+ * @param appliedMediaMargins The sides on which the widget gets the media widget margins.
87
+ * @param settings The media widget margins.
88
+ * @returns The resolved margins.
89
+ */
90
+ export function resolveWidgetLayout(definitionLayout, appliedMediaMargins, settings) {
91
+ return MARGIN_SIDES.reduce((layout, side) => {
92
+ const mediaSide = MARGIN_SIDE_SETTINGS[side];
93
+ return {
94
+ ...layout,
95
+ [side]: definitionLayout?.[side] ?? (appliedMediaMargins?.[mediaSide] ? settings?.[mediaSide] ?? 0 : 0)
96
+ };
97
+ }, {});
48
98
  }
@@ -1,3 +1,4 @@
1
+ import { type MediaMarginSettings } from '@shopgate/engage/settings/types/appSettings';
1
2
  /**
2
3
  * Visibility settings for a widget.
3
4
  */
@@ -16,25 +17,50 @@ export interface WidgetDefinitionVisibility {
16
17
  scheduleEndDate: string;
17
18
  }
18
19
  /**
19
- * Layout settings for a widget.
20
+ * Layout settings for a widget. A side is null when it has no own configuration.
20
21
  */
21
22
  export interface WidgetDefinitionLayout {
22
23
  /**
23
24
  * Top margin for the widget.
24
25
  */
25
- marginTop: number;
26
+ marginTop: number | null;
26
27
  /**
27
28
  * Bottom margin for the widget.
28
29
  */
29
- marginBottom: number;
30
+ marginBottom: number | null;
30
31
  /**
31
32
  * Left margin for the widget.
32
33
  */
33
- marginLeft: number;
34
+ marginLeft: number | null;
34
35
  /**
35
36
  * Right margin for the widget.
36
37
  */
37
- marginRight: number;
38
+ marginRight: number | null;
39
+ }
40
+ /**
41
+ * Margins of a widget container after resolution. Every side is a number, never null.
42
+ */
43
+ export type WidgetLayout = Record<keyof WidgetDefinitionLayout, number>;
44
+ /**
45
+ * The sides on which a widget gets the media widget margins. An omitted side does not.
46
+ */
47
+ export type AppliedMediaMargins = Partial<Record<keyof MediaMarginSettings, boolean>>;
48
+ /**
49
+ * Static configuration a widget declares about itself. It is picked up at build time, so its
50
+ * values are known before the widget is loaded.
51
+ */
52
+ export interface WidgetConfig {
53
+ /**
54
+ * How the container that the page builder renders around the widget behaves.
55
+ */
56
+ layout?: {
57
+ /**
58
+ * On which sides the widget gets the media widget margins that merchants configure in the
59
+ * theme settings. True for all sides, false for none, or an object to opt in per side.
60
+ * Margins configured for a single widget instance always win.
61
+ */
62
+ applyMediaMargins?: boolean | AppliedMediaMargins;
63
+ };
38
64
  }
39
65
  /**
40
66
  * Definition of a API widget
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;OAEG;IACH,UAAU,EAAE,0BAA0B,CAAC;IACvC;;OAEG;IACH,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;OAEG;IACH,IAAI,CAAC,EAAE;QACL;;WAEG;QACH,MAAM,EAAE;YACN;;eAEG;YACH,QAAQ,EAAE,OAAO,CAAC;YAClB;;eAEG;YACH,OAAO,EAAE,MAAM,CAAC;YAChB;;eAEG;YACH,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF;;WAEG;QACH,SAAS,EAAE;YACT;;eAEG;YACH,WAAW,EAAE,OAAO,CAAC;YACrB;;eAEG;YACH,QAAQ,EAAE,OAAO,CAAC;YAClB;;eAEG;YACH,SAAS,EAAE,OAAO,CAAC;YACnB;;eAEG;YACH,OAAO,EAAE,MAAM,CAAC;YAChB;;eAEG;YACH,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAA;CACF;AAED,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../page/components/Widgets/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;OAEG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;OAEG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,sBAAsB,EAAE,MAAM,CAAC,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC;AAEtF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,MAAM,CAAC,EAAE;QACP;;;;WAIG;QACH,iBAAiB,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;KACnD,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;OAEG;IACH,UAAU,EAAE,0BAA0B,CAAC;IACvC;;OAEG;IACH,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;OAEG;IACH,IAAI,CAAC,EAAE;QACL;;WAEG;QACH,MAAM,EAAE;YACN;;eAEG;YACH,QAAQ,EAAE,OAAO,CAAC;YAClB;;eAEG;YACH,OAAO,EAAE,MAAM,CAAC;YAChB;;eAEG;YACH,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF;;WAEG;QACH,SAAS,EAAE;YACT;;eAEG;YACH,WAAW,EAAE,OAAO,CAAC;YACrB;;eAEG;YACH,QAAQ,EAAE,OAAO,CAAC;YAClB;;eAEG;YACH,SAAS,EAAE,OAAO,CAAC;YACnB;;eAEG;YACH,OAAO,EAAE,MAAM,CAAC;YAChB;;eAEG;YACH,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAA;CACF;AAED,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB"}
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Widget configuration",
4
+ "description": "Declares how the page builder treats a widget. The file lives next to the widget implementation and is read at build time, so its values are known before the widget itself is loaded.",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string",
10
+ "description": "Path or url of this schema. Enables autocompletion and validation in the editor."
11
+ },
12
+ "layout": {
13
+ "type": "object",
14
+ "description": "How the container that the page builder renders around the widget behaves.",
15
+ "additionalProperties": false,
16
+ "properties": {
17
+ "applyMediaMargins": {
18
+ "description": "On which sides the widget gets the media widget margins that merchants configure in the theme settings. Margins configured for a single widget instance in the page builder always win. Widgets that bring their own spacing should leave this out.",
19
+ "default": false,
20
+ "oneOf": [
21
+ {
22
+ "type": "boolean",
23
+ "description": "true applies the media widget margins to all four sides, false to none."
24
+ },
25
+ {
26
+ "type": "object",
27
+ "description": "Opts in per side. An omitted side does not get the margin.",
28
+ "additionalProperties": false,
29
+ "minProperties": 1,
30
+ "properties": {
31
+ "top": {
32
+ "type": "boolean",
33
+ "description": "Whether the widget gets the media widget margin above it."
34
+ },
35
+ "bottom": {
36
+ "type": "boolean",
37
+ "description": "Whether the widget gets the media widget margin below it."
38
+ },
39
+ "left": {
40
+ "type": "boolean",
41
+ "description": "Whether the widget gets the media widget margin on its left. Widgets that are meant to touch the screen edges leave this out."
42
+ },
43
+ "right": {
44
+ "type": "boolean",
45
+ "description": "Whether the widget gets the media widget margin on its right. Widgets that are meant to touch the screen edges leave this out."
46
+ }
47
+ }
48
+ }
49
+ ]
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../widget.config.schema.json",
3
+ "layout": {
4
+ "applyMediaMargins": true
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../widget.config.schema.json",
3
+ "layout": {
4
+ "applyMediaMargins": true
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../widget.config.schema.json",
3
+ "layout": {
4
+ "applyMediaMargins": true
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../widget.config.schema.json",
3
+ "layout": {
4
+ "applyMediaMargins": true
5
+ }
6
+ }
@@ -145,11 +145,13 @@ export const useImageSliderWidget = () => {
145
145
  style: {
146
146
  ...(layout.marginLeft ? {
147
147
  marginLeft: layout.marginLeft * -1,
148
- paddingLeft: layout.marginLeft
148
+ paddingLeft: layout.marginLeft,
149
+ '--swiper-pagination-inset-left': `${layout.marginLeft}px`
149
150
  } : {}),
150
151
  ...(layout.marginRight ? {
151
152
  marginRight: layout.marginRight * -1,
152
- paddingRight: layout.marginRight
153
+ paddingRight: layout.marginRight,
154
+ '--swiper-pagination-inset-right': `${layout.marginRight}px`
153
155
  } : {})
154
156
  }
155
157
  } : null),
@@ -0,0 +1,92 @@
1
+ # Widgets
2
+
3
+ Widgets are the building blocks of a CMS page. The core renders a flat list of containers and each
4
+ widget renders inside one, without knowing anything about its surroundings.
5
+
6
+ ## Widget config
7
+
8
+ A widget can tell the core a few things about itself. It does that in a `config.json` inside its
9
+ own folder:
10
+
11
+ ```
12
+ libraries/engage/page/widgets/Video/
13
+ config.json <- the config of this widget
14
+ Video.tsx
15
+ hooks.ts
16
+ index.ts
17
+ ```
18
+
19
+ Widgets that need no configuration ship no file.
20
+
21
+ The file is read **at build time** and its content is passed to the app together with the widget
22
+ mapping, so its values are known before the widget itself is loaded. A running build watches the
23
+ config files, which means editing one is picked up without a restart. Adding a whole new widget
24
+ still needs one, because that also changes the component mapping of the app.
25
+
26
+ A config that does not match the schema, or that cannot be parsed, **fails the build** with a
27
+ message that names the widget.
28
+
29
+ ### Media widget margins
30
+
31
+ Merchants configure margins around media widgets in the theme settings. They arrive in the app
32
+ settings as `widgets.mediaMargins` and are applied to the container of every widget that asks for
33
+ them:
34
+
35
+ ```json
36
+ {
37
+ "$schema": "../../widget.config.schema.json",
38
+ "layout": {
39
+ "applyMediaMargins": true
40
+ }
41
+ }
42
+ ```
43
+
44
+ `true` applies the margin on all four sides. To take part on some sides only, name them:
45
+
46
+ ```json
47
+ {
48
+ "$schema": "../../widget.config.schema.json",
49
+ "layout": {
50
+ "applyMediaMargins": {
51
+ "top": true,
52
+ "bottom": true
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ Widgets that bring their own spacing should not ask for the margins, otherwise the two add up. A
59
+ widget that is meant to touch the screen edges leaves out `left` and `right`.
60
+
61
+ Margins that a merchant configures for a single widget instance in the page builder always win over
62
+ the media widget margins.
63
+
64
+ ### Editor support
65
+
66
+ The optional `"$schema"` entry gives autocompletion and inline validation while editing. It is an
67
+ editor feature only - the build never follows it, and it is stripped from the config before it
68
+ reaches the app. What guards a config is the validation the build runs against
69
+ [widget.config.schema.json](../widget.config.schema.json), which happens with or without the entry.
70
+
71
+ Widgets in this package point at the schema with a path relative to their own folder:
72
+
73
+ ```json
74
+ {
75
+ "$schema": "../../widget.config.schema.json",
76
+ "layout": {
77
+ "applyMediaMargins": true
78
+ }
79
+ }
80
+ ```
81
+
82
+ **Widgets in extensions leave the entry out.** There is no relative path that works for them: an
83
+ extension is developed in its own repository, where this package is not present at all, and in an
84
+ app it depends on whether the theme or the app carries `@shopgate/engage`. A wrong path is not
85
+ dangerous - the editor just offers no help - but it is noise that never starts working. Extension
86
+ authors who want the same support can map the schema in their editor instead, for example through
87
+ `json.schemas` in the workspace settings of their repository.
88
+
89
+ ### Widgets of extensions
90
+
91
+ The config of an extension widget belongs to the repository of that extension. `extensions/` is not
92
+ part of this repository, so a file that is only added to a local checkout never ships.
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../widget.config.schema.json",
3
+ "layout": {
4
+ "applyMediaMargins": true
5
+ }
6
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../../settings/reducers/appSettings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAa/E,KAAK,iBAAiB,GAAG,wBAAwB,GAAG,aAAa,CAAC;AAQlE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBA+DlC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,WAAW,EAAE,OAAO,CAAC,gBAAgB,EAAE,iBAAiB,CAuC7D,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../../settings/reducers/appSettings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAa/E,KAAK,iBAAiB,GAAG,wBAAwB,GAAG,aAAa,CAAC;AAQlE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBAuElC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,WAAW,EAAE,OAAO,CAAC,gBAAgB,EAAE,iBAAiB,CAqD7D,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -67,6 +67,14 @@ export const DEFAULT_APP_SETTINGS = {
67
67
  appearance: {
68
68
  defaultColorSchemeMode: 'light'
69
69
  },
70
+ widgets: {
71
+ mediaMargins: {
72
+ top: 0,
73
+ bottom: 0,
74
+ left: 0,
75
+ right: 0
76
+ }
77
+ },
70
78
  images: {
71
79
  quality: DEFAULT_IMAGE_QUALITY,
72
80
  // Already in the image service's format, so the unhydrated path needs no conversion.
@@ -95,8 +103,12 @@ const appSettings = (state, action = {
95
103
  const {
96
104
  images,
97
105
  typography,
98
- appearance
106
+ appearance,
107
+ widgets
99
108
  } = action.settings ?? {};
109
+ const {
110
+ mediaMargins
111
+ } = widgets ?? {};
100
112
 
101
113
  // Merged over the defaults rather than over the current state, so a field an incoming payload
102
114
  // omits falls back to its default instead of keeping the value of an earlier one. The admin
@@ -117,6 +129,17 @@ const appSettings = (state, action = {
117
129
  appearance: appearance === null ? undefined : {
118
130
  ...appearance,
119
131
  defaultColorSchemeMode: appearance?.defaultColorSchemeMode ?? undefined
132
+ },
133
+ widgets: widgets === null ? undefined : {
134
+ ...widgets,
135
+ // Sides are mapped one by one, because the admin clears a single margin with a null just
136
+ // like it clears a whole branch with one.
137
+ mediaMargins: !mediaMargins ? undefined : {
138
+ top: mediaMargins.top ?? undefined,
139
+ bottom: mediaMargins.bottom ?? undefined,
140
+ left: mediaMargins.left ?? undefined,
141
+ right: mediaMargins.right ?? undefined
142
+ }
120
143
  }
121
144
  }, {
122
145
  isHydrated: true
@@ -119,6 +119,14 @@ export declare const getCardShadowSize: ((state: AppSettingsState) => import("..
119
119
  }> & {
120
120
  clearCache: () => void;
121
121
  };
122
+ /**
123
+ * Selects the margins that are applied around media widgets.
124
+ */
125
+ export declare const getWidgetMediaMargins: ((state: AppSettingsState) => import("../types/appSettings").MediaMarginSettings) & import("reselect").OutputSelectorFields<(args_0: AppSettingsSlice) => import("../types/appSettings").MediaMarginSettings, {
126
+ clearCache: () => void;
127
+ }> & {
128
+ clearCache: () => void;
129
+ };
122
130
  /**
123
131
  * Selects the color scheme mode that applies while the visitor has no own preference stored. A
124
132
  * mode rather than a scheme name, since it can also ask to follow the operating system: a
@@ -1 +1 @@
1
- {"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../../settings/selectors/appSettings.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGhG;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,gBAAgB,KAAG,gBACR,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;;;;CAGrC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;CAGjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,6BAA6B;;;;CAGzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;CAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;CAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;CAG5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;CAGtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;CAGtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;CAG3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;CAG7B,CAAC;AAWF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;CAIrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;CAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;CAGjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;CAMpC,CAAC"}
1
+ {"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../../settings/selectors/appSettings.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGhG;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,gBAAgB,KAAG,gBACR,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;;;;CAGrC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;CAGjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,6BAA6B;;;;CAGzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;CAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;CAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;CAG5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;CAGtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;CAGtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;CAG3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;CAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;CAGjC,CAAC;AAWF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;CAIrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;CAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;CAGjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;CAMpC,CAAC"}
@@ -68,6 +68,11 @@ export const getCardSettings = createSelector(getAppSettingsState, appSettings =
68
68
  */
69
69
  export const getCardShadowSize = createSelector(getCardSettings, cards => cards.style === 'shadow' ? cards.shadow.size : 'none');
70
70
 
71
+ /**
72
+ * Selects the margins that are applied around media widgets.
73
+ */
74
+ export const getWidgetMediaMargins = createSelector(getAppSettingsState, appSettings => appSettings.widgets?.mediaMargins ?? DEFAULT_APP_SETTINGS.widgets.mediaMargins);
75
+
71
76
  /**
72
77
  * Selects the raw appearance setting: a binding color scheme, or `selectable`.
73
78
  */
@@ -198,6 +198,37 @@ export interface ImageSettings {
198
198
  */
199
199
  product: ProductImageSettings;
200
200
  }
201
+ /**
202
+ * Margins around media widgets - the widgets that bring no spacing of their own, like images,
203
+ * sliders and videos. Applied per side, and only to widgets that ask for them.
204
+ */
205
+ export interface MediaMarginSettings {
206
+ /**
207
+ * Margin above the widget.
208
+ */
209
+ top: number;
210
+ /**
211
+ * Margin below the widget.
212
+ */
213
+ bottom: number;
214
+ /**
215
+ * Margin left of the widget.
216
+ */
217
+ left: number;
218
+ /**
219
+ * Margin right of the widget.
220
+ */
221
+ right: number;
222
+ }
223
+ /**
224
+ * Settings for the cms widgets.
225
+ */
226
+ export interface WidgetSettings {
227
+ /**
228
+ * Margins around media widgets.
229
+ */
230
+ mediaMargins: MediaMarginSettings;
231
+ }
201
232
  /**
202
233
  * Settings for the app's overall appearance.
203
234
  */
@@ -234,6 +265,10 @@ export interface AppSettings {
234
265
  cards: CardSettings;
235
266
  typography: TypographySettings;
236
267
  appearance: AppearanceSettings;
268
+ /**
269
+ * Settings for the cms widgets.
270
+ */
271
+ widgets: WidgetSettings;
237
272
  }
238
273
  /**
239
274
  * A font stylesheet to load. The file carries the `@font-face` rules and points its target at the
@@ -1 +1 @@
1
- {"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../../settings/types/appSettings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"appSettings.d.ts","sourceRoot":"","sources":["../../../settings/types/appSettings.ts"],"names":[],"mappings":"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"}
@@ -98,6 +98,15 @@ export const COLOR_SCHEME_SELECTABLE = 'selectable';
98
98
  * service, including category images, carrier logos and page builder widget images.
99
99
  */
100
100
 
101
+ /**
102
+ * Margins around media widgets - the widgets that bring no spacing of their own, like images,
103
+ * sliders and videos. Applied per side, and only to widgets that ask for them.
104
+ */
105
+
106
+ /**
107
+ * Settings for the cms widgets.
108
+ */
109
+
101
110
  /**
102
111
  * Settings for the app's overall appearance.
103
112
  */