From 693364c15b27777cfa7100994221eacf4e366d6d Mon Sep 17 00:00:00 2001 From: Cari Spruiell Date: Tue, 1 Oct 2019 14:18:58 -0500 Subject: [PATCH 01/13] PB-17: Banner content type in Venia UI / PWA Studio --- .../ContentTypes/Banner/banner.css | 43 +++++ .../PageBuilder/ContentTypes/Banner/banner.js | 152 ++++++++++++++++++ .../ContentTypes/Banner/configAggregator.js | 19 +++ .../PageBuilder/ContentTypes/Banner/index.js | 1 + .../RichContent/PageBuilder/config.js | 5 + 5 files changed, 220 insertions(+) create mode 100644 packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css create mode 100644 packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js create mode 100644 packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js create mode 100644 packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/index.js diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css new file mode 100644 index 0000000000..02374673f0 --- /dev/null +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css @@ -0,0 +1,43 @@ +.pagebuilder-banner-wrapper { + background-clip: padding-box; + border-radius: inherit; + box-sizing: border-box; + overflow-wrap: break-word; + word-wrap: break-word; + + .pagebuilder-overlay { + -moz-transition: background-color 500ms ease; + -o-transition: background-color 500ms ease; + -webkit-transition: background-color 500ms ease; + box-sizing: border-box; + padding: 30px; + transition: background-color 500ms ease; + + &.pagebuilder-poster-overlay { + align-items: center; + display: flex; + justify-content: center; + } + + &:not(.pagebuilder-poster-overlay) { + max-width: 540px; + } + + } + + [data-element='content'] { + min-height: 50px; + } + + .pagebuilder-banner-button { + -moz-transition: opacity 500ms ease; + -o-transition: opacity 500ms ease; + -webkit-transition: opacity 500ms ease; + margin: 20px 0 0 0; + max-width: 100%; + text-align: inherit; + transition: opacity 500ms ease; + word-break: break-word; + } + +} diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js new file mode 100644 index 0000000000..197ba2ddcd --- /dev/null +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -0,0 +1,152 @@ +import React from 'react'; +import {arrayOf, bool, oneOf, shape, string} from 'prop-types'; + +/** + * Page Builder Banner component. + * + * This component is part of the Page Builder / PWA integration. It can be consumed without Page Builder. + * + * @typedef Banner + * @kind functional component + * + * @param {props} props React component props + * + * @returns {React.Element} A React component that displays a Banner. + */ +const Banner = props => { + const { + appearance = 'poster', + minHeight, + backgroundColor, + desktopImage, + mobileImage, + backgroundSize, + backgroundPosition, + backgroundAttachment, + backgroundRepeat, + textAlign, + border, + borderColor, + borderWidth, + borderRadius, + marginTop, + marginRight, + marginBottom, + marginLeft, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + cssClasses = [] + } = props; + + let image = desktopImage; + if ( + mobileImage && + typeof window.matchMedia === 'function' && + window.matchMedia('(max-width: 768px)').matches + ) { + image = mobileImage; + } + + const dynamicStyles = { + minHeight: minHeight, + backgroundColor: backgroundColor, + textAlign, + border, + borderColor, + borderWidth, + borderRadius, + marginTop, + marginRight, + marginBottom, + marginLeft, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + backgroundImage: image ? `url(${image})` : null, + backgroundSize, + backgroundPosition, + backgroundAttachment, + backgroundRepeat: backgroundRepeat ? 'repeat' : 'no-repeat' + }; + + if (appearance === 'poster') { + cssClasses.push(classes.poster); + } + + let children = props.children; + if (appearance === 'poster') { + children =
{children}
; + style + } + + return ( +
+ {children} +
+ ); +}; + +/** + * Props for {@link Banner} + * + * @typedef props + * + * @property {Object} classes An object containing the class names for the banner + * @property {String} classes.poster CSS class for the poster appearance element + * @property {String} classes.root CSS class for the banner root element + * @property {String} minHeight CSS minimum height property + * @property {String} backgroundColor CSS background-color property + * @property {String} desktopImage Background image URL to be displayed on desktop devices + * @property {String} mobileImage Background image URL to be displayed on mobile devices + * @property {String} backgroundSize CSS background-size property + * @property {String} backgroundPosition CSS background-position property + * @property {String} backgroundAttachment CSS background-attachment property + * @property {Boolean} backgroundRepeat CSS background-repeat property + * @property {String} textAlign Alignment of the block within the parent container + * @property {String} border CSS border property + * @property {String} borderColor CSS border color property + * @property {String} borderWidth CSS border width property + * @property {String} borderRadius CSS border radius property + * @property {String} marginTop CSS margin top property + * @property {String} marginRight CSS margin right property + * @property {String} marginBottom CSS margin bottom property + * @property {String} marginLeft CSS margin left property + * @property {String} paddingTop CSS padding top property + * @property {String} paddingRight CSS padding right property + * @property {String} paddingBottom CSS padding bottom property + * @property {String} paddingLeft CSS padding left property + * @property {Array} cssClasses List of CSS classes to be applied to the component + */ +Banner.propTypes = { + classes: shape({ + root: string, + appearance: string + }), + appearance: oneOf(['poster', 'collage-left', 'collage-center', 'collage-right']), + minHeight: string, + backgroundColor: string, + desktopImage: string, + mobileImage: string, + backgroundSize: string, + backgroundPosition: string, + backgroundAttachment: string, + backgroundRepeat: bool, + textAlign: string, + border: string, + borderColor: string, + borderWidth: string, + borderRadius: string, + marginTop: string, + marginRight: string, + marginBottom: string, + marginLeft: string, + paddingTop: string, + paddingRight: string, + paddingBottom: string, + cssClasses: arrayOf(string) +}; + +export default Banner; diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js new file mode 100644 index 0000000000..bf755972eb --- /dev/null +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -0,0 +1,19 @@ +import { + getAdvanced, + getBackgroundImages +} from '../../utils'; + +export default (node, props) => { + // Determine which node holds the data for the appearance + const dataNode = + props.appearance === 'poster' ? node.childNodes[0] : node; + return { + appearance: props.appearance, + // minHeight: dataNode.style.minHeight ? dataNode.style.minHeight : null, + backgroundColor: dataNode.style.backgroundColor + ? dataNode.style.backgroundColor + : null, + ...getBackgroundImages(dataNode), + ...getAdvanced(dataNode) + }; +}; diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/index.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/index.js new file mode 100644 index 0000000000..13570240a3 --- /dev/null +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/index.js @@ -0,0 +1 @@ +export { default } from './banner'; diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/config.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/config.js index 5230868115..2dc16e7286 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/config.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/config.js @@ -20,6 +20,7 @@ import buttonItemConfigAggregator from './ContentTypes/ButtonItem/configAggregat import htmlConfigAggregator from './ContentTypes/Html/configAggregator'; import dividerConfigAggregator from './ContentTypes/Divider/configAggregator'; import videoConfigAggregator from './ContentTypes/Video/configAggregator'; +import bannerConfigAggregator from './ContentTypes/Banner/configAggregator'; export const contentTypesConfig = { row: { @@ -81,6 +82,10 @@ export const contentTypesConfig = { video: { configAggregator: videoConfigAggregator, component: React.lazy(() => import('./ContentTypes/Video')) + }, + banner: { + configAggregator: bannerConfigAggregator, + component: React.lazy(() => import('./ContentTypes/Banner')) } }; From dd7e2b23203b9c98720f8764dacd0a00d14a8f69 Mon Sep 17 00:00:00 2001 From: Cari Spruiell Date: Tue, 1 Oct 2019 14:25:10 -0500 Subject: [PATCH 02/13] PB-17: Banner content type in Venia UI / PWA Studio --- .../PageBuilder/ContentTypes/Banner/banner.css | 2 -- .../PageBuilder/ContentTypes/Banner/banner.js | 10 +++++++--- .../ContentTypes/Banner/configAggregator.js | 8 ++------ 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css index 02374673f0..9bc6f83bbf 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css @@ -22,7 +22,6 @@ &:not(.pagebuilder-poster-overlay) { max-width: 540px; } - } [data-element='content'] { @@ -39,5 +38,4 @@ transition: opacity 500ms ease; word-break: break-word; } - } diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index 197ba2ddcd..470c1bdebd 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -1,5 +1,5 @@ import React from 'react'; -import {arrayOf, bool, oneOf, shape, string} from 'prop-types'; +import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; /** * Page Builder Banner component. @@ -79,7 +79,6 @@ const Banner = props => { let children = props.children; if (appearance === 'poster') { children =
{children}
; - style } return ( @@ -125,7 +124,12 @@ Banner.propTypes = { root: string, appearance: string }), - appearance: oneOf(['poster', 'collage-left', 'collage-center', 'collage-right']), + appearance: oneOf([ + 'poster', + 'collage-left', + 'collage-center', + 'collage-right' + ]), minHeight: string, backgroundColor: string, desktopImage: string, diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index bf755972eb..074fa72f9c 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -1,12 +1,8 @@ -import { - getAdvanced, - getBackgroundImages -} from '../../utils'; +import { getAdvanced, getBackgroundImages } from '../../utils'; export default (node, props) => { // Determine which node holds the data for the appearance - const dataNode = - props.appearance === 'poster' ? node.childNodes[0] : node; + const dataNode = props.appearance === 'poster' ? node.childNodes[0] : node; return { appearance: props.appearance, // minHeight: dataNode.style.minHeight ? dataNode.style.minHeight : null, From 079695cc54dd001787b4ce7ed4936966c2464cac Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Tue, 1 Oct 2019 16:37:31 -0500 Subject: [PATCH 03/13] PB-17: Banner content type in Venia UI / PWA Studio --- .../PageBuilder/ContentTypes/Banner/banner.js | 75 +------------------ .../ContentTypes/Banner/configAggregator.js | 26 ++++--- 2 files changed, 17 insertions(+), 84 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index 470c1bdebd..e587642d9a 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -14,78 +14,7 @@ import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; * @returns {React.Element} A React component that displays a Banner. */ const Banner = props => { - const { - appearance = 'poster', - minHeight, - backgroundColor, - desktopImage, - mobileImage, - backgroundSize, - backgroundPosition, - backgroundAttachment, - backgroundRepeat, - textAlign, - border, - borderColor, - borderWidth, - borderRadius, - marginTop, - marginRight, - marginBottom, - marginLeft, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - cssClasses = [] - } = props; - - let image = desktopImage; - if ( - mobileImage && - typeof window.matchMedia === 'function' && - window.matchMedia('(max-width: 768px)').matches - ) { - image = mobileImage; - } - - const dynamicStyles = { - minHeight: minHeight, - backgroundColor: backgroundColor, - textAlign, - border, - borderColor, - borderWidth, - borderRadius, - marginTop, - marginRight, - marginBottom, - marginLeft, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - backgroundImage: image ? `url(${image})` : null, - backgroundSize, - backgroundPosition, - backgroundAttachment, - backgroundRepeat: backgroundRepeat ? 'repeat' : 'no-repeat' - }; - - if (appearance === 'poster') { - cssClasses.push(classes.poster); - } - - let children = props.children; - if (appearance === 'poster') { - children =
{children}
; - } - - return ( -
- {children} -
- ); + return null; }; /** @@ -127,7 +56,7 @@ Banner.propTypes = { appearance: oneOf([ 'poster', 'collage-left', - 'collage-center', + 'collage-centered', 'collage-right' ]), minHeight: string, diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 074fa72f9c..3feffb11da 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -1,15 +1,19 @@ -import { getAdvanced, getBackgroundImages } from '../../utils'; +import {getMargin, getBackgroundImages, getBorder, getPadding} from '../../utils'; export default (node, props) => { - // Determine which node holds the data for the appearance - const dataNode = props.appearance === 'poster' ? node.childNodes[0] : node; - return { - appearance: props.appearance, - // minHeight: dataNode.style.minHeight ? dataNode.style.minHeight : null, - backgroundColor: dataNode.style.backgroundColor - ? dataNode.style.backgroundColor - : null, - ...getBackgroundImages(dataNode), - ...getAdvanced(dataNode) + console.log(props.appearance, node); + const wrapper = node.querySelector('[data-element="wrapper"]'); + const overlay = node.querySelector('[data-element="overlay"]'); + const response = { + minHeight: overlay.style.minHeight ? overlay.style.minHeight : null, + content: node.querySelector('[data-element="content"]').innerHTML, + showButton: node.getAttribute('data-show-button'), + showOverlay: node.getAttribute('data-show-overlay'), + ...getBackgroundImages(wrapper), + ...getBorder(wrapper), + ...getMargin(node), + ...getPadding(overlay), }; + console.log(response); + return response; }; From 5f76519da2c4548714d31ec3486897a7d345c9ed Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Wed, 2 Oct 2019 10:03:06 -0500 Subject: [PATCH 04/13] PB-17: Banner content type in Venia UI / PWA Studio - Complete configAggregator for banner --- .../Banner/__tests__/configAggregator.spec.js | 226 ++++++++++++++++++ .../ContentTypes/Banner/configAggregator.js | 73 ++++-- 2 files changed, 285 insertions(+), 14 deletions(-) create mode 100644 packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js new file mode 100644 index 0000000000..252eb645e6 --- /dev/null +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js @@ -0,0 +1,226 @@ +import configAggregator from '../configAggregator'; + +test('banner config aggregator retrieves default values from empty banner content type', () => { + const node = document.createElement('div'); + node.innerHTML = + '
'; + expect( + configAggregator(node.childNodes[0], { + appearance: 'poster' + }) + ).toEqual( + expect.objectContaining({ + backgroundAttachment: 'scroll', + backgroundPosition: 'left top', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'none', + borderColor: '', + borderRadius: '0px', + borderWidth: '1px', + buttonText: null, + buttonType: null, + content: '', + cssClasses: [], + desktopImage: null, + link: null, + linkType: null, + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + minHeight: '300px', + mobileImage: null, + overlayColor: null, + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', + showButton: 'never', + showOverlay: 'never', + textAlign: '' + }) + ); +}); + +test('banner config aggregator retrieves values from fully configured poster banner content type', () => { + const node = document.createElement('div'); + node.innerHTML = + '

A new way of shopping

Experience the best way of shopping today!

'; + expect( + configAggregator(node.childNodes[0], { + appearance: 'poster' + }) + ).toEqual( + expect.objectContaining({ + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'none', + borderColor: '', + borderRadius: '0px', + borderWidth: '1px', + buttonText: 'Shop Bags', + buttonType: 'primary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: 'desktop-image.jpg', + link: 'gear/bags.html', + linkType: 'category', + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', + overlayColor: null, + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', + showButton: 'always', + showOverlay: 'never', + textAlign: '' + }) + ); +}); + +test('banner config aggregator retrieves values from fully configured collage-left banner content type', () => { + const node = document.createElement('div'); + node.innerHTML = + '

A new way of shopping

Experience the best way of shopping today!

'; + expect( + configAggregator(node.childNodes[0], { + appearance: 'collage-left' + }) + ).toEqual( + expect.objectContaining({ + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'none', + borderColor: '', + borderRadius: '0px', + borderWidth: '1px', + buttonText: 'Shop Bags', + buttonType: 'primary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: + 'https://pagebuilder.test/media/wysiwyg/enhanced-storefront.jpg', + link: 'https://pagebuilder.test/gear/bags.html', + linkType: 'category', + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + minHeight: null, + mobileImage: + 'https://pagebuilder.test/media/wysiwyg/blake-wisz-Kx3o6_m1Yv8-unsplash.jpg', + overlayColor: 'rgba(255, 255, 255, 0.25)', + paddingBottom: '', + paddingLeft: '', + paddingRight: '', + paddingTop: '', + showButton: 'always', + showOverlay: 'always', + textAlign: '' + }) + ); +}); + +test('banner config aggregator retrieves values from fully configured collage-centered banner content type', () => { + const node = document.createElement('div'); + node.innerHTML = + '

A new way of shopping

Experience the best way of shopping today!

'; + expect( + configAggregator(node.childNodes[0], { + appearance: 'collage-centered' + }) + ).toEqual( + expect.objectContaining({ + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'none', + borderColor: '', + borderRadius: '0px', + borderWidth: '1px', + buttonText: 'Shop Bags', + buttonType: 'secondary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: + 'https://pagebuilder.test/media/wysiwyg/enhanced-storefront.jpg', + link: 'https://pagebuilder.test/gear/bags.html', + linkType: 'category', + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + minHeight: null, + mobileImage: + 'https://pagebuilder.test/media/wysiwyg/blake-wisz-Kx3o6_m1Yv8-unsplash.jpg', + overlayColor: null, + paddingBottom: '', + paddingLeft: '', + paddingRight: '', + paddingTop: '', + showButton: 'always', + showOverlay: 'never', + textAlign: 'right' + }) + ); +}); + +test('banner config aggregator retrieves values from fully configured collage-right banner content type', () => { + const node = document.createElement('div'); + node.innerHTML = + '

A new way of shopping

Experience the best way of shopping today!

'; + expect( + configAggregator(node.childNodes[0], { + appearance: 'collage-right' + }) + ).toEqual( + expect.objectContaining({ + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'solid', + borderColor: 'red', + borderRadius: '15px', + borderWidth: '10px', + buttonText: 'Link Button', + buttonType: 'link', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: + 'https://pagebuilder.test/media/wysiwyg/enhanced-storefront.jpg', + link: 'https://pagebuilder.test/gear/bags.html', + linkType: 'category', + marginBottom: '0px', + marginLeft: '0px', + marginRight: '0px', + marginTop: '0px', + minHeight: null, + mobileImage: + 'https://pagebuilder.test/media/wysiwyg/blake-wisz-Kx3o6_m1Yv8-unsplash.jpg', + overlayColor: null, + paddingBottom: '', + paddingLeft: '', + paddingRight: '', + paddingTop: '', + showButton: 'always', + showOverlay: 'never', + textAlign: 'center' + }) + ); +}); diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 3feffb11da..f80843dede 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -1,19 +1,64 @@ -import {getMargin, getBackgroundImages, getBorder, getPadding} from '../../utils'; +import { + getMargin, + getBackgroundImages, + getBorder, + getPadding, + getTextAlign, + getCssClasses +} from '../../utils'; -export default (node, props) => { - console.log(props.appearance, node); - const wrapper = node.querySelector('[data-element="wrapper"]'); - const overlay = node.querySelector('[data-element="overlay"]'); - const response = { - minHeight: overlay.style.minHeight ? overlay.style.minHeight : null, +/** + * Determine the button type based on class + * + * @param node + * @returns {string} + */ +const getButtonType = node => { + if (node.classList.contains('pagebuilder-button-secondary')) { + return 'secondary'; + } + if (node.classList.contains('pagebuilder-button-link')) { + return 'link'; + } + return 'primary'; +}; + +export default node => { + const wrapperElement = node.querySelector('[data-element="wrapper"]'); + const overlayElement = node.querySelector('[data-element="overlay"]'); + const linkElement = node.querySelector('a[data-element="link"]'); + const buttonElement = node.querySelector('[data-element="button"]'); + const showButton = node.getAttribute('data-show-button'); + const showOverlay = node.getAttribute('data-show-overlay'); + + return { + minHeight: overlayElement.style.minHeight + ? overlayElement.style.minHeight + : null, + ...getBackgroundImages(wrapperElement), content: node.querySelector('[data-element="content"]').innerHTML, - showButton: node.getAttribute('data-show-button'), - showOverlay: node.getAttribute('data-show-overlay'), - ...getBackgroundImages(wrapper), - ...getBorder(wrapper), + link: linkElement ? linkElement.getAttribute('href') : null, + linkType: linkElement + ? linkElement.getAttribute('data-link-type') + : null, + showButton, + buttonText: + buttonElement && showButton !== 'never' + ? buttonElement.textContent + : null, + buttonType: + buttonElement && showButton !== 'never' + ? getButtonType(buttonElement) + : null, + showOverlay, + overlayColor: + overlayElement && showOverlay !== 'never' + ? overlayElement.getAttribute('data-overlay-color') + : null, + ...getTextAlign(wrapperElement), + ...getBorder(wrapperElement), + ...getCssClasses(node), ...getMargin(node), - ...getPadding(overlay), + ...getPadding(overlayElement) }; - console.log(response); - return response; }; From 01fb51d3e7e94c933f8aef418716e05b2fea861b Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Wed, 2 Oct 2019 16:01:28 -0500 Subject: [PATCH 05/13] PB-17: Banner content type in Venia UI / PWA Studio - Update propTypes - Implement the majority of banner features --- .../ContentTypes/Banner/banner.css | 76 +++++---- .../PageBuilder/ContentTypes/Banner/banner.js | 149 +++++++++++++++++- .../ContentTypes/Banner/configAggregator.js | 19 ++- 3 files changed, 201 insertions(+), 43 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css index 9bc6f83bbf..dd923e95d6 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css @@ -1,41 +1,47 @@ -.pagebuilder-banner-wrapper { +.root { +} +.wrapper { background-clip: padding-box; border-radius: inherit; box-sizing: border-box; overflow-wrap: break-word; word-wrap: break-word; - - .pagebuilder-overlay { - -moz-transition: background-color 500ms ease; - -o-transition: background-color 500ms ease; - -webkit-transition: background-color 500ms ease; - box-sizing: border-box; - padding: 30px; - transition: background-color 500ms ease; - - &.pagebuilder-poster-overlay { - align-items: center; - display: flex; - justify-content: center; - } - - &:not(.pagebuilder-poster-overlay) { - max-width: 540px; - } - } - - [data-element='content'] { - min-height: 50px; - } - - .pagebuilder-banner-button { - -moz-transition: opacity 500ms ease; - -o-transition: opacity 500ms ease; - -webkit-transition: opacity 500ms ease; - margin: 20px 0 0 0; - max-width: 100%; - text-align: inherit; - transition: opacity 500ms ease; - word-break: break-word; - } +} +.overlay { + box-sizing: border-box; + padding: 30px; + transition: background-color 500ms ease; +} +.content { + min-height: 50px; +} +.poster { + composes: root; +} +.poster .overlay { + align-items: center; + display: flex; + justify-content: center; +} +.collageLeft { + composes: root; +} +.collageLeft .overlay { + margin-right: auto; + max-width: 540px; +} +.collageCentered { + composes: root; +} +.collageCentered .overlay { + margin-right: auto; + margin-left: auto; + max-width: 540px; +} +.collageRight { + composes: root; +} +.collageRight .overlay { + margin-left: auto; + max-width: 540px; } diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index e587642d9a..116f8ee696 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -1,6 +1,10 @@ import React from 'react'; +import defaultClasses from './banner.css'; +import { mergeClasses } from '../../../../../classify'; import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; +const toHTML = str => ({ __html: str }); + /** * Page Builder Banner component. * @@ -14,7 +18,122 @@ import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; * @returns {React.Element} A React component that displays a Banner. */ const Banner = props => { - return null; + const classes = mergeClasses(defaultClasses, props.classes); + const { + appearance = 'poster', + minHeight, + backgroundColor, + desktopImage, + mobileImage, + backgroundSize, + backgroundPosition, + backgroundAttachment, + backgroundRepeat, + textAlign, + border, + borderColor, + borderWidth, + borderRadius, + content, + showButton, + buttonType, + buttonText, + showOverlay, + overlayColor, + marginTop, + marginRight, + marginBottom, + marginLeft, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + cssClasses = [] + } = props; + + let image = desktopImage; + if ( + mobileImage && + typeof window.matchMedia === 'function' && + window.matchMedia('(max-width: 768px)').matches + ) { + image = mobileImage; + } + + const rootStyles = { + marginTop, + marginRight, + marginBottom, + marginLeft + }; + const wrapperStyles = { + backgroundColor, + border, + borderColor, + borderWidth, + borderRadius, + textAlign + }; + const overlayStyles = { + backgroundColor: showOverlay !== 'never' ? overlayColor : null + }; + const contentStyles = {}; + + if (image) { + wrapperStyles.backgroundImage = `url(${image})`; + wrapperStyles.backgroundSize = backgroundSize; + wrapperStyles.backgroundPosition = backgroundPosition; + wrapperStyles.backgroundAttachment = backgroundAttachment; + wrapperStyles.backgroundRepeat = backgroundRepeat + ? 'repeat' + : 'no-repeat'; + } + + if (appearance === 'poster') { + overlayStyles.borderRadius = borderRadius; + overlayStyles.minHeight = minHeight; + overlayStyles.paddingTop = paddingTop; + overlayStyles.paddingRight = paddingRight; + overlayStyles.paddingBottom = paddingBottom; + overlayStyles.paddingLeft = paddingLeft; + contentStyles.width = '100%'; + } else { + wrapperStyles.minHeight = minHeight; + wrapperStyles.paddingTop = paddingTop; + wrapperStyles.paddingRight = paddingRight; + wrapperStyles.paddingBottom = paddingBottom; + wrapperStyles.paddingLeft = paddingLeft; + } + + const appearanceClasses = { + poster: classes.poster, + 'collage-left': classes.collageLeft, + 'collage-centered': classes.collageCentered, + 'collage-right': classes.collageRight + }; + + let BannerButton; + if (showButton) { + BannerButton = ; + } + + return ( +
+
+
+
+ {BannerButton} +
+
+
+ ); }; /** @@ -23,8 +142,10 @@ const Banner = props => { * @typedef props * * @property {Object} classes An object containing the class names for the banner - * @property {String} classes.poster CSS class for the poster appearance element * @property {String} classes.root CSS class for the banner root element + * @property {String} classes.wrapper CSS class for the banner wrapper element + * @property {String} classes.overlay CSS class for the banner overlay element + * @property {String} classes.content CSS class for the banner content element * @property {String} minHeight CSS minimum height property * @property {String} backgroundColor CSS background-color property * @property {String} desktopImage Background image URL to be displayed on desktop devices @@ -33,6 +154,14 @@ const Banner = props => { * @property {String} backgroundPosition CSS background-position property * @property {String} backgroundAttachment CSS background-attachment property * @property {Boolean} backgroundRepeat CSS background-repeat property + * @property {String} content The HTML content to be rendered inside the banner content area + * @property {String} link The link location for the banner + * @property {String} linkType The type of link included with the banner. Values: default, product, category, page + * @property {String} showButton Whether or not to show the button. Values: always, hover, never + * @property {String} buttonText Text to display within the button + * @property {String} buttonType The type of button to display. Values: primary, secondary, link + * @property {String} showOverlay Whether or not to show the overlay. Values: always, hover, never + * @property {String} overlayColor The color of the overlay * @property {String} textAlign Alignment of the block within the parent container * @property {String} border CSS border property * @property {String} borderColor CSS border color property @@ -51,7 +180,13 @@ const Banner = props => { Banner.propTypes = { classes: shape({ root: string, - appearance: string + wrapper: string, + overlay: string, + content: string, + poster: string, + collageLeft: string, + collageCentered: string, + collageRight: string }), appearance: oneOf([ 'poster', @@ -67,6 +202,14 @@ Banner.propTypes = { backgroundPosition: string, backgroundAttachment: string, backgroundRepeat: bool, + content: string, + link: string, + linkType: oneOf(['default', 'product', 'category', 'page']), + showButton: oneOf(['always', 'hover', 'never']), + buttonText: string, + buttonType: oneOf(['primary', 'secondary', 'link']), + showOverlay: oneOf(['always', 'hover', 'never']), + overlayColor: string, textAlign: string, border: string, borderColor: string, diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index f80843dede..3f07106667 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -23,7 +23,7 @@ const getButtonType = node => { return 'primary'; }; -export default node => { +export default (node, props) => { const wrapperElement = node.querySelector('[data-element="wrapper"]'); const overlayElement = node.querySelector('[data-element="overlay"]'); const linkElement = node.querySelector('a[data-element="link"]'); @@ -31,10 +31,19 @@ export default node => { const showButton = node.getAttribute('data-show-button'); const showOverlay = node.getAttribute('data-show-overlay'); - return { - minHeight: overlayElement.style.minHeight + let minHeight = wrapperElement.style.minHeight + ? wrapperElement.style.minHeight + : null; + let padding = getPadding(wrapperElement); + if (props.appearance === 'poster') { + minHeight = overlayElement.style.minHeight ? overlayElement.style.minHeight - : null, + : null; + padding = getPadding(overlayElement); + } + + return { + minHeight, ...getBackgroundImages(wrapperElement), content: node.querySelector('[data-element="content"]').innerHTML, link: linkElement ? linkElement.getAttribute('href') : null, @@ -59,6 +68,6 @@ export default node => { ...getBorder(wrapperElement), ...getCssClasses(node), ...getMargin(node), - ...getPadding(overlayElement) + ...padding }; }; From 0ff875c6f2f3db97242b606384e5ff35e2f3701b Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Wed, 2 Oct 2019 16:26:19 -0500 Subject: [PATCH 06/13] PB-17: Banner content type in Venia UI / PWA Studio - Add backgroundColor to configAggregator - Add button to banner --- .../Banner/__tests__/configAggregator.spec.js | 3 ++- .../ContentTypes/Banner/banner.css | 11 ++++++++++ .../PageBuilder/ContentTypes/Banner/banner.js | 20 +++++++++++++++++-- .../ContentTypes/Banner/configAggregator.js | 1 + 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js index 252eb645e6..5f3ef09aae 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js @@ -46,13 +46,14 @@ test('banner config aggregator retrieves default values from empty banner conten test('banner config aggregator retrieves values from fully configured poster banner content type', () => { const node = document.createElement('div'); node.innerHTML = - ''; + ''; expect( configAggregator(node.childNodes[0], { appearance: 'poster' }) ).toEqual( expect.objectContaining({ + backgroundColor: 'blue', backgroundAttachment: 'scroll', backgroundPosition: 'center center', backgroundRepeat: false, diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css index dd923e95d6..572e56544e 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css @@ -15,14 +15,25 @@ .content { min-height: 50px; } +.button { + margin: 20px 0 0 0; + max-width: 100%; + text-align: inherit; + transition: opacity 500ms ease; + word-break: break-word; +} .poster { composes: root; } .poster .overlay { align-items: center; + align-content: center; display: flex; justify-content: center; } +.poster .button { + width: 100%; +} .collageLeft { composes: root; } diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index 116f8ee696..7c5babadb7 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -2,6 +2,7 @@ import React from 'react'; import defaultClasses from './banner.css'; import { mergeClasses } from '../../../../../classify'; import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; +import Button from "../../../../Button/button"; const toHTML = str => ({ __html: str }); @@ -112,9 +113,19 @@ const Banner = props => { 'collage-right': classes.collageRight }; + const buttonPriorityMap = { + primary: 'high', + secondary: 'normal', + link: 'low' + }; + let BannerButton; - if (showButton) { - BannerButton = ; + if (showButton !== 'never') { + BannerButton =
+ +
; } return ( @@ -146,6 +157,11 @@ const Banner = props => { * @property {String} classes.wrapper CSS class for the banner wrapper element * @property {String} classes.overlay CSS class for the banner overlay element * @property {String} classes.content CSS class for the banner content element + * @property {String} classes.poster CSS class for the banner poster appearance + * @property {String} classes.collageLeft CSS class for the banner collage left appearance + * @property {String} classes.collageCentered CSS class for the banner collage centered appearance + * @property {String} classes.collageRight CSS class for the banner collage right appearance + * @property {String} classes.poster CSS class for the banner poster appearance * @property {String} minHeight CSS minimum height property * @property {String} backgroundColor CSS background-color property * @property {String} desktopImage Background image URL to be displayed on desktop devices diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 3f07106667..5882225a69 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -44,6 +44,7 @@ export default (node, props) => { return { minHeight, + backgroundColor: wrapperElement.style.backgroundColor, ...getBackgroundImages(wrapperElement), content: node.querySelector('[data-element="content"]').innerHTML, link: linkElement ? linkElement.getAttribute('href') : null, From f1bfad9e0196341f67a23bde6b3eaadccd8384d7 Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Wed, 2 Oct 2019 16:36:46 -0500 Subject: [PATCH 07/13] PB-17: Banner content type in Venia UI / PWA Studio - Fix test issues --- .../Banner/__tests__/configAggregator.spec.js | 64 +++++++++---------- .../PageBuilder/ContentTypes/Banner/banner.js | 40 ++++++++++-- .../ContentTypes/Banner/configAggregator.js | 1 + 3 files changed, 65 insertions(+), 40 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js index 5f3ef09aae..5443f57fc0 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js @@ -70,6 +70,7 @@ test('banner config aggregator retrieves values from fully configured poster ban desktopImage: 'desktop-image.jpg', link: 'gear/bags.html', linkType: 'category', + openInNewTab: true, marginBottom: '0px', marginLeft: '0px', marginRight: '0px', @@ -91,7 +92,7 @@ test('banner config aggregator retrieves values from fully configured poster ban test('banner config aggregator retrieves values from fully configured collage-left banner content type', () => { const node = document.createElement('div'); node.innerHTML = - ''; + ''; expect( configAggregator(node.childNodes[0], { appearance: 'collage-left' @@ -111,22 +112,21 @@ test('banner config aggregator retrieves values from fully configured collage-le content: '

A new way of shopping

Experience the best way of shopping today!

', cssClasses: [], - desktopImage: - 'https://pagebuilder.test/media/wysiwyg/enhanced-storefront.jpg', - link: 'https://pagebuilder.test/gear/bags.html', + desktopImage: 'desktop-image.jpg', + link: 'gear/bags.html', linkType: 'category', + openInNewTab: true, marginBottom: '0px', marginLeft: '0px', marginRight: '0px', marginTop: '0px', - minHeight: null, - mobileImage: - 'https://pagebuilder.test/media/wysiwyg/blake-wisz-Kx3o6_m1Yv8-unsplash.jpg', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', overlayColor: 'rgba(255, 255, 255, 0.25)', - paddingBottom: '', - paddingLeft: '', - paddingRight: '', - paddingTop: '', + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', showButton: 'always', showOverlay: 'always', textAlign: '' @@ -137,7 +137,7 @@ test('banner config aggregator retrieves values from fully configured collage-le test('banner config aggregator retrieves values from fully configured collage-centered banner content type', () => { const node = document.createElement('div'); node.innerHTML = - ''; + ''; expect( configAggregator(node.childNodes[0], { appearance: 'collage-centered' @@ -157,22 +157,21 @@ test('banner config aggregator retrieves values from fully configured collage-ce content: '

A new way of shopping

Experience the best way of shopping today!

', cssClasses: [], - desktopImage: - 'https://pagebuilder.test/media/wysiwyg/enhanced-storefront.jpg', - link: 'https://pagebuilder.test/gear/bags.html', + desktopImage: 'desktop-image.jpg', + link: 'gear/bags.html', linkType: 'category', + openInNewTab: true, marginBottom: '0px', marginLeft: '0px', marginRight: '0px', marginTop: '0px', - minHeight: null, - mobileImage: - 'https://pagebuilder.test/media/wysiwyg/blake-wisz-Kx3o6_m1Yv8-unsplash.jpg', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', overlayColor: null, - paddingBottom: '', - paddingLeft: '', - paddingRight: '', - paddingTop: '', + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', showButton: 'always', showOverlay: 'never', textAlign: 'right' @@ -183,7 +182,7 @@ test('banner config aggregator retrieves values from fully configured collage-ce test('banner config aggregator retrieves values from fully configured collage-right banner content type', () => { const node = document.createElement('div'); node.innerHTML = - ''; + ''; expect( configAggregator(node.childNodes[0], { appearance: 'collage-right' @@ -203,22 +202,21 @@ test('banner config aggregator retrieves values from fully configured collage-ri content: '

A new way of shopping

Experience the best way of shopping today!

', cssClasses: [], - desktopImage: - 'https://pagebuilder.test/media/wysiwyg/enhanced-storefront.jpg', - link: 'https://pagebuilder.test/gear/bags.html', + desktopImage: 'desktop-image.jpg', + link: 'gear/bags.html', linkType: 'category', + openInNewTab: false, marginBottom: '0px', marginLeft: '0px', marginRight: '0px', marginTop: '0px', - minHeight: null, - mobileImage: - 'https://pagebuilder.test/media/wysiwyg/blake-wisz-Kx3o6_m1Yv8-unsplash.jpg', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', overlayColor: null, - paddingBottom: '', - paddingLeft: '', - paddingRight: '', - paddingTop: '', + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', showButton: 'always', showOverlay: 'never', textAlign: 'center' diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index 7c5babadb7..8c5982600f 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -2,7 +2,8 @@ import React from 'react'; import defaultClasses from './banner.css'; import { mergeClasses } from '../../../../../classify'; import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; -import Button from "../../../../Button/button"; +import Button from '../../../../Button/button'; +import resolveLinkProps from '../../resolveLinkProps'; const toHTML = str => ({ __html: str }); @@ -39,6 +40,9 @@ const Banner = props => { showButton, buttonType, buttonText, + link, + linkType, + openInNewTab = false, showOverlay, overlayColor, marginTop, @@ -113,19 +117,40 @@ const Banner = props => { 'collage-right': classes.collageRight }; - const buttonPriorityMap = { + const typeToPriorityMapping = { primary: 'high', secondary: 'normal', link: 'low' }; + let linkProps = {}; + let url = ''; + if (typeof link === 'string') { + linkProps = resolveLinkProps(link, linkType); + url = linkProps.to ? linkProps.to : linkProps.href; + } + let BannerButton; if (showButton !== 'never') { - BannerButton =
- -
; + const handleClick = () => { + if (openInNewTab) { + window.open(url, '_blank'); + } else { + props.history.push(url); + } + }; + + BannerButton = ( +
+ +
+ ); } return ( @@ -221,6 +246,7 @@ Banner.propTypes = { content: string, link: string, linkType: oneOf(['default', 'product', 'category', 'page']), + openInNewTab: bool, showButton: oneOf(['always', 'hover', 'never']), buttonText: string, buttonType: oneOf(['primary', 'secondary', 'link']), diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 5882225a69..1a63f5c55f 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -51,6 +51,7 @@ export default (node, props) => { linkType: linkElement ? linkElement.getAttribute('data-link-type') : null, + openInNewTab: linkElement && linkElement.getAttribute('target') === '_blank', showButton, buttonText: buttonElement && showButton !== 'never' From d17654f270042188dbaccb1a22ea6b42aac0a9a0 Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Thu, 3 Oct 2019 10:35:32 -0500 Subject: [PATCH 08/13] PB-17: Banner content type in Venia UI / PWA Studio - Add link to entire banner --- .../ContentTypes/Banner/banner.css | 21 ++++++- .../PageBuilder/ContentTypes/Banner/banner.js | 63 +++++++++++++++---- .../ContentTypes/Banner/configAggregator.js | 3 +- 3 files changed, 72 insertions(+), 15 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css index 572e56544e..0a89cdb04a 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.css @@ -1,5 +1,8 @@ .root { } +a.link { + text-decoration: none; +} .wrapper { background-clip: padding-box; border-radius: inherit; @@ -11,9 +14,17 @@ box-sizing: border-box; padding: 30px; transition: background-color 500ms ease; + align-items: center; + display: flex; + flex-wrap: wrap; +} +.overlayHover { + composes: overlay; + background-color: transparent !important; } .content { min-height: 50px; + width: 100%; } .button { margin: 20px 0 0 0; @@ -21,14 +32,20 @@ text-align: inherit; transition: opacity 500ms ease; word-break: break-word; + width: 100%; +} +.root:hover .buttonHover { + opacity: 1; +} +.buttonHover { + composes: button; + opacity: 0; } .poster { composes: root; } .poster .overlay { - align-items: center; align-content: center; - display: flex; justify-content: center; } .poster .button { diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index 8c5982600f..5606e85c32 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -1,9 +1,10 @@ -import React from 'react'; +import React, { useState } from 'react'; import defaultClasses from './banner.css'; import { mergeClasses } from '../../../../../classify'; import { arrayOf, bool, oneOf, shape, string } from 'prop-types'; import Button from '../../../../Button/button'; import resolveLinkProps from '../../resolveLinkProps'; +import { Link } from '@magento/venia-drivers'; const toHTML = str => ({ __html: str }); @@ -21,6 +22,8 @@ const toHTML = str => ({ __html: str }); */ const Banner = props => { const classes = mergeClasses(defaultClasses, props.classes); + const [hovered, setHovered] = useState(false); + const toggleHover = () => setHovered(!hovered); const { appearance = 'poster', minHeight, @@ -125,13 +128,18 @@ const Banner = props => { let linkProps = {}; let url = ''; + let LinkComponent; if (typeof link === 'string') { linkProps = resolveLinkProps(link, linkType); url = linkProps.to ? linkProps.to : linkProps.href; + LinkComponent = linkProps.to ? Link : 'a'; } let BannerButton; if (showButton !== 'never') { + const buttonClass = + showButton === 'hover' ? classes.buttonHover : classes.button; + const handleClick = () => { if (openInNewTab) { window.open(url, '_blank'); @@ -141,7 +149,7 @@ const Banner = props => { }; BannerButton = ( -
+
+
+
+
+ + +`; + +exports[`on hover displays button and overlay 2`] = ` +
+ + +`; + +exports[`renders a configured collage-left Banner component 1`] = ` +
+ + +`; + +exports[`renders a configured collage-left Banner component on mobile 1`] = ` +
+ + +`; + +exports[`renders a configured poster Banner component 1`] = ` +
+ + +`; + +exports[`renders an empty Banner component 1`] = ` +
+
+
+
+
+ +
+
+
+
+`; diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js new file mode 100644 index 0000000000..0fff0c5fb3 --- /dev/null +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js @@ -0,0 +1,230 @@ +import React from 'react'; +import { createTestInstance } from '@magento/peregrine'; +import Banner from "../banner"; +import { act } from 'react-test-renderer'; +import Button from '../../../../../Button/button'; +import { Link } from '@magento/venia-drivers'; + +jest.mock('@magento/venia-drivers', () => ({ + resourceUrl: jest.fn(), + Link: jest.fn(() => null) +})); + +jest.mock('../../../../../../classify'); + +test('renders an empty Banner component', () => { + const component = createTestInstance(); + + expect(component.toJSON()).toMatchSnapshot(); +}); + +test('renders a configured poster Banner component', () => { + const bannerProps = { + appearance: 'poster', + backgroundColor: 'blue', + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: true, + backgroundSize: 'cover', + border: 'solid', + borderColor: 'rgb(0,0,0)', + borderRadius: '15px', + borderWidth: '1px', + buttonText: 'Shop Bags', + buttonType: 'primary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: 'desktop-image.jpg', + link: 'gear/bags.html', + linkType: 'category', + openInNewTab: true, + marginBottom: '1px', + marginLeft: '2px', + marginRight: '3px', + marginTop: '4px', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', + overlayColor: 'rgb(0,0,0,0.5)', + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', + showButton: 'always', + showOverlay: 'hover', + textAlign: 'right' + }; + const component = createTestInstance(); + + expect(component.toJSON()).toMatchSnapshot(); +}); + +test('renders a configured collage-left Banner component', () => { + const bannerProps = { + appearance: 'collage-left', + backgroundColor: 'blue', + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'solid', + borderColor: 'rgb(0,0,0)', + borderRadius: '15px', + borderWidth: '1px', + buttonText: 'Shop Bags', + buttonType: 'primary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: 'desktop-image.jpg', + link: 'gear/bags.html', + linkType: 'category', + openInNewTab: false, + marginBottom: '1px', + marginLeft: '2px', + marginRight: '3px', + marginTop: '4px', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', + overlayColor: 'rgb(0,0,0,0.5)', + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', + showButton: 'hover', + showOverlay: 'always', + textAlign: 'right' + }; + const component = createTestInstance(); + + expect(component.toJSON()).toMatchSnapshot(); +}); + +test('renders a configured collage-left Banner component on mobile', () => { + window.matchMedia = jest.fn().mockImplementation(query => { + return { + matches: true, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn() + }; + }); + + const bannerProps = { + appearance: 'collage-left', + backgroundColor: 'blue', + backgroundAttachment: 'scroll', + backgroundPosition: 'center center', + backgroundRepeat: false, + backgroundSize: 'cover', + border: 'solid', + borderColor: 'rgb(0,0,0)', + borderRadius: '15px', + borderWidth: '1px', + buttonText: 'Shop Bags', + buttonType: 'primary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + cssClasses: [], + desktopImage: 'desktop-image.jpg', + link: 'https://www.adobe.com', + linkType: 'default', + openInNewTab: true, + marginBottom: '1px', + marginLeft: '2px', + marginRight: '3px', + marginTop: '4px', + minHeight: '300px', + mobileImage: 'mobile-image.jpg', + overlayColor: 'rgb(0,0,0,0.5)', + paddingBottom: '40px', + paddingLeft: '40px', + paddingRight: '40px', + paddingTop: '40px', + showButton: 'hover', + showOverlay: 'never', + textAlign: 'right' + }; + const component = createTestInstance(); + + expect(component.toJSON()).toMatchSnapshot(); +}); + +test('on hover displays button and overlay', () => { + const bannerProps = { + appearance: 'collage-left', + buttonType: 'primary', + content: + '

A new way of shopping

Experience the best way of shopping today!

', + link: 'https://www.adobe.com', + linkType: 'default', + openInNewTab: false, + overlayColor: 'rgb(0,0,0,0.5)', + showButton: 'hover', + showOverlay: 'hover' + }; + const component = createTestInstance(); + act(() => { + component.toTree().rendered.props.onMouseEnter(); + }); + expect(component.toJSON()).toMatchSnapshot(); + + act(() => { + component.toTree().rendered.props.onMouseLeave(); + }); + expect(component.toJSON()).toMatchSnapshot(); +}); + +test('clicking banner with external link button goes to correct destination', () => { + const bannerProps = { + link: 'https://www.adobe.com', + linkType: 'default', + openInNewTab: true, + showButton: 'always', + buttonText: 'Shop Bags', + buttonType: 'primary', + }; + const component = createTestInstance(); + const button = component.root.findByType(Button); + window.open = jest.fn().mockImplementation(() => {}); + button.props.onClick(); + expect(window.open).toHaveBeenCalledWith('https://www.adobe.com', '_blank'); +}); + +test('clicking banner with internal link button goes to correct destination', () => { + process.env.MAGENTO_BACKEND_URL = 'http://magento.com/'; + const bannerProps = { + link: 'test-product.html', + linkType: 'product', + openInNewTab: false, + showButton: 'always', + buttonText: 'Shop Bags', + buttonType: 'primary', + history: { + push: jest.fn() + } + }; + const component = createTestInstance(); + const button = component.root.findByType(Button); + button.props.onClick(); + expect(bannerProps.history.push).toHaveBeenCalledWith('test-product.html'); +}); + +test('generates an internal when URL is internal', () => { + process.env.MAGENTO_BACKEND_URL = 'http://magento.com/'; + const bannerProps = { + link: 'http://magento.com/test-product.html', + linkType: 'product', + openInNewTab: false, + showButton: 'always', + buttonText: 'Shop Bags', + buttonType: 'primary' + }; + const component = createTestInstance(); + const button = component.root.findByType(Link); + expect(button.props.to).toEqual('/test-product.html'); +}); From 5ea7b03ad11f3e98cbe1114dc347c541d631e867 Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Thu, 3 Oct 2019 15:33:40 -0500 Subject: [PATCH 10/13] PB-17: Banner content type in Venia UI / PWA Studio --- .../Banner/__tests__/banner.spec.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js index 0fff0c5fb3..fea4853ed6 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js @@ -1,6 +1,6 @@ import React from 'react'; import { createTestInstance } from '@magento/peregrine'; -import Banner from "../banner"; +import Banner from '../banner'; import { act } from 'react-test-renderer'; import Button from '../../../../../Button/button'; import { Link } from '@magento/venia-drivers'; @@ -54,7 +54,7 @@ test('renders a configured poster Banner component', () => { showOverlay: 'hover', textAlign: 'right' }; - const component = createTestInstance(); + const component = createTestInstance(); expect(component.toJSON()).toMatchSnapshot(); }); @@ -95,7 +95,7 @@ test('renders a configured collage-left Banner component', () => { showOverlay: 'always', textAlign: 'right' }; - const component = createTestInstance(); + const component = createTestInstance(); expect(component.toJSON()).toMatchSnapshot(); }); @@ -149,7 +149,7 @@ test('renders a configured collage-left Banner component on mobile', () => { showOverlay: 'never', textAlign: 'right' }; - const component = createTestInstance(); + const component = createTestInstance(); expect(component.toJSON()).toMatchSnapshot(); }); @@ -167,7 +167,7 @@ test('on hover displays button and overlay', () => { showButton: 'hover', showOverlay: 'hover' }; - const component = createTestInstance(); + const component = createTestInstance(); act(() => { component.toTree().rendered.props.onMouseEnter(); }); @@ -186,9 +186,9 @@ test('clicking banner with external link button goes to correct destination', () openInNewTab: true, showButton: 'always', buttonText: 'Shop Bags', - buttonType: 'primary', + buttonType: 'primary' }; - const component = createTestInstance(); + const component = createTestInstance(); const button = component.root.findByType(Button); window.open = jest.fn().mockImplementation(() => {}); button.props.onClick(); @@ -208,7 +208,7 @@ test('clicking banner with internal link button goes to correct destination', () push: jest.fn() } }; - const component = createTestInstance(); + const component = createTestInstance(); const button = component.root.findByType(Button); button.props.onClick(); expect(bannerProps.history.push).toHaveBeenCalledWith('test-product.html'); @@ -224,7 +224,7 @@ test('generates an internal when URL is internal', () => { buttonText: 'Shop Bags', buttonType: 'primary' }; - const component = createTestInstance(); + const component = createTestInstance(); const button = component.root.findByType(Link); expect(button.props.to).toEqual('/test-product.html'); }); From d4e833f8e2d11a70d4e3bb5f8b246b10526e8f75 Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Fri, 4 Oct 2019 09:10:53 -0500 Subject: [PATCH 11/13] PB-17: Banner content type in Venia UI / PWA Studio --- .../Banner/__tests__/banner.spec.js | 17 ++++++++--------- .../PageBuilder/ContentTypes/Banner/banner.js | 11 ++++------- .../ContentTypes/Banner/configAggregator.js | 14 ++++---------- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js index fea4853ed6..c9df33af7d 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/banner.spec.js @@ -12,6 +12,12 @@ jest.mock('@magento/venia-drivers', () => ({ jest.mock('../../../../../../classify'); +window.matchMedia = jest.fn().mockImplementation(() => { + return { + matches: false + }; +}); + test('renders an empty Banner component', () => { const component = createTestInstance(); @@ -101,16 +107,9 @@ test('renders a configured collage-left Banner component', () => { }); test('renders a configured collage-left Banner component on mobile', () => { - window.matchMedia = jest.fn().mockImplementation(query => { + window.matchMedia = jest.fn().mockImplementation(() => { return { - matches: true, - media: query, - onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn() + matches: true }; }); diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js index 5606e85c32..adf5bbeddf 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/banner.js @@ -60,11 +60,7 @@ const Banner = props => { } = props; let image = desktopImage; - if ( - mobileImage && - typeof window.matchMedia === 'function' && - window.matchMedia('(max-width: 768px)').matches - ) { + if (mobileImage && window.matchMedia('(max-width: 768px)').matches) { image = mobileImage; } @@ -179,7 +175,8 @@ const Banner = props => {
); - if (typeof link === 'string' && LinkComponent) { + // If we have a LinkComponent it means we're wanting to make the whole banner a link + if (LinkComponent) { BannerFragment = ( { * @property {String} buttonType The type of button to display. Values: primary, secondary, link * @property {String} showOverlay Whether or not to show the overlay. Values: always, hover, never * @property {String} overlayColor The color of the overlay - * @property {String} textAlign Alignment of the block within the parent container + * @property {String} textAlign Alignment of the banner within the parent container * @property {String} border CSS border property * @property {String} borderColor CSS border color property * @property {String} borderWidth CSS border width property diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 5213307c41..9e6c619491 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -31,19 +31,13 @@ export default (node, props) => { const showButton = node.getAttribute('data-show-button'); const showOverlay = node.getAttribute('data-show-overlay'); - let minHeight = wrapperElement.style.minHeight - ? wrapperElement.style.minHeight - : null; - let padding = getPadding(wrapperElement); + let minHeightPaddingElement = wrapperElement; if (props.appearance === 'poster') { - minHeight = overlayElement.style.minHeight - ? overlayElement.style.minHeight - : null; - padding = getPadding(overlayElement); + minHeightPaddingElement = overlayElement; } return { - minHeight, + minHeight: minHeightPaddingElement.style.minHeight || null, backgroundColor: wrapperElement.style.backgroundColor, ...getBackgroundImages(wrapperElement), content: node.querySelector('[data-element="content"]').innerHTML, @@ -71,6 +65,6 @@ export default (node, props) => { ...getBorder(wrapperElement), ...getCssClasses(node), ...getMargin(node), - ...padding + ...getPadding(minHeightPaddingElement) }; }; From e5f0aa53f8e824b4b7e0c208aad1497c582927ef Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Fri, 4 Oct 2019 11:12:02 -0500 Subject: [PATCH 12/13] PB-17: Banner content type in Venia UI / PWA Studio - Fix hidden banner --- .../PageBuilder/ContentTypes/Banner/configAggregator.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 9e6c619491..7bf55dc071 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -4,7 +4,7 @@ import { getBorder, getPadding, getTextAlign, - getCssClasses + getCssClasses, getIsHidden } from '../../utils'; /** @@ -65,6 +65,7 @@ export default (node, props) => { ...getBorder(wrapperElement), ...getCssClasses(node), ...getMargin(node), - ...getPadding(minHeightPaddingElement) + ...getPadding(minHeightPaddingElement), + ...getIsHidden(node) }; }; From 4bbdb1f133c8461b55cf367cc2b7e7a1a3718b96 Mon Sep 17 00:00:00 2001 From: Dave Macaulay Date: Fri, 4 Oct 2019 11:17:41 -0500 Subject: [PATCH 13/13] PB-17: Banner content type in Venia UI / PWA Studio --- .../Banner/__tests__/configAggregator.spec.js | 15 +++++++++++++++ .../ContentTypes/Banner/configAggregator.js | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js index 5443f57fc0..9074188c08 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/__tests__/configAggregator.spec.js @@ -223,3 +223,18 @@ test('banner config aggregator retrieves values from fully configured collage-ri }) ); }); + +test('banner config aggregator retrieve isHidden value', () => { + const node = document.createElement('div'); + node.innerHTML = + ''; + expect( + configAggregator(node.childNodes[0], { + appearance: 'collage-right' + }) + ).toEqual( + expect.objectContaining({ + isHidden: true + }) + ); +}); diff --git a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js index 7bf55dc071..985b4fece3 100644 --- a/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js +++ b/packages/venia-ui/lib/components/RichContent/PageBuilder/ContentTypes/Banner/configAggregator.js @@ -4,7 +4,8 @@ import { getBorder, getPadding, getTextAlign, - getCssClasses, getIsHidden + getCssClasses, + getIsHidden } from '../../utils'; /**