UNPKG

wix-style-react

Version:
217 lines (196 loc) • 6.58 kB
import React from 'react'; import PropTypes from 'prop-types'; import { WixStyleReactContext } from '../WixStyleReactProvider/context'; import Content from './components/Content'; import { Layout, Cell } from '../Layout'; import Proportion from '../Proportion'; import { SIZES, DIRECTIONS } from './constants'; import { st, classes } from './MarketingLayout.st.css'; import { stVars as colorsStVars } from '../Foundation/stylable/colors.st.css'; import deprecationLog from '../utils/deprecationLog'; const cellSpansBySize = { [SIZES.tiny]: { image: 4, content: 8, }, [SIZES.small]: { image: 3, spacer: 1, content: 8, }, [SIZES.medium]: { image: 4, spacer: 1, content: 7, }, [SIZES.large]: { image: 5, spacer: 1, content: 6, }, }; const imagePlaceholderAspectRatioBySize = { [SIZES.tiny]: 1, [SIZES.small]: 1, [SIZES.medium]: 282 / 188, [SIZES.large]: 360 / 240, }; /** Marketing layout is a layout designed to promote new features or display first time visit. * Component has title, description, action and illustration areas. */ class MarketingLayout extends React.PureComponent { static displayName = 'MarketingLayout'; static propTypes = { /** Applies a data-hook HTML attribute that can be used in the tests. */ dataHook: PropTypes.string, /** Accepts image URL or a custom element to be displayed on the side of content. */ image: PropTypes.node, /** Specifies image area background color. Can be a keyword from color palette or any supported CSS color value (HEX, RGB, etc.). */ imageBackgroundColor: PropTypes.string, /** * Controls the size of the marketing layout.<br/> * Large size will be deprecated in the next major version. */ size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large']), /** Controls content direction. */ direction: PropTypes.oneOf(['horizontal', 'vertical']), /** Controls the vertical alignment of the content. */ alignItems: PropTypes.oneOf(['center', 'stretch']), /** Flips content layout. If true, image will be displayed on the left side of the content. */ inverted: PropTypes.bool, /** Sets marketing layout actions. Accepts single or multiple interactive components. Most commonly contain `<Button/>` or `<TextButton/>`. */ actions: PropTypes.node, /** Sets the marketing layout title. Accepts text string or a custom element. */ title: PropTypes.node, /** Sets the marketing layout description. Accepts text string or a custom element. */ description: PropTypes.node, /** Adds a container for a `<Badge/>` component at the top left corner. Affect component height. */ badge: PropTypes.node, /** Specifies whether the badge is hidden. Can be used to add additional vertical spacing, if no badge is given. */ hiddenBadge: PropTypes.bool, }; static defaultProps = { size: 'small', alignItems: 'center', inverted: false, direction: 'horizontal', hiddenBadge: false, }; _renderSpacerCell = span => <Cell key="spacer" span={span} />; _renderImagePlaceholder = () => { const { size } = this.props; return ( <Proportion aspectRatio={imagePlaceholderAspectRatioBySize[size]}> <div className={classes.imagePlaceholder} /> </Proportion> ); }; _renderImageCell = span => { const { image, imageBackgroundColor } = this.props; return ( <Cell key="image" span={span}> <div className={classes.imageWrapper}> {imageBackgroundColor && ( <div className={classes.imageBackground} style={{ backgroundColor: colorsStVars[imageBackgroundColor] || imageBackgroundColor, }} /> )} <div className={classes.imageContainer}> {typeof image === 'string' ? ( <img src={image} width="100%" /> ) : ( image || this._renderImagePlaceholder() )} </div> </div> </Cell> ); }; _renderContentCell = span => { const { size, actions, title, description, badge, hiddenBadge } = this.props; return ( <Cell key="content" span={span}> {badge && !hiddenBadge && <div className={classes.badge}>{badge}</div>} <Content size={size} actions={actions} title={title} description={description} badge={badge} /> </Cell> ); }; _renderContent = () => { const { direction, size } = this.props; const isVertical = direction === DIRECTIONS.vertical; return ( <Layout gap={size === SIZES.tiny ? '24px' : '30px'}> {isVertical ? this._renderVerticalCells() : this._renderHorizontalCells()} </Layout> ); }; _renderHorizontalCells() { const { inverted, size } = this.props; const { image, spacer, content } = cellSpansBySize[size]; const contentCell = this._renderContentCell(content); const spacerCell = size !== SIZES.tiny && this._renderSpacerCell(spacer); const imageCell = this._renderImageCell(image); return inverted ? [imageCell, contentCell, spacerCell] : [contentCell, spacerCell, imageCell]; } _renderVerticalCells() { const { inverted, image } = this.props; const imageCell = image && this._renderImageCell(12); const contentCell = this._renderContentCell(12); return inverted ? [contentCell, imageCell] : [imageCell, contentCell]; } render() { const { size, badge, hiddenBadge, alignItems, inverted, actions, dataHook, imageBackgroundColor, direction, } = this.props; if (size === SIZES.large) { deprecationLog( `<MarketingLayout/> size large wil be deprecated in the next major version`, ); } return ( <WixStyleReactContext.Consumer> {({ reducedSpacingAndImprovedLayout }) => ( <div className={st(classes.root, { size, badge: !!badge, hiddenBadge, alignItems, inverted, withActions: !!actions, withImageBackground: !!imageBackgroundColor, reducedSpacingAndImprovedLayout, direction, })} data-hook={dataHook} > {this._renderContent()} </div> )} </WixStyleReactContext.Consumer> ); } } export default MarketingLayout;