@magento/pagebuilder 7.1.0-beta.1 → 7.2.0-beta.1

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 (48) hide show
  1. package/lib/ContentTypes/Banner/__tests__/__snapshots__/banner.shimmer.spec.js.snap +0 -1
  2. package/lib/ContentTypes/Banner/__tests__/__snapshots__/banner.spec.js.snap +0 -1
  3. package/lib/ContentTypes/Banner/banner.js +23 -4
  4. package/lib/ContentTypes/Banner/banner.shimmer.js +13 -2
  5. package/lib/ContentTypes/Banner/configAggregator.js +4 -2
  6. package/lib/ContentTypes/Column/column.js +13 -2
  7. package/lib/ContentTypes/Column/configAggregator.js +3 -1
  8. package/lib/ContentTypes/DynamicBlock/__tests__/__snapshots__/dynamicBlock.ce.spec.js.snap +3 -0
  9. package/lib/ContentTypes/DynamicBlock/__tests__/__snapshots__/dynamicBlock.ee.spec.js.snap +93 -0
  10. package/lib/ContentTypes/DynamicBlock/__tests__/__snapshots__/dynamicBlock.shimmer.spec.js.snap +39 -0
  11. package/lib/ContentTypes/DynamicBlock/__tests__/configAggregator.spec.js +49 -0
  12. package/lib/ContentTypes/DynamicBlock/__tests__/dynamicBlock.ce.spec.js +17 -0
  13. package/lib/ContentTypes/DynamicBlock/__tests__/dynamicBlock.ee.spec.js +70 -0
  14. package/lib/ContentTypes/DynamicBlock/__tests__/dynamicBlock.shimmer.spec.js +20 -0
  15. package/lib/ContentTypes/DynamicBlock/configAggregator.js +25 -0
  16. package/lib/ContentTypes/DynamicBlock/dynamicBlock.ce.js +5 -0
  17. package/lib/ContentTypes/DynamicBlock/dynamicBlock.ee.js +134 -0
  18. package/lib/ContentTypes/DynamicBlock/dynamicBlock.module.css +8 -0
  19. package/lib/ContentTypes/DynamicBlock/dynamicBlock.shimmer.js +134 -0
  20. package/lib/ContentTypes/DynamicBlock/dynamicBlock.shimmer.module.css +26 -0
  21. package/lib/ContentTypes/DynamicBlock/index.js +2 -0
  22. package/lib/ContentTypes/Image/__tests__/__snapshots__/image.shimmer.spec.js.snap +139 -0
  23. package/lib/ContentTypes/Image/__tests__/configAggregator.spec.js +28 -10
  24. package/lib/ContentTypes/Image/__tests__/image.shimmer.spec.js +122 -0
  25. package/lib/ContentTypes/Image/__tests__/image.spec.js +5 -5
  26. package/lib/ContentTypes/Image/configAggregator.js +51 -18
  27. package/lib/ContentTypes/Image/image.js +25 -9
  28. package/lib/ContentTypes/Image/image.module.css +2 -0
  29. package/lib/ContentTypes/Image/image.shimmer.js +191 -0
  30. package/lib/ContentTypes/Image/image.shimmer.module.css +5 -0
  31. package/lib/ContentTypes/Image/index.js +1 -0
  32. package/lib/ContentTypes/Row/__tests__/configAggregator.spec.js +18 -0
  33. package/lib/ContentTypes/Row/__tests__/row.spec.js +2 -1
  34. package/lib/ContentTypes/Row/configAggregator.js +13 -3
  35. package/lib/ContentTypes/Row/row.js +26 -3
  36. package/lib/ContentTypes/Slider/configAggregator.js +3 -2
  37. package/lib/ContentTypes/Slider/slider.js +21 -2
  38. package/lib/ContentTypes/Slider/slider.shimmer.js +13 -2
  39. package/lib/ContentTypes/TabItem/configAggregator.js +4 -2
  40. package/lib/ContentTypes/TabItem/tabItem.js +13 -2
  41. package/lib/ContentTypes/Tabs/configAggregator.js +4 -2
  42. package/lib/ContentTypes/Tabs/tabs.js +19 -2
  43. package/lib/__tests__/parseStorageHtml.spec.js +35 -0
  44. package/lib/__tests__/utils.spec.js +21 -1
  45. package/lib/config.js +10 -2
  46. package/lib/parseStorageHtml.js +32 -0
  47. package/lib/utils.js +46 -0
  48. package/package.json +8 -8
@@ -14,7 +14,7 @@ test('renders an empty Image component', () => {
14
14
 
15
15
  test('renders a Image component', () => {
16
16
  const imageProps = {
17
- desktopImage: 'test-image.png'
17
+ desktopImage: { src: 'test-image.png' }
18
18
  };
19
19
  const component = createTestInstance(<Image {...imageProps} />);
20
20
 
@@ -23,8 +23,8 @@ test('renders a Image component', () => {
23
23
 
24
24
  test('renders a Image component with all props configured', () => {
25
25
  const imageProps = {
26
- desktopImage: 'desktop-image.png',
27
- mobileImage: 'mobile-image.png',
26
+ desktopImage: { src: 'desktop-image.png' },
27
+ mobileImage: { src: 'mobile-image.png' },
28
28
  altText: 'Alt Text',
29
29
  title: 'Title Text',
30
30
  link: 'http://www.adobe.com/',
@@ -53,7 +53,7 @@ test('renders a Image component with all props configured', () => {
53
53
 
54
54
  test('renders a Image component with openInNewTab set to false', () => {
55
55
  const imageProps = {
56
- desktopImage: 'desktop-image.png',
56
+ desktopImage: { src: 'desktop-image.png' },
57
57
  link: 'http://www.adobe.com/',
58
58
  linkType: 'default',
59
59
  openInNewTab: false
@@ -65,7 +65,7 @@ test('renders a Image component with openInNewTab set to false', () => {
65
65
 
66
66
  test('renders a Image component with only mobile image', () => {
67
67
  const imageProps = {
68
- mobileImage: 'mobile-image.png'
68
+ mobileImage: { src: 'mobile-image.png' }
69
69
  };
70
70
  const component = createTestInstance(<Image {...imageProps} />);
71
71
 
@@ -4,7 +4,8 @@ import {
4
4
  getIsHidden,
5
5
  getMargin,
6
6
  getPadding,
7
- getTextAlign
7
+ getTextAlign,
8
+ getMediaQueries
8
9
  } from '../../utils';
9
10
 
10
11
  export default node => {
@@ -17,35 +18,67 @@ export default node => {
17
18
  ? node.childNodes[0].childNodes
18
19
  : node.childNodes;
19
20
 
20
- const mobileImageSrc = () => {
21
- if (imageNode[1]) {
22
- return imageNode[1].getAttribute('src');
21
+ const getImageData = imageNode => {
22
+ let imageDimension = null;
23
+ try {
24
+ imageDimension = JSON.parse(
25
+ imageNode.getAttribute('data-image-dimensions')
26
+ );
27
+ } catch (e) {
28
+ // Do nothing
23
29
  }
24
- if (imageNode[0]) {
25
- return imageNode[0].getAttribute('src');
30
+ return {
31
+ src: imageNode.getAttribute('src'),
32
+ dimensions: imageDimension
33
+ };
34
+ };
35
+
36
+ const getImageProps = () => {
37
+ const image = imageNode[0];
38
+ let imageProps = {
39
+ desktopImage: null,
40
+ mobileImage: null,
41
+ altText: null,
42
+ title: null
43
+ };
44
+ if (image) {
45
+ const imageData = getImageData(image);
46
+ if (image.getAttribute('data-element') === 'desktop_image') {
47
+ imageProps.desktopImage = imageData;
48
+ const image2 = imageNode[1];
49
+ if (
50
+ image2.getAttribute('data-element') === 'mobile_image' &&
51
+ image2.getAttribute('src') !== imageData.src
52
+ ) {
53
+ imageProps.mobileImage = getImageData(image2);
54
+ }
55
+ } else {
56
+ // If there is no desktop image
57
+ imageProps.mobileImage = imageData;
58
+ }
59
+ imageProps.altText = image.getAttribute('alt');
60
+ imageProps.title = image.getAttribute('title');
61
+ imageProps = {
62
+ ...imageProps,
63
+ ...getBorder(image)
64
+ };
26
65
  }
27
- return null;
66
+
67
+ return imageProps;
28
68
  };
29
69
 
30
70
  const props = {
31
- desktopImage:
32
- imageNode[0] && imageNode[1]
33
- ? imageNode[0].getAttribute('src')
34
- : null,
35
- mobileImage: mobileImageSrc(),
36
- altText: imageNode[0] ? imageNode[0].getAttribute('alt') : null,
37
- title: imageNode[0] ? imageNode[0].getAttribute('title') : null,
71
+ ...getImageProps(),
38
72
  openInNewTab: node.childNodes[0].getAttribute('target') === '_blank',
39
73
  ...getPadding(node),
40
74
  ...getMargin(node),
41
75
  ...(imageNode[0] ? getBorder(imageNode[0]) : []),
42
76
  ...getCssClasses(node),
43
77
  ...getTextAlign(node),
44
- ...getIsHidden(node)
78
+ ...getIsHidden(node),
79
+ ...getMediaQueries(node)
45
80
  };
46
- if (props.desktopImage === props.mobileImage) {
47
- props.mobileImage = null;
48
- }
81
+
49
82
  if (node.childNodes[0].nodeName === 'A') {
50
83
  props.link = node.childNodes[0].getAttribute('href');
51
84
  props.linkType = node.childNodes[0].getAttribute('data-link-type');
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import defaultClasses from './image.module.css';
3
- import { arrayOf, bool, oneOf, shape, string } from 'prop-types';
3
+ import { arrayOf, bool, oneOf, shape, string, number } from 'prop-types';
4
4
  import { Link } from 'react-router-dom';
5
5
  import resolveLinkProps from '../../resolveLinkProps';
6
6
  import { useStyle } from '@magento/venia-ui/lib/classify';
@@ -67,10 +67,10 @@ const Image = props => {
67
67
  return null;
68
68
  }
69
69
 
70
- const SourceFragment = mobileImage ? (
70
+ const MobileSourceFragment = mobileImage ? (
71
71
  <source
72
72
  media="(max-width: 48rem)"
73
- srcSet={resourceUrl(mobileImage, {
73
+ srcSet={resourceUrl(mobileImage.src, {
74
74
  type: 'image-wysiwyg',
75
75
  quality: 85
76
76
  })}
@@ -80,7 +80,7 @@ const Image = props => {
80
80
  );
81
81
 
82
82
  const imgSrc = desktopImage
83
- ? resourceUrl(desktopImage, {
83
+ ? resourceUrl(desktopImage.src, {
84
84
  type: 'image-wysiwyg',
85
85
  quality: 85
86
86
  })
@@ -94,7 +94,7 @@ const Image = props => {
94
94
  const PictureFragment = (
95
95
  <>
96
96
  <picture>
97
- {SourceFragment}
97
+ {MobileSourceFragment}
98
98
  <img
99
99
  className={imgClassName}
100
100
  srcSet={`${imgSrc} 1x`}
@@ -115,6 +115,7 @@ const Image = props => {
115
115
 
116
116
  return (
117
117
  <figure
118
+ data-cy="PageBuilder-Image-root"
118
119
  style={figureStyles}
119
120
  className={[classes.root, ...cssClasses].join(' ')}
120
121
  >
@@ -129,6 +130,7 @@ const Image = props => {
129
130
  } else {
130
131
  return (
131
132
  <figure
133
+ data-cy="PageBuilder-Image-root"
132
134
  style={figureStyles}
133
135
  className={[classes.root, ...cssClasses].join(' ')}
134
136
  >
@@ -145,8 +147,8 @@ const Image = props => {
145
147
  *
146
148
  * @property {Object} classes An object containing the class names for the Image
147
149
  * @property {String} classes.img CSS classes for the img element
148
- * @property {String} desktopImage URL src of the desktop image
149
- * @property {String} mobileImage URL src of the mobile image
150
+ * @property {Object} desktopImage desktop image URL src and dimensions
151
+ * @property {Object} mobileImage mobile image URL src and dimensions
150
152
  * @property {String} altText Alternate text
151
153
  * @property {String} title Title of the image
152
154
  * @property {String} link URL to redirect to
@@ -174,8 +176,22 @@ Image.propTypes = {
174
176
  img: string,
175
177
  mobileOnly: string
176
178
  }),
177
- desktopImage: string,
178
- mobileImage: string,
179
+ desktopImage: shape({
180
+ src: string,
181
+ dimensions: shape({
182
+ height: number,
183
+ ratio: number,
184
+ width: number
185
+ })
186
+ }),
187
+ mobileImage: shape({
188
+ src: string,
189
+ dimensions: shape({
190
+ height: number,
191
+ ratio: number,
192
+ width: number
193
+ })
194
+ }),
179
195
  altText: string,
180
196
  title: string,
181
197
  link: string,
@@ -3,6 +3,8 @@
3
3
  }
4
4
  .img {
5
5
  max-width: 100%;
6
+ vertical-align: middle;
7
+ display: inline-block;
6
8
  }
7
9
 
8
10
  @media (min-width: 48rem) {
@@ -0,0 +1,191 @@
1
+ import React, { useMemo, useRef, useEffect } from 'react';
2
+ import { arrayOf, shape, string, number } from 'prop-types';
3
+ import defaultClasses from './image.shimmer.module.css';
4
+ import { useStyle } from '@magento/venia-ui/lib/classify';
5
+ import Shimmer from '@magento/venia-ui/lib/components/Shimmer';
6
+
7
+ /**
8
+ * Page Builder Image Shimmer component.
9
+ *
10
+ * @typedef ImageShimmer
11
+ * @kind functional component
12
+ *
13
+ * @param {props} props React component props
14
+ *
15
+ * @returns {React.Element|null} A React component that displays an Image Shimmer.
16
+ */
17
+ const ImageShimmer = props => {
18
+ const classes = useStyle(defaultClasses, props.classes);
19
+ const {
20
+ desktopImage,
21
+ mobileImage,
22
+ textAlign,
23
+ border,
24
+ borderColor,
25
+ borderWidth,
26
+ borderRadius,
27
+ marginTop,
28
+ marginRight,
29
+ marginBottom,
30
+ marginLeft,
31
+ paddingTop,
32
+ paddingRight,
33
+ paddingBottom,
34
+ paddingLeft,
35
+ cssClasses = []
36
+ } = props;
37
+
38
+ const figureStyles = {
39
+ textAlign,
40
+ marginTop,
41
+ marginRight,
42
+ marginBottom,
43
+ marginLeft,
44
+ paddingTop,
45
+ paddingRight,
46
+ paddingBottom,
47
+ paddingLeft
48
+ };
49
+ const imageStyles = {
50
+ border,
51
+ borderColor,
52
+ borderWidth,
53
+ borderRadius
54
+ };
55
+
56
+ const figureRef = useRef();
57
+
58
+ const dimensions = useMemo(() => {
59
+ const value = {
60
+ height: 0,
61
+ width: 0
62
+ };
63
+ if (
64
+ window.matchMedia('(max-width: 48rem)').matches &&
65
+ mobileImage &&
66
+ mobileImage.dimensions
67
+ ) {
68
+ value.width = mobileImage.dimensions.width;
69
+ value.height = mobileImage.dimensions.height;
70
+ } else if (desktopImage && desktopImage.dimensions) {
71
+ value.width = desktopImage.dimensions.width;
72
+ value.height = desktopImage.dimensions.height;
73
+ } else {
74
+ return null;
75
+ }
76
+ return value;
77
+ }, [desktopImage, mobileImage]);
78
+
79
+ useEffect(() => {
80
+ if (figureRef.current) {
81
+ const width = figureRef.current.offsetWidth;
82
+ if (dimensions.width > width) {
83
+ if (
84
+ window.matchMedia('(max-width: 48rem)').matches &&
85
+ mobileImage &&
86
+ mobileImage.dimensions
87
+ ) {
88
+ dimensions.width = width;
89
+ dimensions.height =
90
+ dimensions.width * mobileImage.dimensions.ratio;
91
+ } else if (desktopImage && desktopImage.dimensions) {
92
+ dimensions.width = width;
93
+ dimensions.height =
94
+ dimensions.width * desktopImage.dimensions.ratio;
95
+ }
96
+ }
97
+ }
98
+ }, [desktopImage, dimensions, mobileImage]);
99
+
100
+ if (!dimensions) {
101
+ return null;
102
+ }
103
+
104
+ return (
105
+ <figure style={figureStyles} ref={figureRef}>
106
+ <Shimmer
107
+ aria-live="polite"
108
+ aria-busy="true"
109
+ classes={{
110
+ root_rectangle: [
111
+ classes.root,
112
+ classes.shimmerRoot,
113
+ ...cssClasses
114
+ ].join(' ')
115
+ }}
116
+ style={imageStyles}
117
+ height={dimensions.height + 'px'}
118
+ width={dimensions.width + 'px'}
119
+ />
120
+ </figure>
121
+ );
122
+ };
123
+
124
+ /**
125
+ * Props for {@link ImageShimmer}
126
+ *
127
+ * * @typedef props
128
+ * *
129
+ * * @property {Object} classes An object containing the class names for the Image
130
+ * * @property {String} classes.img CSS classes for the img element
131
+ * * @property {Object} desktopImage desktop image URL src and dimensions
132
+ * * @property {Object} mobileImage mobile image URL src and dimensions
133
+ * * @property {String} altText Alternate text
134
+ * * @property {String} textAlign Alignment of the divider within the parent container
135
+ * * @property {String} border CSS border property
136
+ * * @property {String} borderColor CSS border color property
137
+ * * @property {String} borderWidth CSS border width property
138
+ * * @property {String} borderRadius CSS border radius property
139
+ * * @property {String} marginTop CSS margin top property
140
+ * * @property {String} marginRight CSS margin right property
141
+ * * @property {String} marginBottom CSS margin bottom property
142
+ * * @property {String} marginLeft CSS margin left property
143
+ * * @property {String} paddingTop CSS padding top property
144
+ * * @property {String} paddingRight CSS padding right property
145
+ * * @property {String} paddingBottom CSS padding bottom property
146
+ * * @property {String} paddingLeft CSS padding left property
147
+ * * @property {Array} cssClasses List of CSS classes to be applied to the component
148
+ * */
149
+ ImageShimmer.propTypes = {
150
+ classes: shape({
151
+ root: string,
152
+ shimmerRoot: string,
153
+ overlay: string,
154
+ content: string,
155
+ wrapper: string,
156
+ img: string,
157
+ mobileOnly: string
158
+ }),
159
+ desktopImage: shape({
160
+ src: string,
161
+ dimensions: shape({
162
+ height: number,
163
+ ratio: number,
164
+ width: number
165
+ })
166
+ }),
167
+ mobileImage: shape({
168
+ src: string,
169
+ dimensions: shape({
170
+ height: number,
171
+ ratio: number,
172
+ width: number
173
+ })
174
+ }),
175
+ altText: string,
176
+ textAlign: string,
177
+ border: string,
178
+ borderColor: string,
179
+ borderWidth: string,
180
+ borderRadius: string,
181
+ marginTop: string,
182
+ marginRight: string,
183
+ marginBottom: string,
184
+ marginLeft: string,
185
+ paddingTop: string,
186
+ paddingRight: string,
187
+ paddingBottom: string,
188
+ cssClasses: arrayOf(string)
189
+ };
190
+
191
+ export default ImageShimmer;
@@ -0,0 +1,5 @@
1
+ .shimmerRoot {
2
+ composes: root_rectangle from '~@magento/venia-ui/lib/components/Shimmer/shimmer.module.css';
3
+ composes: root img from './image.module.css';
4
+ margin: 1rem 0;
5
+ }
@@ -1 +1,2 @@
1
1
  export { default } from './image';
2
+ export { default as ImageShimmer } from './image.shimmer';
@@ -93,3 +93,21 @@ test('config is aggregated correctly for row appearance == full-width with video
93
93
  })
94
94
  );
95
95
  });
96
+
97
+ test('config is aggregated correctly for row containing dynamic block', () => {
98
+ const node = document.createElement('div');
99
+ node.innerHTML = `<div data-content-type="row" data-appearance="contained" data-element="main"><div class="class1 class2" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-element="inner" style="justify-content: flex-start; display: flex; flex-direction: column; background-position: left top; background-size: cover; background-repeat: no-repeat; background-attachment: scroll; text-align: right; border-style: dashed; border-color: rgb(252, 0, 9); border-width: 20px; border-radius: 30px; margin: 5px; padding: 10px; min-height: 40px;"><div data-content-type="dynamic_block" data-appearance="default" data-element="main">{{widget type="Magento\\Banner\\Block\\Widget\\Banner" display_mode="fixed" rotate="" template="widget/block.phtml" banner_ids="2" unique_id="2" type_name="Dynamic Blocks Rotator"}}</div></div></div>`;
100
+ const config = configAggregator(node.childNodes[0], {
101
+ appearance: 'contained'
102
+ });
103
+
104
+ // minHeight should be null, minHeight is managed by dynamicBlock
105
+ expect(config).toEqual(
106
+ expect.objectContaining({
107
+ minHeight: null,
108
+ backgroundColor: null,
109
+ enableParallax: false,
110
+ parallaxSpeed: 0.5
111
+ })
112
+ );
113
+ });
@@ -75,7 +75,8 @@ test('render row with parallax initializes JarallaxVideo', () => {
75
75
  videoLazyLoading: true,
76
76
  videoLoop: true,
77
77
  videoPlayOnlyVisible: true,
78
- videoSrc: 'https://example.video'
78
+ videoSrc: 'https://example.video',
79
+ zIndex: 'auto'
79
80
  });
80
81
  });
81
82
 
@@ -2,7 +2,8 @@ import {
2
2
  getAdvanced,
3
3
  getBackgroundImages,
4
4
  getVerticalAlignment,
5
- getIsHidden
5
+ getIsHidden,
6
+ getMediaQueries
6
7
  } from '../../utils';
7
8
 
8
9
  export default (node, props) => {
@@ -16,8 +17,16 @@ export default (node, props) => {
16
17
  : dataNode.childNodes[0] &&
17
18
  dataNode.childNodes[0].getAttribute('data-video-overlay-color');
18
19
 
20
+ const minHeight = dataNode.style.minHeight
21
+ ? dataNode.style.minHeight
22
+ : null;
23
+
24
+ const containsDynamicBlock = [...dataNode.childNodes].some(e => {
25
+ return e.getAttribute('data-content-type') === 'dynamic_block';
26
+ });
27
+
19
28
  return {
20
- minHeight: dataNode.style.minHeight ? dataNode.style.minHeight : null,
29
+ minHeight: containsDynamicBlock ? null : minHeight,
21
30
  ...getVerticalAlignment(dataNode),
22
31
  backgroundColor: dataNode.style.backgroundColor
23
32
  ? dataNode.style.backgroundColor
@@ -35,6 +44,7 @@ export default (node, props) => {
35
44
  dataNode.getAttribute('data-video-lazy-load') === 'true',
36
45
  videoOverlayColor: videoOverlayColor || null,
37
46
  ...getAdvanced(dataNode),
38
- ...getIsHidden(node)
47
+ ...getIsHidden(node),
48
+ ...getMediaQueries(dataNode)
39
49
  };
40
50
  };
@@ -2,9 +2,18 @@ import React, { useEffect, useRef, useState } from 'react';
2
2
  import defaultClasses from './row.module.css';
3
3
  import { verticalAlignmentToFlex } from '../../utils';
4
4
  import { useStyle } from '@magento/venia-ui/lib/classify';
5
- import { arrayOf, oneOf, shape, bool, string, number } from 'prop-types';
5
+ import {
6
+ arrayOf,
7
+ oneOf,
8
+ shape,
9
+ bool,
10
+ string,
11
+ number,
12
+ object
13
+ } from 'prop-types';
6
14
  import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
7
15
  import { useDetectScrollWidth } from '@magento/peregrine/lib/hooks/useDetectScrollWidth';
16
+ import { useMediaQuery } from '@magento/peregrine/lib/hooks/useMediaQuery';
8
17
 
9
18
  const { matchMedia } = globalThis;
10
19
 
@@ -24,6 +33,7 @@ const Row = props => {
24
33
  const backgroundElement = useRef(null);
25
34
  const [bgImageStyle, setBgImageStyle] = useState(null);
26
35
  const classes = useStyle(defaultClasses, props.classes);
36
+
27
37
  const {
28
38
  appearance,
29
39
  verticalAlignment,
@@ -46,6 +56,7 @@ const Row = props => {
46
56
  marginRight,
47
57
  marginBottom,
48
58
  marginLeft,
59
+ mediaQueries,
49
60
  paddingTop,
50
61
  paddingRight,
51
62
  paddingBottom,
@@ -61,6 +72,8 @@ const Row = props => {
61
72
  videoOverlayColor
62
73
  } = props;
63
74
 
75
+ const { styles: mediaQueryStyles } = useMediaQuery({ mediaQueries });
76
+
64
77
  let image = desktopImage;
65
78
  if (mobileImage && matchMedia && matchMedia('(max-width: 768px)').matches) {
66
79
  image = mobileImage;
@@ -171,7 +184,8 @@ const Row = props => {
171
184
  videoSrc,
172
185
  videoLoop,
173
186
  videoPlayOnlyVisible,
174
- videoLazyLoading
187
+ videoLazyLoading,
188
+ zIndex: 'auto'
175
189
  });
176
190
 
177
191
  parallaxElement.jarallax.video &&
@@ -218,6 +232,7 @@ const Row = props => {
218
232
  ref={backgroundElement}
219
233
  style={{
220
234
  ...dynamicStyles,
235
+ ...mediaQueryStyles,
221
236
  marginLeft: null,
222
237
  marginRight: null,
223
238
  '--pbRowMarginLeft': marginLeft,
@@ -241,6 +256,7 @@ const Row = props => {
241
256
  ref={backgroundElement}
242
257
  style={{
243
258
  ...dynamicStyles,
259
+ ...mediaQueryStyles,
244
260
  marginLeft: null,
245
261
  marginRight: null,
246
262
  '--pbRowMarginLeft': marginLeft,
@@ -263,7 +279,7 @@ const Row = props => {
263
279
  <div
264
280
  ref={backgroundElement}
265
281
  className={classes.inner}
266
- style={dynamicStyles}
282
+ style={{ ...dynamicStyles, ...mediaQueryStyles }}
267
283
  >
268
284
  {videoOverlay}
269
285
  {children}
@@ -301,6 +317,7 @@ const Row = props => {
301
317
  * @property {String} marginRight CSS margin right property
302
318
  * @property {String} marginBottom CSS margin bottom property
303
319
  * @property {String} marginLeft CSS margin left property
320
+ * @property {Array} mediaQueries List of media query rules to be applied to the component
304
321
  * @property {String} paddingTop CSS padding top property
305
322
  * @property {String} paddingRight CSS padding right property
306
323
  * @property {String} paddingBottom CSS padding bottom property
@@ -343,6 +360,12 @@ Row.propTypes = {
343
360
  marginRight: string,
344
361
  marginBottom: string,
345
362
  marginLeft: string,
363
+ mediaQueries: arrayOf(
364
+ shape({
365
+ media: string,
366
+ style: object
367
+ })
368
+ ),
346
369
  paddingTop: string,
347
370
  paddingRight: string,
348
371
  paddingBottom: string,
@@ -1,4 +1,4 @@
1
- import { getAdvanced } from '../../utils';
1
+ import { getAdvanced, getMediaQueries } from '../../utils';
2
2
 
3
3
  export default node => {
4
4
  const autoplaySpeed = parseInt(node.getAttribute('data-autoplay-speed'));
@@ -11,6 +11,7 @@ export default node => {
11
11
  showArrows: node.getAttribute('data-show-arrows') === 'true',
12
12
  showDots: node.getAttribute('data-show-dots') === 'true',
13
13
  ...(!isNaN(autoplaySpeed) && { autoplaySpeed }),
14
- ...getAdvanced(node)
14
+ ...getAdvanced(node),
15
+ ...getMediaQueries(node)
15
16
  };
16
17
  };
@@ -1,8 +1,17 @@
1
1
  import React, { Children } from 'react';
2
- import { arrayOf, bool, number, oneOf, shape, string } from 'prop-types';
2
+ import {
3
+ arrayOf,
4
+ bool,
5
+ number,
6
+ oneOf,
7
+ shape,
8
+ string,
9
+ object
10
+ } from 'prop-types';
3
11
  import SlickSlider from 'react-slick';
4
12
  import defaultClasses from './slider.module.css';
5
13
  import { useStyle } from '@magento/venia-ui/lib/classify';
14
+ import { useMediaQuery } from '@magento/peregrine/lib/hooks/useMediaQuery';
6
15
  import { jarallax } from 'jarallax';
7
16
 
8
17
  /**
@@ -37,6 +46,7 @@ const Slider = props => {
37
46
  marginRight,
38
47
  marginBottom,
39
48
  marginLeft,
49
+ mediaQueries,
40
50
  paddingTop,
41
51
  paddingRight,
42
52
  paddingBottom,
@@ -45,6 +55,8 @@ const Slider = props => {
45
55
  children
46
56
  } = props;
47
57
 
58
+ const { styles: mediaQueryStyles } = useMediaQuery({ mediaQueries });
59
+
48
60
  const dynamicStyles = {
49
61
  minHeight,
50
62
  textAlign,
@@ -101,7 +113,7 @@ const Slider = props => {
101
113
  aria-live="polite"
102
114
  aria-busy="false"
103
115
  className={[classes.root, ...cssClasses].join(' ')}
104
- style={dynamicStyles}
116
+ style={{ ...dynamicStyles, ...mediaQueryStyles }}
105
117
  >
106
118
  <SlickSlider {...sliderSettings}>{children}</SlickSlider>
107
119
  </div>
@@ -135,6 +147,7 @@ const Slider = props => {
135
147
  * @property {String} marginRight CSS margin right property
136
148
  * @property {String} marginBottom CSS margin bottom property
137
149
  * @property {String} marginLeft CSS margin left property
150
+ * @property {Array} mediaQueries List of media query rules to be applied to the component
138
151
  * @property {String} paddingTop CSS padding top property
139
152
  * @property {String} paddingRight CSS padding right property
140
153
  * @property {String} paddingBottom CSS padding bottom property
@@ -166,6 +179,12 @@ Slider.propTypes = {
166
179
  marginRight: string,
167
180
  marginBottom: string,
168
181
  marginLeft: string,
182
+ mediaQueries: arrayOf(
183
+ shape({
184
+ media: string,
185
+ style: object
186
+ })
187
+ ),
169
188
  paddingTop: string,
170
189
  paddingRight: string,
171
190
  paddingBottom: string,