From e9d7c30d521d21a3b1300e14b9fd68d01039baec Mon Sep 17 00:00:00 2001 From: Luigi Date: Tue, 4 Jan 2022 14:55:19 +0100 Subject: [PATCH 01/10] Product title: add support global style #4965 --- .../blocks/product-elements/title/block.tsx | 57 +++++----- .../blocks/product-elements/title/index.ts | 31 ++++-- assets/js/utils/style-attributes-utils.ts | 105 ++++++++++++++++++ 3 files changed, 154 insertions(+), 39 deletions(-) create mode 100644 assets/js/utils/style-attributes-utils.ts diff --git a/assets/js/atomic/blocks/product-elements/title/block.tsx b/assets/js/atomic/blocks/product-elements/title/block.tsx index 86801e51fbd..793a49c422b 100644 --- a/assets/js/atomic/blocks/product-elements/title/block.tsx +++ b/assets/js/atomic/blocks/product-elements/title/block.tsx @@ -7,7 +7,6 @@ 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'; import ProductName from '@woocommerce/base-components/product-name'; @@ -18,6 +17,11 @@ import { useStoreEvents } from '@woocommerce/base-context/hooks'; */ import './style.scss'; import { Attributes } from './types'; +import { + useSpacingProps, + useTypographyProps, + useColorProps, +} from '../../../../utils/style-attributes-utils'; type Props = Attributes & HTMLAttributes< HTMLDivElement >; @@ -49,33 +53,26 @@ const TagName = ( { * will be used if this is not provided. * @return {*} The component. */ -export const Block = ( { - className, - headingLevel = 2, - showProductLink = true, - align, - textColor, - fontSize, - style, -}: Props ): JSX.Element => { +export const Block = ( props: Props ): JSX.Element => { + const { + className, + headingLevel = 2, + showProductLink = true, + align, + } = props; + const { parentClassName } = useInnerBlockLayoutContext(); const { product } = useProductDataContext(); const { dispatchStoreEvent } = useStoreEvents(); - const colorClass = getColorClassName( 'color', textColor ); - const fontSizeClass = getFontSizeClass( fontSize ); - const titleClasses = classnames( 'wp-block-woocommerce-product-title', { - 'has-text-color': textColor || style?.color?.text || style?.color, - [ `has-font-size` ]: - fontSize || style?.typography?.fontSize || style?.fontSize, - [ colorClass ]: colorClass, - [ fontSizeClass ]: fontSizeClass, - } ); + const colorProps = useColorProps( props ); + const spacingProps = useSpacingProps( props ); + const typographyProps = useTypographyProps( props ); - const titleStyle = { - fontSize: style?.fontSize || style?.typography?.fontSize, - color: style?.color?.text || style?.color, - }; + const titleClasses = classnames( + 'wp-block-woocommerce-product-title', + colorProps.className + ); if ( ! product.id ) { return ( @@ -88,7 +85,6 @@ export const Block = ( { [ `${ parentClassName }__product-title` ]: parentClassName, [ `wc-block-components-product-title--align-${ align }` ]: align && isFeaturePluginBuild(), - [ titleClasses ]: isFeaturePluginBuild(), } ) } /> @@ -109,9 +105,7 @@ export const Block = ( { ) } > ); diff --git a/assets/js/atomic/blocks/product-elements/title/index.ts b/assets/js/atomic/blocks/product-elements/title/index.ts index bf70fbfd62c..9ee1af8b9e2 100644 --- a/assets/js/atomic/blocks/product-elements/title/index.ts +++ b/assets/js/atomic/blocks/product-elements/title/index.ts @@ -24,17 +24,26 @@ const blockConfig: BlockConfiguration = { icon: { src: icon }, attributes, edit, - supports: isFeaturePluginBuild() - ? { - html: false, - color: { - background: false, - }, - typography: { - fontSize: true, - }, - } - : sharedConfig.supports, + supports: { + typography: { + fontSize: true, + lineHeight: true, + ...( isFeaturePluginBuild() & + { + __experimentalFontWeight: true, + __experimentalTextTransform: true, + __experimentalFontFamily: true, + } ), + }, + color: { + text: false, + background: true, + gradients: true, + }, + spacing: { + margin: true, + }, + }, }; registerBlockType( 'woocommerce/product-title', blockConfig ); diff --git a/assets/js/utils/style-attributes-utils.ts b/assets/js/utils/style-attributes-utils.ts new file mode 100644 index 00000000000..15ca869a3ef --- /dev/null +++ b/assets/js/utils/style-attributes-utils.ts @@ -0,0 +1,105 @@ +/* eslint-disable @wordpress/no-unsafe-wp-apis */ +/** + * External dependencies + */ +import { __experimentalUseColorProps } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import { isFeaturePluginBuild } from '../settings/blocks/feature-flags'; +import { isString, isObject } from '../types/type-guards'; + +const parseStyle = ( style: unknown ): Record< string, unknown > => { + if ( isString( style ) ) { + return JSON.parse( style ) || {}; + } + + if ( isObject( style ) ) { + return style; + } + + return {}; +}; + +const parseSpacingStyle = ( + spacing: Record< string, unknown > +): Record< string, unknown > => { + const keys = [ 'margin' ]; + + const getValueOrDefault = ( value: unknown ) => { + return isString( value ) && value.length > 0 ? value : '0'; + }; + + return Object.keys( spacing ).reduce( ( acc, key ) => { + const spacingProperty = isObject( spacing[ key ] ) + ? ( spacing[ key ] as Record< string, unknown > ) + : {}; + + if ( keys.includes( key ) ) { + return { + ...acc, + [ key ]: `${ getValueOrDefault( + spacingProperty.top + ) } ${ getValueOrDefault( + spacingProperty.right + ) } ${ getValueOrDefault( + spacingProperty.bottom + ) } ${ getValueOrDefault( spacingProperty.left ) }`, + }; + } + + return acc; + }, {} ); +}; + +export const useSpacingProps = ( + attributes: unknown +): { + style: Record< string, unknown >; +} => { + const style = isObject( attributes ) ? parseStyle( attributes.style ) : {}; + const spacingStyles = isObject( style.spacing ) ? style.spacing : {}; + + return { + style: parseSpacingStyle( spacingStyles ), + }; +}; + +export const useTypographyProps = ( + attributes: unknown +): { + style: Record< string, unknown >; +} => { + const attributesObject = isObject( attributes ) ? attributes : {}; + const style = parseStyle( attributesObject.style ); + const typography = isObject( style.typography ) + ? ( style.typography as Record< string, unknown > ) + : {}; + + return { + style: { + fontSize: attributesObject.fontSize || typography.fontSize, + lineHeight: typography.lineHeight, + fontWeight: typography.fontWeight, + textTransform: typography.textTransform, + fontFamily: attributesObject.fontFamily, + }, + }; +}; + +export const useColorProps = ( + attributes: unknown +): { + className: string; + style: Record< string, unknown >; +} => { + if ( ! isFeaturePluginBuild() ) { + return { + className: '', + style: {}, + }; + } + + return __experimentalUseColorProps( attributes ); +}; From 517f80a11760fad95c480309b6dcc7dd5747148c Mon Sep 17 00:00:00 2001 From: Luigi Date: Tue, 4 Jan 2022 14:57:23 +0100 Subject: [PATCH 02/10] add specific type --- .../blocks/product-elements/title/block.tsx | 1 + .../blocks/product-elements/title/index.ts | 11 +++---- assets/js/utils/style-attributes-utils.ts | 32 +++++++++---------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/assets/js/atomic/blocks/product-elements/title/block.tsx b/assets/js/atomic/blocks/product-elements/title/block.tsx index 793a49c422b..99369553568 100644 --- a/assets/js/atomic/blocks/product-elements/title/block.tsx +++ b/assets/js/atomic/blocks/product-elements/title/block.tsx @@ -120,6 +120,7 @@ export const Block = ( props: Props ): JSX.Element => { ? { ...spacingProps.style, ...typographyProps.style, + ...colorProps.style, } : {} } diff --git a/assets/js/atomic/blocks/product-elements/title/index.ts b/assets/js/atomic/blocks/product-elements/title/index.ts index 9ee1af8b9e2..03935b1a702 100644 --- a/assets/js/atomic/blocks/product-elements/title/index.ts +++ b/assets/js/atomic/blocks/product-elements/title/index.ts @@ -28,12 +28,11 @@ const blockConfig: BlockConfiguration = { typography: { fontSize: true, lineHeight: true, - ...( isFeaturePluginBuild() & - { - __experimentalFontWeight: true, - __experimentalTextTransform: true, - __experimentalFontFamily: true, - } ), + ...( isFeaturePluginBuild() && { + __experimentalFontWeight: true, + __experimentalTextTransform: true, + __experimentalFontFamily: true, + } ), }, color: { text: false, diff --git a/assets/js/utils/style-attributes-utils.ts b/assets/js/utils/style-attributes-utils.ts index 15ca869a3ef..ab4145af1f4 100644 --- a/assets/js/utils/style-attributes-utils.ts +++ b/assets/js/utils/style-attributes-utils.ts @@ -10,6 +10,14 @@ import { __experimentalUseColorProps } from '@wordpress/block-editor'; import { isFeaturePluginBuild } from '../settings/blocks/feature-flags'; import { isString, isObject } from '../types/type-guards'; +type WithClass = { + className: string; +}; + +type WithStyle = { + style: Record< string, unknown >; +}; + const parseStyle = ( style: unknown ): Record< string, unknown > => { if ( isString( style ) ) { return JSON.parse( style ) || {}; @@ -53,11 +61,7 @@ const parseSpacingStyle = ( }, {} ); }; -export const useSpacingProps = ( - attributes: unknown -): { - style: Record< string, unknown >; -} => { +export const useSpacingProps = ( attributes: unknown ): WithStyle => { const style = isObject( attributes ) ? parseStyle( attributes.style ) : {}; const spacingStyles = isObject( style.spacing ) ? style.spacing : {}; @@ -66,11 +70,7 @@ export const useSpacingProps = ( }; }; -export const useTypographyProps = ( - attributes: unknown -): { - style: Record< string, unknown >; -} => { +export const useTypographyProps = ( attributes: unknown ): WithStyle => { const attributesObject = isObject( attributes ) ? attributes : {}; const style = parseStyle( attributesObject.style ); const typography = isObject( style.typography ) @@ -88,12 +88,7 @@ export const useTypographyProps = ( }; }; -export const useColorProps = ( - attributes: unknown -): { - className: string; - style: Record< string, unknown >; -} => { +export const useColorProps = ( attributes: unknown ): WithStyle & WithClass => { if ( ! isFeaturePluginBuild() ) { return { className: '', @@ -101,5 +96,8 @@ export const useColorProps = ( }; } - return __experimentalUseColorProps( attributes ); + const attributesObject = isObject( attributes ) ? attributes : {}; + const style = parseStyle( attributesObject.style ); + + return __experimentalUseColorProps( { ...attributesObject, style } ); }; From 48709c77dd8764e0ad383113f877b26997e70b87 Mon Sep 17 00:00:00 2001 From: Luigi Date: Wed, 5 Jan 2022 15:15:57 +0100 Subject: [PATCH 03/10] add custom save function --- .../blocks/product-elements/title/block.tsx | 7 +--- .../blocks/product-elements/title/index.ts | 37 ++++++++++++------- .../blocks/product-elements/title/save.tsx | 21 +++++++++++ .../blocks/product-elements/title/style.scss | 9 +++++ assets/js/utils/style-attributes-utils.ts | 36 ++++++++++++++---- 5 files changed, 82 insertions(+), 28 deletions(-) create mode 100644 assets/js/atomic/blocks/product-elements/title/save.tsx diff --git a/assets/js/atomic/blocks/product-elements/title/block.tsx b/assets/js/atomic/blocks/product-elements/title/block.tsx index 99369553568..6637d761b0c 100644 --- a/assets/js/atomic/blocks/product-elements/title/block.tsx +++ b/assets/js/atomic/blocks/product-elements/title/block.tsx @@ -69,11 +69,6 @@ export const Block = ( props: Props ): JSX.Element => { const spacingProps = useSpacingProps( props ); const typographyProps = useTypographyProps( props ); - const titleClasses = classnames( - 'wp-block-woocommerce-product-title', - colorProps.className - ); - if ( ! product.id ) { return ( { ) } > & { + className?: string; + }; +}; + +export const Save = ( { attributes }: Props ): JSX.Element => { + return ( +
+ ); +}; diff --git a/assets/js/atomic/blocks/product-elements/title/style.scss b/assets/js/atomic/blocks/product-elements/title/style.scss index 47dd2c6800c..7e0f8ec0065 100644 --- a/assets/js/atomic/blocks/product-elements/title/style.scss +++ b/assets/js/atomic/blocks/product-elements/title/style.scss @@ -1,3 +1,7 @@ +.wp-block-woocommerce-product-title { + width: fit-content; +} + .wc-block-components-product-title { margin-top: 0; margin-bottom: $gap-small; @@ -10,6 +14,11 @@ font-size: inherit; display: block; } + +.wc-block-components-product-name { + color: inherit; +} + .is-loading { .wc-block-components-product-title::before { @include placeholder(); diff --git a/assets/js/utils/style-attributes-utils.ts b/assets/js/utils/style-attributes-utils.ts index ab4145af1f4..48b3d03aa0a 100644 --- a/assets/js/utils/style-attributes-utils.ts +++ b/assets/js/utils/style-attributes-utils.ts @@ -30,13 +30,34 @@ const parseStyle = ( style: unknown ): Record< string, unknown > => { return {}; }; +const getSpacingStyleInline = ( + key: string, + values: { + top: string | null; + right: string | null; + bottom: string | null; + left: string | null; + } +) => { + return { + ...( isString( values.top ) && { [ `${ key }Top` ]: values.top } ), + ...( isString( values.right ) && { + [ `${ key }Right` ]: values.right, + } ), + ...( isString( values.bottom ) && { + [ `${ key }Bottom` ]: values.bottom, + } ), + ...( isString( values.left ) && { [ `${ key }Left` ]: values.left } ), + }; +}; + const parseSpacingStyle = ( spacing: Record< string, unknown > ): Record< string, unknown > => { const keys = [ 'margin' ]; const getValueOrDefault = ( value: unknown ) => { - return isString( value ) && value.length > 0 ? value : '0'; + return isString( value ) && value.length > 0 ? value : null; }; return Object.keys( spacing ).reduce( ( acc, key ) => { @@ -47,13 +68,12 @@ const parseSpacingStyle = ( if ( keys.includes( key ) ) { return { ...acc, - [ key ]: `${ getValueOrDefault( - spacingProperty.top - ) } ${ getValueOrDefault( - spacingProperty.right - ) } ${ getValueOrDefault( - spacingProperty.bottom - ) } ${ getValueOrDefault( spacingProperty.left ) }`, + ...getSpacingStyleInline( key, { + top: getValueOrDefault( spacingProperty.top ), + right: getValueOrDefault( spacingProperty.right ), + bottom: getValueOrDefault( spacingProperty.bottom ), + left: getValueOrDefault( spacingProperty.left ), + } ), }; } From 6d7982476744d978762bea6025f3c3e49b7e46cf Mon Sep 17 00:00:00 2001 From: Luigi Date: Thu, 6 Jan 2022 16:26:17 +0100 Subject: [PATCH 04/10] move hooks in a specific folder --- .../blocks/product-elements/title/block.tsx | 2 +- .../style-attributes.ts} | 72 ++++--------------- 2 files changed, 16 insertions(+), 58 deletions(-) rename assets/js/{utils/style-attributes-utils.ts => hooks/style-attributes.ts} (50%) diff --git a/assets/js/atomic/blocks/product-elements/title/block.tsx b/assets/js/atomic/blocks/product-elements/title/block.tsx index 6637d761b0c..ae4d8a43104 100644 --- a/assets/js/atomic/blocks/product-elements/title/block.tsx +++ b/assets/js/atomic/blocks/product-elements/title/block.tsx @@ -21,7 +21,7 @@ import { useSpacingProps, useTypographyProps, useColorProps, -} from '../../../../utils/style-attributes-utils'; +} from '../../../../hooks/style-attributes'; type Props = Attributes & HTMLAttributes< HTMLDivElement >; diff --git a/assets/js/utils/style-attributes-utils.ts b/assets/js/hooks/style-attributes.ts similarity index 50% rename from assets/js/utils/style-attributes-utils.ts rename to assets/js/hooks/style-attributes.ts index 48b3d03aa0a..da7a94b8daa 100644 --- a/assets/js/utils/style-attributes-utils.ts +++ b/assets/js/hooks/style-attributes.ts @@ -2,7 +2,10 @@ /** * External dependencies */ -import { __experimentalUseColorProps } from '@wordpress/block-editor'; +import { + __experimentalUseColorProps, + __experimentalGetSpacingClassesAndStyles, +} from '@wordpress/block-editor'; /** * Internal dependencies @@ -30,64 +33,19 @@ const parseStyle = ( style: unknown ): Record< string, unknown > => { return {}; }; -const getSpacingStyleInline = ( - key: string, - values: { - top: string | null; - right: string | null; - bottom: string | null; - left: string | null; - } -) => { - return { - ...( isString( values.top ) && { [ `${ key }Top` ]: values.top } ), - ...( isString( values.right ) && { - [ `${ key }Right` ]: values.right, - } ), - ...( isString( values.bottom ) && { - [ `${ key }Bottom` ]: values.bottom, - } ), - ...( isString( values.left ) && { [ `${ key }Left` ]: values.left } ), - }; -}; - -const parseSpacingStyle = ( - spacing: Record< string, unknown > -): Record< string, unknown > => { - const keys = [ 'margin' ]; - - const getValueOrDefault = ( value: unknown ) => { - return isString( value ) && value.length > 0 ? value : null; - }; - - return Object.keys( spacing ).reduce( ( acc, key ) => { - const spacingProperty = isObject( spacing[ key ] ) - ? ( spacing[ key ] as Record< string, unknown > ) - : {}; - - if ( keys.includes( key ) ) { - return { - ...acc, - ...getSpacingStyleInline( key, { - top: getValueOrDefault( spacingProperty.top ), - right: getValueOrDefault( spacingProperty.right ), - bottom: getValueOrDefault( spacingProperty.bottom ), - left: getValueOrDefault( spacingProperty.left ), - } ), - }; - } - - return acc; - }, {} ); -}; - export const useSpacingProps = ( attributes: unknown ): WithStyle => { - const style = isObject( attributes ) ? parseStyle( attributes.style ) : {}; - const spacingStyles = isObject( style.spacing ) ? style.spacing : {}; + if ( ! isFeaturePluginBuild() ) { + return { + style: {}, + }; + } + const attributesObject = isObject( attributes ) ? attributes : {}; + const style = parseStyle( attributesObject.style ); - return { - style: parseSpacingStyle( spacingStyles ), - }; + return __experimentalGetSpacingClassesAndStyles( { + ...attributesObject, + style, + } ); }; export const useTypographyProps = ( attributes: unknown ): WithStyle => { From a17ca36e485d47dac65010ea2599656a8c0f5b47 Mon Sep 17 00:00:00 2001 From: Luigi Date: Fri, 7 Jan 2022 16:59:29 +0100 Subject: [PATCH 05/10] fix crash on WP 5.8 --- .../atomic/blocks/product-elements/title/index.ts | 14 ++++++++------ assets/js/hooks/style-attributes.ts | 3 ++- assets/js/utils/global-style.js | 8 ++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 assets/js/utils/global-style.js diff --git a/assets/js/atomic/blocks/product-elements/title/index.ts b/assets/js/atomic/blocks/product-elements/title/index.ts index acb55c20264..6ac95ebc102 100644 --- a/assets/js/atomic/blocks/product-elements/title/index.ts +++ b/assets/js/atomic/blocks/product-elements/title/index.ts @@ -16,6 +16,7 @@ import { BLOCK_DESCRIPTION as description, } from './constants'; import { Save } from './save'; +import { hasSpacingStyleSupport } from '../../../../utils/global-style'; const blockConfig: BlockConfiguration = { ...sharedConfig, @@ -45,12 +46,13 @@ const blockConfig: BlockConfiguration = { __experimentalSkipSerialization: true, }, } ), - ...( isFeaturePluginBuild() && { - spacing: { - margin: true, - __experimentalSkipSerialization: true, - }, - } ), + ...( isFeaturePluginBuild() && + hasSpacingStyleSupport() && { + spacing: { + margin: true, + __experimentalSkipSerialization: true, + }, + } ), }, }; diff --git a/assets/js/hooks/style-attributes.ts b/assets/js/hooks/style-attributes.ts index da7a94b8daa..9acb889d848 100644 --- a/assets/js/hooks/style-attributes.ts +++ b/assets/js/hooks/style-attributes.ts @@ -12,6 +12,7 @@ import { */ import { isFeaturePluginBuild } from '../settings/blocks/feature-flags'; import { isString, isObject } from '../types/type-guards'; +import { hasSpacingStyleSupport } from '../utils/global-style'; type WithClass = { className: string; @@ -34,7 +35,7 @@ const parseStyle = ( style: unknown ): Record< string, unknown > => { }; export const useSpacingProps = ( attributes: unknown ): WithStyle => { - if ( ! isFeaturePluginBuild() ) { + if ( ! isFeaturePluginBuild() || ! hasSpacingStyleSupport() ) { return { style: {}, }; diff --git a/assets/js/utils/global-style.js b/assets/js/utils/global-style.js new file mode 100644 index 00000000000..0a05b0378bd --- /dev/null +++ b/assets/js/utils/global-style.js @@ -0,0 +1,8 @@ +/* eslint-disable @wordpress/no-unsafe-wp-apis */ +/** + * External dependencies + */ +import { __experimentalGetSpacingClassesAndStyles } from '@wordpress/block-editor'; + +export const hasSpacingStyleSupport = () => + typeof __experimentalGetSpacingClassesAndStyles === 'function'; From 8e2f0dcf9494029359377920f2b055e7e2d6780f Mon Sep 17 00:00:00 2001 From: Luigi Date: Mon, 10 Jan 2022 18:10:37 +0100 Subject: [PATCH 06/10] Featured Category block: Add support for global style #4965 Featured Category block: Add support for global style --- assets/js/blocks/featured-category/block.js | 45 +++------- assets/js/blocks/featured-category/edit.tsx | 18 ++++ assets/js/blocks/featured-category/index.js | 37 ++++++-- assets/js/blocks/featured-category/style.scss | 14 ++- assets/js/hooks/style-attributes.ts | 17 ++++ src/BlockTypes/FeaturedCategory.php | 89 ++++++++++++++++++- src/Utils/StyleAttributesUtils.php | 76 ++++++++++++++++ 7 files changed, 251 insertions(+), 45 deletions(-) create mode 100644 assets/js/blocks/featured-category/edit.tsx diff --git a/assets/js/blocks/featured-category/block.js b/assets/js/blocks/featured-category/block.js index 1d98eb0ae23..4458d77ccb0 100644 --- a/assets/js/blocks/featured-category/block.js +++ b/assets/js/blocks/featured-category/block.js @@ -8,8 +8,6 @@ import { InnerBlocks, InspectorControls, MediaReplaceFlow, - PanelColorSettings, - withColors, RichText, } from '@wordpress/block-editor'; import { @@ -56,8 +54,6 @@ import { withCategory } from '../../hocs'; * @param {function(any):any} props.getCategory Function for getting category details. * @param {boolean} props.isLoading Whether loading or not. * @param {Object} props.category The product category object. - * @param {Object} props.overlayColor Overlay color object for content. - * @param {function(any):any} props.setOverlayColor Setter for overlay color. * @param {function(any):any} props.debouncedSpeak Function for delayed speak. * @param {function():void} props.triggerUrlUpdate Function to update Shop now button Url. */ @@ -69,8 +65,6 @@ const FeaturedCategory = ( { getCategory, isLoading, category, - overlayColor, - setOverlayColor, debouncedSpeak, triggerUrlUpdate = () => void null, } ) => { @@ -148,21 +142,14 @@ const FeaturedCategory = ( { } /> - + - { !! url && ( - <> + ) } + > ) } - - ) } - + + + ) } ); }; @@ -288,13 +275,13 @@ const FeaturedCategory = ( { const renderCategory = () => { const { - className, contentAlign, dimRatio, focalPoint, height, showDesc, } = attributes; + const classes = classnames( 'wc-block-featured-category', { @@ -304,14 +291,10 @@ const FeaturedCategory = ( { 'has-background-dim': dimRatio !== 0, }, dimRatioToClass( dimRatio ), - contentAlign !== 'center' && `has-${ contentAlign }-content`, - className + contentAlign !== 'center' && `has-${ contentAlign }-content` ); const mediaSrc = attributes.mediaSrc || getCategoryImageSrc( category ); const style = !! category ? getBackgroundImageStyles( mediaSrc ) : {}; - if ( overlayColor.color ) { - style.backgroundColor = overlayColor.color; - } if ( focalPoint ) { const bgPosX = focalPoint.x * 100; const bgPosY = focalPoint.y * 100; @@ -416,9 +399,6 @@ FeaturedCategory.propTypes = { description: PropTypes.node, permalink: PropTypes.string, } ), - // from withColors - overlayColor: PropTypes.object, - setOverlayColor: PropTypes.func.isRequired, // from withSpokenMessages debouncedSpeak: PropTypes.func.isRequired, triggerUrlUpdate: PropTypes.func, @@ -426,7 +406,6 @@ FeaturedCategory.propTypes = { export default compose( [ withCategory, - withColors( { overlayColor: 'background-color' } ), withSpokenMessages, withSelect( ( select, { clientId }, { dispatch } ) => { const Block = select( 'core/block-editor' ).getBlock( clientId ); diff --git a/assets/js/blocks/featured-category/edit.tsx b/assets/js/blocks/featured-category/edit.tsx new file mode 100644 index 00000000000..b67c4e9f725 --- /dev/null +++ b/assets/js/blocks/featured-category/edit.tsx @@ -0,0 +1,18 @@ +/** + * External dependencies + */ +import { useBlockProps } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import Block from './block'; + +export const Edit = ( props: unknown ) => { + const blockProps = useBlockProps(); + return ( +
+ +
+ ); +}; diff --git a/assets/js/blocks/featured-category/index.js b/assets/js/blocks/featured-category/index.js index e9b3f6bd178..93ee098ea8d 100644 --- a/assets/js/blocks/featured-category/index.js +++ b/assets/js/blocks/featured-category/index.js @@ -6,19 +6,21 @@ import { InnerBlocks } from '@wordpress/block-editor'; import { registerBlockType } from '@wordpress/blocks'; import { getSetting } from '@woocommerce/settings'; import { Icon, folderStarred } from '@woocommerce/icons'; +import { isFeaturePluginBuild } from '@woocommerce/block-settings'; /** * Internal dependencies */ import './style.scss'; import './editor.scss'; -import Block from './block'; import { example } from './example'; +import { Edit } from './edit'; /** * Register and run the "Featured Category" block. */ registerBlockType( 'woocommerce/featured-category', { + apiVersion: 2, title: __( 'Featured Category', 'woo-gutenberg-products-block' ), icon: { src: ( @@ -37,6 +39,21 @@ registerBlockType( 'woocommerce/featured-category', { supports: { align: [ 'wide', 'full' ], html: false, + color: { + text: true, + background: true, + }, + typography: { + fontSize: true, + }, + ...( isFeaturePluginBuild() && { + __experimentalBorder: { + color: true, + radius: true, + width: true, + __experimentalSkipSerialization: false, + }, + } ), }, example, attributes: { @@ -139,6 +156,14 @@ registerBlockType( 'woocommerce/featured-category', { type: 'object', default: null, }, + backgroundColor: { + type: 'string', + default: 'black', + }, + textColor: { + type: 'string', + default: 'white', + }, }, /** @@ -146,14 +171,8 @@ registerBlockType( 'woocommerce/featured-category', { * * @param {Object} props Props to pass to block. */ - edit( props ) { - return ; - }, - - /** - * Block content is rendered in PHP, not via save function. - */ - save() { + edit: Edit, + save: () => { return ; }, } ); diff --git a/assets/js/blocks/featured-category/style.scss b/assets/js/blocks/featured-category/style.scss index 8a0fc195c82..41b860997e6 100644 --- a/assets/js/blocks/featured-category/style.scss +++ b/assets/js/blocks/featured-category/style.scss @@ -1,10 +1,10 @@ .wc-block-featured-category { position: relative; - background-color: $gray-900; + background-color: inherit; background-size: cover; background-position: center center; width: 100%; - margin: 0 0 1.5em 0; + margin: 0 0 0 0; display: flex; justify-content: center; align-items: center; @@ -63,6 +63,8 @@ .wc-block-featured-category__description, .wc-block-featured-category__price, .wc-block-featured-category__link { + color: inherit; + font-size: inherit; width: 100%; padding: 0 48px 16px 48px; z-index: 1; @@ -71,12 +73,19 @@ .wc-block-featured-category__title { margin-top: 0; + div { + color: inherit; + font-size: inherit; + } + &::before { display: none; } } .wc-block-featured-category__description { + color: inherit; + font-size: inherit; p { margin: 0; } @@ -94,6 +103,7 @@ bottom: 0; right: 0; background-color: inherit; + border-radius: inherit; opacity: 0.5; z-index: 1; } diff --git a/assets/js/hooks/style-attributes.ts b/assets/js/hooks/style-attributes.ts index 9acb889d848..509a82dc6c2 100644 --- a/assets/js/hooks/style-attributes.ts +++ b/assets/js/hooks/style-attributes.ts @@ -5,6 +5,7 @@ import { __experimentalUseColorProps, __experimentalGetSpacingClassesAndStyles, + __experimentalUseBorderProps, } from '@wordpress/block-editor'; /** @@ -80,3 +81,19 @@ export const useColorProps = ( attributes: unknown ): WithStyle & WithClass => { return __experimentalUseColorProps( { ...attributesObject, style } ); }; + +export const useBorderProps = ( + attributes: unknown +): WithStyle & WithClass => { + if ( ! isFeaturePluginBuild() ) { + return { + className: '', + style: {}, + }; + } + + const attributesObject = isObject( attributes ) ? attributes : {}; + const style = parseStyle( attributesObject.style ); + + return __experimentalUseBorderProps( { ...attributesObject, style } ); +}; diff --git a/src/BlockTypes/FeaturedCategory.php b/src/BlockTypes/FeaturedCategory.php index adfc78c8214..8245d4767c0 100644 --- a/src/BlockTypes/FeaturedCategory.php +++ b/src/BlockTypes/FeaturedCategory.php @@ -1,6 +1,9 @@ true, ); + /** + * Get block attributes. + * + * @return array + */ + protected function get_block_type_attributes() { + return array_merge( + parent::get_block_type_attributes(), + array( + 'textColor' => $this->get_schema_string(), + 'fontSize' => $this->get_schema_string(), + 'lineHeight' => $this->get_schema_string(), + 'style' => array( 'type' => 'object' ), + ) + ); + } + /** * Render the Featured Category block. * @@ -36,6 +64,7 @@ class FeaturedCategory extends AbstractDynamicBlock { * @return string Rendered block type output. */ protected function render( $attributes, $content ) { + $id = absint( isset( $attributes['categoryId'] ) ? $attributes['categoryId'] : 0 ); $category = get_term( $id, 'product_cat' ); @@ -57,7 +86,13 @@ protected function render( $attributes, $content ) { wc_format_content( wp_kses_post( $category->description ) ) ); - $output = sprintf( '
', esc_attr( $this->get_classes( $attributes ) ), esc_attr( $this->get_styles( $attributes, $category ) ) ); + $background_color_class_and_style = $this->get_background_color_class_and_style_with_default( $attributes ); + $text_color_class_and_style = $this->get_text_color_class_and_style_with_default( $attributes ); + + $styles = $this->get_styles( $attributes, $category ) . ' ' . $text_color_class_and_style['style'] . ' ' . $background_color_class_and_style['style']; + $classes = $this->get_classes( $attributes ) . ' ' . $text_color_class_and_style['class'] . ' ' . $background_color_class_and_style['class']; + + $output = sprintf( '