Product Stock indicator: Add support for background color, margin, padding & various typography controls (https://github.com/woocommerce/woocommerce-blocks/pull/8954)
* Add color, typography, and spacing support to Product SKU block This commit introduces a new file `supports.ts` for the Product SKU block in the WooCommerce Blocks plugin, which adds color, typography, and spacing support. The following configuration has been added: 1. In `assets/js/atomic/blocks/product-elements/sku/supports.ts`, a new `supports` object is created, which extends the shared configuration and adds support for the following properties: - `text` and `background` color - `fontSize`, `lineHeight`, `__experimentalFontWeight`, `__experimentalFontFamily`, `__experimentalFontStyle`, `__experimentalTextTransform`, `__experimentalTextDecoration`, and `__experimentalLetterSpacing` for typography - `margin` and `padding` for spacing * Add color, typography, and spacing support for Product SKU block in All Products block This commit extends the support for color, typography, and spacing to the Product SKU block when used within the All Products block. The following changes have been made: 1. In `assets/js/atomic/blocks/product-elements/sku/block.tsx`, the `useColorProps`, `useSpacingProps`, and `useTypographyProps` hooks are imported and used to add the appropriate className and style properties to the rendered SKU element. 2. In `assets/js/atomic/blocks/product-elements/sku/edit.tsx`, the `style` property is separated from `useBlockProps()` and used directly on the `div` element for the SKU block. * Add server-side rendering class for Product SKU Gutenberg block This commit adds the ".wp-block-woocommerce-product-sku" class to the Product SKU Gutenberg block for server-side rendering purposes. The inclusion of this class ensures consistent styling between the editor and the front-end view of the block, providing a seamless experience for users. The class name is generated based on the Gutenberg block prefix "wp-block", the namespace "woocommerce", and the block name "product-sku", creating a unique and identifiable class for the block. This class enables developers to target the block specifically in both the editor and front-end styles, maintaining the integrity of the block's appearance and functionality across different environments. By adding this class to the server-side rendered version of the block, we ensure a unified and coherent styling experience throughout the block's usage. * Fix minor issues * Gate only experimental features behind isFeaturePluginBuild flag This commit refactors the Product SKU block supports to enable color, typography, and spacing features for all builds, while keeping experimental features specific to the feature plugin build. It also adds necessary lint and TypeScript error handling for the experimental spacing API. * Add overflow-wrap to Product SKU block and update comment This commit adds the overflow-wrap property to the Product SKU block styles to handle long SKU values gracefully. It also updates the comment for the experimental spacing API to better reflect the usage check. * Refactor Product SKU block classname and style handling This commit refactors the Product SKU block classname and style handling. It combines classnames for better readability and removes the hardcoded textTransform style in favor of default styles. This also fix the issue where textTransform style was not working as expected. * Add support for color, typography and spacing to stock indicator block This commit updates the stock-indicator block support in the woocommerce-blocks repository. It includes the following changes: - Added support for background color, line height, and various experimental typography features. - Conditionally included support for margin and padding based on the availability of the __experimentalGetSpacingClassesAndStyles function from the @wordpress/block-editor package. These updates provide more customization options for the stock-indicator block, allowing users to better match the appearance of this element to their site's design. * Refactor stock text generation and apply minor style adjustments This commit introduces a new function, `getTextBasedOnStock`, which handles the generation of stock text based on the stock information provided. It replaces the previous `lowStockText` and `stockText` functions, making the code more readable and maintainable. In addition, minor adjustments to the class name handling have been made to simplify the code and ensure consistent styling when used inside the All Products block. In the `edit.tsx` file, the `useBlockProps` function call has been updated to include the default `wc-block-components-product-stock-indicator` class name, ensuring it is always applied. * Remove redundant block type supports in ProductStockIndicator This commit removes the redundant get_block_type_supports() method from the ProductStockIndicator.php file, as it is no longer needed. The block type supports are now handled in the frontend.
This commit is contained in:
parent
a40f54e7f0
commit
be5356d30a
|
@ -12,6 +12,10 @@ export const blockAttributes: BlockAttributes = {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
isDescendantOfAllProducts: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default blockAttributes;
|
export default blockAttributes;
|
||||||
|
|
|
@ -7,7 +7,11 @@ import {
|
||||||
useInnerBlockLayoutContext,
|
useInnerBlockLayoutContext,
|
||||||
useProductDataContext,
|
useProductDataContext,
|
||||||
} from '@woocommerce/shared-context';
|
} from '@woocommerce/shared-context';
|
||||||
import { useColorProps, useTypographyProps } from '@woocommerce/base-hooks';
|
import {
|
||||||
|
useColorProps,
|
||||||
|
useTypographyProps,
|
||||||
|
useSpacingProps,
|
||||||
|
} from '@woocommerce/base-hooks';
|
||||||
import { withProductDataContext } from '@woocommerce/shared-hocs';
|
import { withProductDataContext } from '@woocommerce/shared-hocs';
|
||||||
import type { HTMLAttributes } from 'react';
|
import type { HTMLAttributes } from 'react';
|
||||||
|
|
||||||
|
@ -17,22 +21,43 @@ import type { HTMLAttributes } from 'react';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
import type { BlockAttributes } from './types';
|
import type { BlockAttributes } from './types';
|
||||||
|
|
||||||
const lowStockText = ( lowStock: number ): string => {
|
/**
|
||||||
|
* Get stock text based on stock. For example:
|
||||||
|
* - In stock
|
||||||
|
* - Out of stock
|
||||||
|
* - Available on backorder
|
||||||
|
* - 2 left in stock
|
||||||
|
*
|
||||||
|
* @param stockInfo Object containing stock information.
|
||||||
|
* @param stockInfo.isInStock Whether product is in stock.
|
||||||
|
* @param stockInfo.isLowStock Whether product is low in stock.
|
||||||
|
* @param stockInfo.lowStockAmount Number of items left in stock.
|
||||||
|
* @param stockInfo.isOnBackorder Whether product is on backorder.
|
||||||
|
* @return string Stock text.
|
||||||
|
*/
|
||||||
|
const getTextBasedOnStock = ( {
|
||||||
|
isInStock = false,
|
||||||
|
isLowStock = false,
|
||||||
|
lowStockAmount = null,
|
||||||
|
isOnBackorder = false,
|
||||||
|
}: {
|
||||||
|
isInStock?: boolean;
|
||||||
|
isLowStock?: boolean;
|
||||||
|
lowStockAmount?: number | null;
|
||||||
|
isOnBackorder?: boolean;
|
||||||
|
} ): string => {
|
||||||
|
if ( isLowStock && lowStockAmount !== null ) {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
/* translators: %d stock amount (number of items in stock for product) */
|
/* translators: %d stock amount (number of items in stock for product) */
|
||||||
__( '%d left in stock', 'woo-gutenberg-products-block' ),
|
__( '%d left in stock', 'woo-gutenberg-products-block' ),
|
||||||
lowStock
|
lowStockAmount
|
||||||
);
|
);
|
||||||
};
|
} else if ( isOnBackorder ) {
|
||||||
|
|
||||||
const stockText = ( inStock: boolean, isBackordered: boolean ): string => {
|
|
||||||
if ( isBackordered ) {
|
|
||||||
return __( 'Available on backorder', 'woo-gutenberg-products-block' );
|
return __( 'Available on backorder', 'woo-gutenberg-products-block' );
|
||||||
|
} else if ( isInStock ) {
|
||||||
|
return __( 'In stock', 'woo-gutenberg-products-block' );
|
||||||
}
|
}
|
||||||
|
return __( 'Out of stock', 'woo-gutenberg-products-block' );
|
||||||
return inStock
|
|
||||||
? __( 'In Stock', 'woo-gutenberg-products-block' )
|
|
||||||
: __( 'Out of Stock', 'woo-gutenberg-products-block' );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = BlockAttributes & HTMLAttributes< HTMLDivElement >;
|
type Props = BlockAttributes & HTMLAttributes< HTMLDivElement >;
|
||||||
|
@ -43,8 +68,9 @@ export const Block = ( props: Props ): JSX.Element | null => {
|
||||||
const { product } = useProductDataContext();
|
const { product } = useProductDataContext();
|
||||||
const colorProps = useColorProps( props );
|
const colorProps = useColorProps( props );
|
||||||
const typographyProps = useTypographyProps( props );
|
const typographyProps = useTypographyProps( props );
|
||||||
|
const spacingProps = useSpacingProps( props );
|
||||||
|
|
||||||
if ( ! product.id || ! product.is_purchasable ) {
|
if ( ! product.id ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,13 +80,8 @@ export const Block = ( props: Props ): JSX.Element | null => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={ classnames(
|
className={ classnames( className, {
|
||||||
className,
|
[ `${ parentClassName }__stock-indicator` ]: parentClassName,
|
||||||
colorProps.className,
|
|
||||||
'wc-block-components-product-stock-indicator',
|
|
||||||
{
|
|
||||||
[ `${ parentClassName }__stock-indicator` ]:
|
|
||||||
parentClassName,
|
|
||||||
'wc-block-components-product-stock-indicator--in-stock':
|
'wc-block-components-product-stock-indicator--in-stock':
|
||||||
inStock,
|
inStock,
|
||||||
'wc-block-components-product-stock-indicator--out-of-stock':
|
'wc-block-components-product-stock-indicator--out-of-stock':
|
||||||
|
@ -69,13 +90,29 @@ export const Block = ( props: Props ): JSX.Element | null => {
|
||||||
!! lowStock,
|
!! lowStock,
|
||||||
'wc-block-components-product-stock-indicator--available-on-backorder':
|
'wc-block-components-product-stock-indicator--available-on-backorder':
|
||||||
!! isBackordered,
|
!! isBackordered,
|
||||||
}
|
// When inside All products block
|
||||||
) }
|
...( props.isDescendantOfAllProducts && {
|
||||||
style={ { ...colorProps.style, ...typographyProps.style } }
|
[ colorProps.className ]: colorProps.className,
|
||||||
|
[ typographyProps.className ]: typographyProps.className,
|
||||||
|
'wc-block-components-product-stock-indicator wp-block-woocommerce-product-stock-indicator':
|
||||||
|
true,
|
||||||
|
} ),
|
||||||
|
} ) }
|
||||||
|
// When inside All products block
|
||||||
|
{ ...( props.isDescendantOfAllProducts && {
|
||||||
|
style: {
|
||||||
|
...colorProps.style,
|
||||||
|
...typographyProps.style,
|
||||||
|
...spacingProps.style,
|
||||||
|
},
|
||||||
|
} ) }
|
||||||
>
|
>
|
||||||
{ lowStock
|
{ getTextBasedOnStock( {
|
||||||
? lowStockText( lowStock )
|
isInStock: inStock,
|
||||||
: stockText( inStock, isBackordered ) }
|
isLowStock: !! lowStock,
|
||||||
|
lowStockAmount: lowStock,
|
||||||
|
isOnBackorder: isBackordered,
|
||||||
|
} ) }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,9 @@ const Edit = ( {
|
||||||
setAttributes,
|
setAttributes,
|
||||||
context,
|
context,
|
||||||
}: BlockEditProps< BlockAttributes > & { context: Context } ): JSX.Element => {
|
}: BlockEditProps< BlockAttributes > & { context: Context } ): JSX.Element => {
|
||||||
const blockProps = useBlockProps();
|
const { style, ...blockProps } = useBlockProps( {
|
||||||
|
className: 'wc-block-components-product-stock-indicator',
|
||||||
|
} );
|
||||||
|
|
||||||
const blockAttrs = {
|
const blockAttrs = {
|
||||||
...attributes,
|
...attributes,
|
||||||
|
@ -38,7 +40,15 @@ const Edit = ( {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div { ...blockProps }>
|
<div
|
||||||
|
{ ...blockProps }
|
||||||
|
/**
|
||||||
|
* If block is decendant of the All Products block, we don't want to
|
||||||
|
* apply style here because it will be applied inside Block using
|
||||||
|
* useColors, useTypography, and useSpacing hooks.
|
||||||
|
*/
|
||||||
|
style={ attributes.isDescendantOfAllProducts ? undefined : style }
|
||||||
|
>
|
||||||
<EditProductLink />
|
<EditProductLink />
|
||||||
<Block { ...blockAttrs } />
|
<Block { ...blockAttrs } />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,17 +2,39 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { isFeaturePluginBuild } from '@woocommerce/block-settings';
|
import { isFeaturePluginBuild } from '@woocommerce/block-settings';
|
||||||
|
import {
|
||||||
|
// @ts-expect-error We check if this exists before using it.
|
||||||
|
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
|
||||||
|
__experimentalGetSpacingClassesAndStyles,
|
||||||
|
} from '@wordpress/block-editor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import sharedConfig from '../shared/config';
|
||||||
|
|
||||||
export const supports = {
|
export const supports = {
|
||||||
...( isFeaturePluginBuild() && {
|
...sharedConfig.supports,
|
||||||
color: {
|
color: {
|
||||||
text: true,
|
text: true,
|
||||||
background: false,
|
background: true,
|
||||||
link: false,
|
|
||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
fontSize: true,
|
fontSize: true,
|
||||||
|
lineHeight: true,
|
||||||
|
...( isFeaturePluginBuild() && {
|
||||||
|
__experimentalFontWeight: true,
|
||||||
|
__experimentalFontFamily: true,
|
||||||
|
__experimentalFontStyle: true,
|
||||||
|
__experimentalTextTransform: true,
|
||||||
|
__experimentalTextDecoration: true,
|
||||||
|
__experimentalLetterSpacing: true,
|
||||||
|
} ),
|
||||||
|
},
|
||||||
|
...( typeof __experimentalGetSpacingClassesAndStyles === 'function' && {
|
||||||
|
spacing: {
|
||||||
|
margin: true,
|
||||||
|
padding: true,
|
||||||
},
|
},
|
||||||
__experimentalSelector: '.wc-block-components-product-stock-indicator',
|
|
||||||
} ),
|
} ),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export interface BlockAttributes {
|
export interface BlockAttributes {
|
||||||
productId: number;
|
productId: number;
|
||||||
isDescendentOfQueryLoop: boolean;
|
isDescendentOfQueryLoop: boolean;
|
||||||
|
isDescendantOfAllProducts: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,28 +22,6 @@ class ProductStockIndicator extends AbstractBlock {
|
||||||
*/
|
*/
|
||||||
protected $api_version = '2';
|
protected $api_version = '2';
|
||||||
|
|
||||||
/**
|
|
||||||
* Get block supports. Shared with the frontend.
|
|
||||||
* IMPORTANT: If you change anything here, make sure to update the JS file too.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function get_block_type_supports() {
|
|
||||||
return array(
|
|
||||||
'color' =>
|
|
||||||
array(
|
|
||||||
'link' => false,
|
|
||||||
'background' => false,
|
|
||||||
'text' => true,
|
|
||||||
),
|
|
||||||
'typography' =>
|
|
||||||
array(
|
|
||||||
'fontSize' => true,
|
|
||||||
),
|
|
||||||
'__experimentalSelector' => '.wc-block-components-product-stock-indicator',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register script and style assets for the block type before it is registered.
|
* Register script and style assets for the block type before it is registered.
|
||||||
*
|
*
|
||||||
|
@ -125,7 +103,7 @@ class ProductStockIndicator extends AbstractBlock {
|
||||||
$classnames .= $is_on_backorder ? ' wc-block-components-product-stock-indicator--available-on-backorder ' : '';
|
$classnames .= $is_on_backorder ? ' wc-block-components-product-stock-indicator--available-on-backorder ' : '';
|
||||||
|
|
||||||
$output = '';
|
$output = '';
|
||||||
$output .= '<div class="wc-block-components-product-stock-indicator ' . esc_attr( $classnames ) . '"';
|
$output .= '<div class="wc-block-components-product-stock-indicator wp-block-woocommerce-product-stock-indicator ' . esc_attr( $classnames ) . '"';
|
||||||
$output .= isset( $classes_and_styles['styles'] ) ? ' style="' . esc_attr( $classes_and_styles['styles'] ) . '"' : '';
|
$output .= isset( $classes_and_styles['styles'] ) ? ' style="' . esc_attr( $classes_and_styles['styles'] ) . '"' : '';
|
||||||
$output .= '>';
|
$output .= '>';
|
||||||
$output .= wp_kses_post( self::getTextBasedOnStock( $is_in_stock, $is_low_stock, $low_stock_amount, $is_on_backorder ) );
|
$output .= wp_kses_post( self::getTextBasedOnStock( $is_in_stock, $is_low_stock, $low_stock_amount, $is_on_backorder ) );
|
||||||
|
|
Loading…
Reference in New Issue