From 5c63ab27fe715e234de349589c031657777cb48d Mon Sep 17 00:00:00 2001 From: Luigi Teschio Date: Tue, 30 Nov 2021 16:28:45 +0100 Subject: [PATCH] Add global style for Product Categories List block (#5133) * Add global style for product categories list block #4965 Add global style for product categories list block * add support for link color * add feature flag * fix code style and PHP warning * update doc comment * remove empty space * refactor StyleAttributesUtils (#5277) Co-authored-by: Tung Du --- assets/js/blocks/product-categories/block.js | 10 +- assets/js/blocks/product-categories/index.js | 12 ++ src/BlockTypes/ProductCategories.php | 26 ++- src/Utils/StyleAttributesUtils.php | 210 +++++++++++++++++++ 4 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 src/Utils/StyleAttributesUtils.php diff --git a/assets/js/blocks/product-categories/block.js b/assets/js/blocks/product-categories/block.js index 461dcd15bbd..459a4bbd1cd 100644 --- a/assets/js/blocks/product-categories/block.js +++ b/assets/js/blocks/product-categories/block.js @@ -2,7 +2,7 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import { InspectorControls } from '@wordpress/block-editor'; +import { InspectorControls, useBlockProps } from '@wordpress/block-editor'; import ServerSideRender from '@wordpress/server-side-render'; import PropTypes from 'prop-types'; import { @@ -183,8 +183,12 @@ const ProductCategoriesBlock = ( { attributes, setAttributes, name } ) => { ); }; + const blockProps = useBlockProps( { + className: 'wc-block-product-categories', + } ); + return ( - <> +
{ getInspectorControls() } { EmptyResponsePlaceholder={ EmptyPlaceholder } /> - +
); }; diff --git a/assets/js/blocks/product-categories/index.js b/assets/js/blocks/product-categories/index.js index a491710666c..4a544557050 100644 --- a/assets/js/blocks/product-categories/index.js +++ b/assets/js/blocks/product-categories/index.js @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n'; import { createBlock, registerBlockType } from '@wordpress/blocks'; import { Icon, list } from '@woocommerce/icons'; +import { isFeaturePluginBuild } from '@woocommerce/block-settings'; /** * Internal dependencies */ @@ -13,6 +14,7 @@ import './style.scss'; import Block from './block.js'; registerBlockType( 'woocommerce/product-categories', { + apiVersion: 2, title: __( 'Product Categories List', 'woo-gutenberg-products-block' ), icon: { src: , @@ -27,6 +29,16 @@ registerBlockType( 'woocommerce/product-categories', { supports: { align: [ 'wide', 'full' ], html: false, + ...( isFeaturePluginBuild() && { + color: { + background: false, + link: true, + }, + typography: { + fontSize: true, + lineHeight: true, + }, + } ), }, example: { attributes: { diff --git a/src/BlockTypes/ProductCategories.php b/src/BlockTypes/ProductCategories.php index 9bdc8809b45..a432ac87256 100644 --- a/src/BlockTypes/ProductCategories.php +++ b/src/BlockTypes/ProductCategories.php @@ -1,11 +1,14 @@ $this->get_schema_boolean( false ), 'isDropdown' => $this->get_schema_boolean( false ), 'isHierarchical' => $this->get_schema_boolean( true ), + 'textColor' => $this->get_schema_string(), + 'fontSize' => $this->get_schema_string(), + 'lineHeight' => $this->get_schema_string(), + 'style' => array( 'type' => 'object' ), ) ); } @@ -77,9 +84,15 @@ protected function render( $attributes, $content ) { } } - $classes = $this->get_container_classes( $attributes ); + $classes_and_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( + $attributes, + array( 'line_height', 'text_color', 'font_size' ) + ); + + $classes = $this->get_container_classes( $attributes ) . ' ' . $classes_and_styles['classes']; + $styles = $classes_and_styles['styles']; - $output = '
'; + $output = '
'; $output .= ! empty( $attributes['isDropdown'] ) ? $this->renderDropdown( $categories, $attributes, $uid ) : $this->renderList( $categories, $attributes, $uid ); $output .= '
'; @@ -93,6 +106,7 @@ protected function render( $attributes, $content ) { * @return string space-separated list of classes. */ protected function get_container_classes( $attributes = array() ) { + $classes = array( 'wc-block-product-categories' ); if ( isset( $attributes['align'] ) ) { @@ -301,11 +315,15 @@ protected function renderList( $categories, $attributes, $uid, $depth = 0 ) { protected function renderListItems( $categories, $attributes, $uid, $depth = 0 ) { $output = ''; + $link_color_class_and_style = StyleAttributesUtils::get_link_color_class_and_style( $attributes ); + + $link_color_style = isset( $link_color_class_and_style['style'] ) ? $link_color_class_and_style['style'] : ''; + foreach ( $categories as $category ) { $output .= '
  • - ' . $this->get_image_html( $category, $attributes ) . esc_html( $category->name ) . ' - ' . $this->getCount( $category, $attributes ) . ' + ' . $this->get_image_html( $category, $attributes ) . esc_html( $category->name ) . ' + ' . $this->getCount( $category, $attributes ) . ' ' . ( ! empty( $category->children ) ? $this->renderList( $category->children, $attributes, $uid, $depth + 1 ) : '' ) . '
  • '; diff --git a/src/Utils/StyleAttributesUtils.php b/src/Utils/StyleAttributesUtils.php new file mode 100644 index 00000000000..35d64e456a0 --- /dev/null +++ b/src/Utils/StyleAttributesUtils.php @@ -0,0 +1,210 @@ + sprintf( 'has-font-size has-%s-font-size', $font_size ), + 'style' => null, + ); + } elseif ( $has_custom_font_size ) { + return array( + 'class' => null, + 'style' => sprintf( 'font-size: %s;', $custom_font_size ), + ); + } + return null; + } + + /** + * Get class and style for text-color from attributes. + * + * @param array $attributes Block attributes. + * + * @return (array | null) + */ + public static function get_text_color_class_and_style( $attributes ) { + + $text_color = $attributes['textColor']; + + $custom_text_color = isset( $attributes['style']['color']['text'] ) ? $attributes['style']['color']['text'] : null; + + if ( ! isset( $text_color ) && ! isset( $custom_text_color ) ) { + return null; + }; + + $has_named_text_color = ! empty( $text_color ); + $has_custom_text_color = isset( $custom_text_color ); + + if ( $has_named_text_color ) { + return array( + 'class' => sprintf( 'has-text-color has-%s-color', $text_color ), + 'style' => null, + ); + } elseif ( $has_custom_text_color ) { + return array( + 'class' => null, + 'style' => sprintf( 'color: %s;', $custom_text_color ), + ); + } + return null; + } + + /** + * Get class and style for link-color from attributes. + * + * @param array $attributes Block attributes. + * + * @return (array | null) + */ + public static function get_link_color_class_and_style( $attributes ) { + + if ( ! isset( $attributes['style']['elements']['link']['color']['text'] ) ) { + return null; + }; + + $link_color = $attributes['style']['elements']['link']['color']['text']; + + // If the link color is selected from the theme color picker, the value of $link_color is var:preset|color|slug. + // If the link color is selected from the core color picker, the value of $link_color is an hex value. + // When the link color is a string var:preset|color|slug we parsed it for get the slug, otherwise we use the hex value. + $index_named_link_color = strrpos( $link_color, '|' ); + + if ( ! empty( $index_named_link_color ) ) { + $parsed_named_link_color = substr( $link_color, $index_named_link_color + 1 ); + return array( + 'class' => null, + 'style' => sprintf( 'color: %s;', $parsed_named_link_color ), + ); + } else { + return array( + 'class' => null, + 'style' => sprintf( 'color: %s;', $link_color ), + ); + } + } + + /** + * Get class and style for line height from attributes. + * + * @param array $attributes Block attributes. + * + * @return (array | null) + */ + public static function get_line_height_class_and_style( $attributes ) { + + $line_height = isset( $attributes['style']['typography']['lineHeight'] ) ? $attributes['style']['typography']['lineHeight'] : null; + + if ( ! isset( $line_height ) ) { + return null; + }; + + $line_height_style = sprintf( 'line-height: %s;', $line_height ); + + return array( + 'class' => null, + 'style' => $line_height_style, + ); + } + + /** + * Get classes and styles from attributes. + * + * @param array $attributes Block attributes. + * @param array $properties Properties to get classes/styles from. + * + * @return array + */ + public static function get_classes_and_styles_by_attributes( $attributes, $properties = array() ) { + $classes_and_styles = array( + 'line_height' => self::get_line_height_class_and_style( $attributes ), + 'text_color' => self::get_text_color_class_and_style( $attributes ), + 'font_size' => self::get_font_size_class_and_style( $attributes ), + 'link_color' => self::get_link_color_class_and_style( $attributes ), + ); + + if ( ! empty( $properties ) ) { + foreach ( $classes_and_styles as $key => $value ) { + if ( ! in_array( $key, $properties, true ) ) { + unset( $classes_and_styles[ $key ] ); + } + } + } + + $classes_and_styles = array_filter( $classes_and_styles ); + + $classes = array_map( + function( $item ) { + return $item['class']; + }, + $classes_and_styles + ); + + $styles = array_map( + function( $item ) { + return $item['style']; + }, + $classes_and_styles + ); + + $classes = array_filter( $classes ); + $styles = array_filter( $styles ); + + return array( + 'classes' => implode( ' ', $classes ), + 'styles' => implode( ' ', $styles ), + ); + } + + /** + * Get space-separated classes from block attributes. + * + * @param array $attributes Block attributes. + * @param array $properties Properties to get classes from. + * + * @return string Space-separated classes. + */ + public static function get_classes_by_attributes( $attributes, $properties = array() ) { + $classes_and_styles = self::get_classes_and_styles_by_attributes( $attributes, $properties ); + + return $classes_and_styles['classes']; + } + + /** + * Get space-separated style rules from block attributes. + * + * @param array $attributes Block attributes. + * @param array $properties Properties to get styles from. + * + * @return string Space-separated style rules. + */ + public static function get_styles_by_attributes( $attributes, $properties = array() ) { + $classes_and_styles = self::get_classes_and_styles_by_attributes( $attributes, $properties ); + + return $classes_and_styles['styles']; + } +}