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

Product Stock indicator: Add support for background color, margin, padding & various typography controls #8954

Merged
merged 18 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ef08d62
Add color, typography, and spacing support to Product SKU block
imanish003 Mar 30, 2023
157cba8
Add color, typography, and spacing support for Product SKU block in A…
imanish003 Mar 30, 2023
13e27b0
Merge branch 'trunk' into add/7954-product-sku-global-styles-review
imanish003 Mar 31, 2023
8db4da5
Add server-side rendering class for Product SKU Gutenberg block
imanish003 Mar 31, 2023
a007701
Fix minor issues
imanish003 Mar 31, 2023
35f82f6
Gate only experimental features behind isFeaturePluginBuild flag
imanish003 Apr 4, 2023
705599d
Add overflow-wrap to Product SKU block and update comment
imanish003 Apr 4, 2023
9e10039
Refactor Product SKU block classname and style handling
imanish003 Apr 4, 2023
8c4e4c5
Merge branch 'trunk' into add/7954-product-sku-global-styles-review
imanish003 Apr 4, 2023
4b53363
Merge branch 'trunk' into add/7954-product-sku-global-styles-review
imanish003 Apr 4, 2023
e5e1c4b
Add support for color, typography and spacing to stock indicator block
imanish003 Apr 4, 2023
a2fb221
Merge branch 'trunk' into add/7954-product-stock-indicator-spacing
imanish003 Apr 4, 2023
22dad22
Merge branch 'trunk' into add/7954-product-stock-indicator-spacing
imanish003 Apr 5, 2023
0c69a83
Refactor stock text generation and apply minor style adjustments
imanish003 Apr 6, 2023
f5a26f4
Merge branch 'trunk' into add/7954-product-stock-indicator-spacing
imanish003 Apr 6, 2023
773f782
Merge branch 'trunk' into add/7954-product-stock-indicator-spacing
imanish003 Apr 14, 2023
b304150
Remove redundant block type supports in ProductStockIndicator
imanish003 Apr 14, 2023
c0301f6
Merge branch 'trunk' into add/7954-product-stock-indicator-spacing
imanish003 Apr 17, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export const blockAttributes: BlockAttributes = {
type: 'boolean',
default: false,
},
isDescendantOfAllProducts: {
type: 'boolean',
default: false,
},
};

export default blockAttributes;
111 changes: 74 additions & 37 deletions assets/js/atomic/blocks/product-elements/stock-indicator/block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {
useInnerBlockLayoutContext,
useProductDataContext,
} 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 type { HTMLAttributes } from 'react';

Expand All @@ -17,22 +21,43 @@ import type { HTMLAttributes } from 'react';
import './style.scss';
import type { BlockAttributes } from './types';

const lowStockText = ( lowStock: number ): string => {
return sprintf(
/* translators: %d stock amount (number of items in stock for product) */
__( '%d left in stock', 'woo-gutenberg-products-block' ),
lowStock
);
};

const stockText = ( inStock: boolean, isBackordered: boolean ): string => {
if ( isBackordered ) {
/**
* 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(
/* translators: %d stock amount (number of items in stock for product) */
__( '%d left in stock', 'woo-gutenberg-products-block' ),
lowStockAmount
);
} else if ( isOnBackorder ) {
return __( 'Available on backorder', 'woo-gutenberg-products-block' );
} else if ( isInStock ) {
return __( 'In stock', 'woo-gutenberg-products-block' );
}

return inStock
? __( 'In Stock', 'woo-gutenberg-products-block' )
: __( 'Out of Stock', 'woo-gutenberg-products-block' );
return __( 'Out of stock', 'woo-gutenberg-products-block' );
};

type Props = BlockAttributes & HTMLAttributes< HTMLDivElement >;
Expand All @@ -43,8 +68,9 @@ export const Block = ( props: Props ): JSX.Element | null => {
const { product } = useProductDataContext();
const colorProps = useColorProps( props );
const typographyProps = useTypographyProps( props );
const spacingProps = useSpacingProps( props );

if ( ! product.id || ! product.is_purchasable ) {
if ( ! product.id ) {
return null;
}

Expand All @@ -54,28 +80,39 @@ export const Block = ( props: Props ): JSX.Element | null => {

return (
<div
className={ classnames(
className,
colorProps.className,
'wc-block-components-product-stock-indicator',
{
[ `${ parentClassName }__stock-indicator` ]:
parentClassName,
'wc-block-components-product-stock-indicator--in-stock':
inStock,
'wc-block-components-product-stock-indicator--out-of-stock':
! inStock,
'wc-block-components-product-stock-indicator--low-stock':
!! lowStock,
'wc-block-components-product-stock-indicator--available-on-backorder':
!! isBackordered,
}
) }
style={ { ...colorProps.style, ...typographyProps.style } }
className={ classnames( className, {
[ `${ parentClassName }__stock-indicator` ]: parentClassName,
'wc-block-components-product-stock-indicator--in-stock':
inStock,
'wc-block-components-product-stock-indicator--out-of-stock':
! inStock,
'wc-block-components-product-stock-indicator--low-stock':
!! lowStock,
'wc-block-components-product-stock-indicator--available-on-backorder':
!! isBackordered,
// When inside All products block
...( props.isDescendantOfAllProducts && {
[ 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
? lowStockText( lowStock )
: stockText( inStock, isBackordered ) }
{ getTextBasedOnStock( {
isInStock: inStock,
isLowStock: !! lowStock,
lowStockAmount: lowStock,
isOnBackorder: isBackordered,
} ) }
</div>
);
};
Expand Down
14 changes: 12 additions & 2 deletions assets/js/atomic/blocks/product-elements/stock-indicator/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const Edit = ( {
setAttributes,
context,
}: BlockEditProps< BlockAttributes > & { context: Context } ): JSX.Element => {
const blockProps = useBlockProps();
const { style, ...blockProps } = useBlockProps( {
className: 'wc-block-components-product-stock-indicator',
} );

const blockAttrs = {
...attributes,
Expand All @@ -38,7 +40,15 @@ const Edit = ( {
);

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 />
<Block { ...blockAttrs } />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,39 @@
* External dependencies
*/
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 = {
...( isFeaturePluginBuild() && {
color: {
text: true,
background: false,
link: false,
},
typography: {
fontSize: true,
...sharedConfig.supports,
color: {
text: true,
background: true,
},
typography: {
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',
} ),
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface BlockAttributes {
productId: number;
isDescendentOfQueryLoop: boolean;
isDescendantOfAllProducts: boolean;
}
24 changes: 1 addition & 23 deletions src/BlockTypes/ProductStockIndicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,6 @@ class ProductStockIndicator extends AbstractBlock {
*/
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.
*
Expand Down Expand Up @@ -125,7 +103,7 @@ protected function render( $attributes, $content, $block ) {
$classnames .= $is_on_backorder ? ' wc-block-components-product-stock-indicator--available-on-backorder ' : '';

$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 .= '>';
$output .= wp_kses_post( self::getTextBasedOnStock( $is_in_stock, $is_low_stock, $low_stock_amount, $is_on_backorder ) );
Expand Down