Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Global Styles support for Product Price block #5950

Merged
merged 5 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 1 addition & 25 deletions assets/js/atomic/blocks/product-elements/price/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,7 @@ let blockAttributes = {
if ( isFeaturePluginBuild() ) {
blockAttributes = {
...blockAttributes,
align: {
type: 'string',
},
fontSize: {
type: 'string',
},
customFontSize: {
type: 'number',
},
saleFontSize: {
type: 'string',
},
customSaleFontSize: {
type: 'number',
},
color: {
type: 'string',
},
saleColor: {
type: 'string',
},
customColor: {
type: 'string',
},
customSaleColor: {
textAlign: {
type: 'string',
},
};
Expand Down
113 changes: 39 additions & 74 deletions assets/js/atomic/blocks/product-elements/price/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,127 +9,92 @@ import {
useInnerBlockLayoutContext,
useProductDataContext,
} from '@woocommerce/shared-context';
import { getColorClassName, getFontSizeClass } from '@wordpress/block-editor';
import { isFeaturePluginBuild } from '@woocommerce/block-settings';
import { withProductDataContext } from '@woocommerce/shared-hocs';

/**
* Internal dependencies
*/
import {
useColorProps,
useTypographyProps,
} from '../../../../hooks/style-attributes';

/**
* Product Price Block Component.
*
* @param {Object} props Incoming props.
* @param {string} [props.className] CSS Class name for the component.
* @param {string} [props.align] Text alignment.
* @param {string} [props.textAlign] Text alignment.
* @param {string} [props.fontSize] Normal Price font size name.
* @param {number} [props.customFontSize] Normal Price custom font size.
* @param {string} [props.saleFontSize] Original Price font size name.
* @param {number} [props.customSaleFontSize] Original Price custom font size.
* @param {string} [props.color] Normal Price text color.
* @param {string} [props.customColor] Normal Price custom text color.
* @param {string} [props.saleColor] Original Price text color.
* @param {string} [props.customSaleColor] Original Price custom text color.
* context will be used if this is not provided.
* @return {*} The component.
*/
const Block = ( {
className,
align,
fontSize,
customFontSize,
saleFontSize,
customSaleFontSize,
color,
customColor,
saleColor,
customSaleColor,
} ) => {
const Block = ( props ) => {
const { className, textAlign } = props;
const { parentClassName } = useInnerBlockLayoutContext();
const { product } = useProductDataContext();

const wrapperClassName = classnames( className, {
[ `${ parentClassName }__product-price` ]: parentClassName,
} );

if ( ! product.id ) {
return <ProductPrice align={ align } className={ wrapperClassName } />;
}
const colorProps = useColorProps( props );
const typographyProps = useTypographyProps( props );

const colorClass = getColorClassName( 'color', color );
const fontSizeClass = getFontSizeClass( fontSize );
const saleColorClass = getColorClassName( 'color', saleColor );
const saleFontSizeClass = getFontSizeClass( saleFontSize );

const classes = classnames( {
'has-text-color': color || customColor,
'has-font-size': fontSize || customFontSize,
[ colorClass ]: colorClass,
[ fontSizeClass ]: fontSizeClass,
} );

const saleClasses = classnames( {
'has-text-color': saleColor || customSaleColor,
'has-font-size': saleFontSize || customSaleFontSize,
[ saleColorClass ]: saleColorClass,
[ saleFontSizeClass ]: saleFontSizeClass,
} );
const wrapperClassName = classnames(
'wc-block-components-product-price',
className,
colorProps.className,
{
[ `${ parentClassName }__product-price` ]: parentClassName,
}
);

const style = {
color: customColor,
fontSize: customFontSize,
...typographyProps.style,
...colorProps.style,
};

const saleStyle = {
color: customSaleColor,
fontSize: customSaleFontSize,
};
if ( ! product.id ) {
return (
<ProductPrice align={ textAlign } className={ wrapperClassName } />
);
}

const prices = product.prices;
const currency = getCurrencyFromPriceResponse( prices );
const isOnSale = prices.price !== prices.regular_price;
const priceClassName = isOnSale
? classnames( {
[ `${ parentClassName }__product-price__value` ]: parentClassName,
[ saleClasses ]: isFeaturePluginBuild(),
} )
: classnames( {
[ `${ parentClassName }__product-price__value` ]: parentClassName,
[ classes ]: isFeaturePluginBuild(),
} );
const priceStyle = isOnSale ? saleStyle : style;
const priceClassName = classnames( {
[ `${ parentClassName }__product-price__value` ]: parentClassName,
[ `${ parentClassName }__product-price__value--on-sale` ]: isOnSale,
} );

return (
<ProductPrice
align={ align }
align={ textAlign }
className={ wrapperClassName }
priceStyle={ style }
regularPriceStyle={ style }
priceClassName={ priceClassName }
currency={ currency }
price={ prices.price }
priceClassName={ priceClassName }
priceStyle={ isFeaturePluginBuild() ? priceStyle : {} }
// Range price props
minPrice={ prices?.price_range?.min_amount }
maxPrice={ prices?.price_range?.max_amount }
// This is the regular or original price when the `price` value is a sale price.
regularPrice={ prices.regular_price }
regularPriceClassName={ classnames( {
[ `${ parentClassName }__product-price__regular` ]: parentClassName,
tomasztunik marked this conversation as resolved.
Show resolved Hide resolved
[ classes ]: isFeaturePluginBuild(),
} ) }
regularPriceStyle={ isFeaturePluginBuild() ? style : {} }
/>
);
};

Block.propTypes = {
className: PropTypes.string,
product: PropTypes.object,
align: PropTypes.string,
textAlign: PropTypes.oneOf( [ 'left', 'right', 'center' ] ),
fontSize: PropTypes.string,
customFontSize: PropTypes.number,
saleFontSize: PropTypes.string,
customSaleFontSize: PropTypes.number,
fontWidth: PropTypes.string,
fontStyle: PropTypes.string,
color: PropTypes.string,
customColor: PropTypes.string,
saleColor: PropTypes.string,
customSaleColor: PropTypes.string,
};

export default withProductDataContext( Block );
138 changes: 28 additions & 110 deletions assets/js/atomic/blocks/product-elements/price/edit.js
Original file line number Diff line number Diff line change
@@ -1,133 +1,51 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, BaseControl } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import { isFeaturePluginBuild } from '@woocommerce/block-settings';
import {
InspectorControls,
BlockControls,
AlignmentToolbar,
withColors,
ColorPalette,
FontSizePicker,
withFontSizes,
BlockControls,
useBlockProps,
} from '@wordpress/block-editor';
import { isFeaturePluginBuild } from '@woocommerce/block-settings';
import { __ } from '@wordpress/i18n';

/**
*
*/

/**
* Internal dependencies
*/
import Block from './block';
import withProductSelector from '../shared/with-product-selector';
import { BLOCK_TITLE, BLOCK_ICON } from './constants';

const TextControl = ( {
fontSize,
setFontSize,
color,
setColor,
colorLabel,
} ) => (
<>
<FontSizePicker value={ fontSize.size } onChange={ setFontSize } />
{ /* ColorPalette doesn't accept an id. */
/* eslint-disable-next-line @wordpress/no-base-control-with-label-without-id */ }
<BaseControl label={ colorLabel }>
<ColorPalette
value={ color.color }
onChange={ setColor }
label={ __( 'Color', 'woo-gutenberg-products-block' ) }
/>
</BaseControl>
</>
);
const PriceEdit = ( {
fontSize,
saleFontSize,
setFontSize,
setSaleFontSize,
color,
saleColor,
setColor,
setSaleColor,
attributes,
setAttributes,
} ) => {
const { align } = attributes;
const PriceEdit = ( { attributes, setAttributes } ) => {
const blockProps = useBlockProps();
return (
<>
{ isFeaturePluginBuild() && (
<BlockControls>
<BlockControls>
{ isFeaturePluginBuild() && (
<AlignmentToolbar
value={ align }
onChange={ ( nextAlign ) => {
setAttributes( { align: nextAlign } );
value={ attributes.textAlign }
onChange={ ( newAlign ) => {
setAttributes( { textAlign: newAlign } );
} }
/>
</BlockControls>
) }
<InspectorControls>
{ isFeaturePluginBuild() && (
<>
<PanelBody
title={ __(
'Price',
'woo-gutenberg-products-block'
) }
>
<TextControl
color={ color }
setColor={ setColor }
fontSize={ fontSize }
setFontSize={ setFontSize }
colorLabel={ __(
'Color',
'woo-gutenberg-products-block'
) }
/>
</PanelBody>
<PanelBody
title={ __(
'Sale price',
'woo-gutenberg-products-block'
) }
>
<TextControl
color={ saleColor }
setColor={ setSaleColor }
fontSize={ saleFontSize }
setFontSize={ setSaleFontSize }
colorLabel={ __(
'Color',
'woo-gutenberg-products-block'
) }
/>
</PanelBody>
</>
) }
</InspectorControls>
<Block { ...attributes } />
</BlockControls>
<div { ...blockProps }>
<Block { ...attributes } />
</div>
</>
);
};

const Price = isFeaturePluginBuild()
? compose( [
withFontSizes( 'fontSize' ),
withFontSizes( 'saleFontSize' ),
withFontSizes( 'originalFontSize' ),
withColors( 'color', { textColor: 'color' } ),
withColors( 'saleColor', { textColor: 'saleColor' } ),
withColors( 'originalColor', { textColor: 'originalColor' } ),
withProductSelector( {
icon: BLOCK_ICON,
label: BLOCK_TITLE,
description: __(
'Choose a product to display its price.',
'woo-gutenberg-products-block'
),
} ),
] )( PriceEdit )
: PriceEdit;

export default Price;
export default withProductSelector( {
gigitux marked this conversation as resolved.
Show resolved Hide resolved
icon: BLOCK_ICON,
label: BLOCK_TITLE,
description: __(
'Choose a product to display its price.',
'woo-gutenberg-products-block'
),
} )( PriceEdit );
Loading