diff --git a/assets/js/blocks/cart/cart-cross-sells-product-list/cart-cross-sells-product.tsx b/assets/js/blocks/cart/cart-cross-sells-product-list/cart-cross-sells-product.tsx index 145ec2316af..74e1313a3e4 100644 --- a/assets/js/blocks/cart/cart-cross-sells-product-list/cart-cross-sells-product.tsx +++ b/assets/js/blocks/cart/cart-cross-sells-product-list/cart-cross-sells-product.tsx @@ -18,7 +18,7 @@ import { Block as ProductSaleBadge } from '../../../atomic/blocks/product-elemen import { Block as ProductPrice } from '../../../atomic/blocks/product-elements/price/block'; import { AddToCartButton } from '../../../atomic/blocks/product-elements/add-to-cart/shared'; -interface CrossSellsProducProps { +interface CrossSellsProductProps { crossSellsProduct: ProductResponseItem; isLoading: boolean; } @@ -26,12 +26,12 @@ interface CrossSellsProducProps { const CartCrossSellsProduct = ( { crossSellsProduct, isLoading, -}: CrossSellsProducProps ): JSX.Element => { +}: CrossSellsProductProps ): JSX.Element => { const { product } = useProductDataContext(); const { permalink } = product; return ( -
+
- + diff --git a/assets/js/blocks/cart/cart-cross-sells-product-list/index.tsx b/assets/js/blocks/cart/cart-cross-sells-product-list/index.tsx index fe9627a4af2..fdb7cbe8d60 100644 --- a/assets/js/blocks/cart/cart-cross-sells-product-list/index.tsx +++ b/assets/js/blocks/cart/cart-cross-sells-product-list/index.tsx @@ -2,6 +2,7 @@ * External dependencies */ import { ProductResponseItem } from '@woocommerce/type-defs/product-response'; +import Noninteractive from '@woocommerce/base-components/noninteractive'; /** * Internal dependencies @@ -16,15 +17,19 @@ interface CrossSellsProducListProps { crossSellsProducts: ProductResponseItem[]; isLoading: boolean; className?: string; + columns: number; } const CartCrossSellsProductList = ( { crossSellsProducts, isLoading = false, + columns, }: CrossSellsProducListProps ): JSX.Element => { const products = isLoading ? placeholderRows - : crossSellsProducts.map( ( crossSellsProduct ) => { + : crossSellsProducts.map( ( crossSellsProduct, i ) => { + if ( i >= columns ) return null; + return ( { products }; + return { products }; }; export default CartCrossSellsProductList; diff --git a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-block/edit.tsx b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-block/edit.tsx index a2ea2931276..25d8a8a9b20 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-block/edit.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-block/edit.tsx @@ -1,18 +1,14 @@ /** * External dependencies */ -import { useBlockProps, InnerBlocks } from '@wordpress/block-editor'; import type { TemplateArray } from '@wordpress/blocks'; import { __ } from '@wordpress/i18n'; +import { useBlockProps, InnerBlocks } from '@wordpress/block-editor'; -/** - * Internal dependencies - */ export const Edit = (): JSX.Element => { const blockProps = useBlockProps( { className: 'wc-block-cart__cross-sells', } ); - const defaultTemplate = [ [ 'core/heading', diff --git a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.json b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.json index 673dbb1e4f5..aa84030ad19 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.json +++ b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.json @@ -11,6 +11,12 @@ "reusable": false, "inserter": false }, + "attributes": { + "columns": { + "type": "number", + "default": 3 + } + }, "parent": [ "woocommerce/cart-cross-sells-block" ], "textdomain": "woo-gutenberg-products-block", "apiVersion": 2 diff --git a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.tsx b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.tsx index ffb4acd9e6f..33e0d4720c0 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.tsx @@ -8,12 +8,19 @@ import { useStoreCart } from '@woocommerce/base-context/hooks'; */ import CartCrossSellsProductList from '../../cart-cross-sells-product-list'; -const Block = ( { className }: { className: string } ): JSX.Element => { +interface BlockProps { + className?: string; + columns: number; +} + +const Block = ( { className, columns }: BlockProps ): JSX.Element => { const { crossSellsProducts, cartIsLoading } = useStoreCart(); + return ( ); diff --git a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/edit.tsx b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/edit.tsx index 5f6e4d91ddf..6ee9075a260 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/edit.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/edit.tsx @@ -1,7 +1,10 @@ /** * External dependencies */ -import { useBlockProps } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { PanelBody, RangeControl } from '@wordpress/components'; +import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; +import { getSetting } from '@woocommerce/settings'; /** * Internal dependencies @@ -9,17 +12,41 @@ import { useBlockProps } from '@wordpress/block-editor'; import Block from './block'; import './editor.scss'; -export const Edit = ( { - attributes, -}: { - attributes: { className: string }; -} ): JSX.Element => { - const { className } = attributes; +interface Attributes { + className?: string; + columns: number; +} + +interface Props { + attributes: Attributes; + setAttributes: ( attributes: Record< string, unknown > ) => void; +} + +export const Edit = ( { attributes, setAttributes }: Props ): JSX.Element => { + const { className, columns } = attributes; const blockProps = useBlockProps(); return (
- + + + + setAttributes( { columns: value } ) + } + min={ getSetting( 'min_columns', 1 ) } + max={ getSetting( 'max_columns', 6 ) } + /> + + +
); }; diff --git a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/editor.scss b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/editor.scss index a964032e6a2..e2aa9cfc547 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/editor.scss +++ b/assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/editor.scss @@ -1,12 +1,12 @@ .wp-block-woocommerce-cart-cross-sells-products-block { - display: flex; - flex-wrap: wrap; - >div { - flex: 0 0 30%; - list-style: none; + .cross-sells-product { + display: inline-block; + margin-bottom: 2em; padding-right: 5%; text-align: center; + vertical-align: top; + width: 30%; &:nth-child(3n + 3) { padding-right: 0%; diff --git a/assets/js/blocks/cart/inner-blocks/cart-items-block/edit.tsx b/assets/js/blocks/cart/inner-blocks/cart-items-block/edit.tsx index b761a8d4240..22d0c07ee69 100644 --- a/assets/js/blocks/cart/inner-blocks/cart-items-block/edit.tsx +++ b/assets/js/blocks/cart/inner-blocks/cart-items-block/edit.tsx @@ -13,7 +13,11 @@ import { getAllowedBlocks, } from '../../../cart-checkout-shared'; -export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => { +interface Props { + clientId: string; +} + +export const Edit = ( { clientId }: Props ): JSX.Element => { const blockProps = useBlockProps( { className: 'wc-block-cart__main' } ); const allowedBlocks = getAllowedBlocks( innerBlockAreas.CART_ITEMS ); const defaultTemplate = [ diff --git a/assets/js/previews/cart.ts b/assets/js/previews/cart.ts index 99b34b4e270..6852a35ee9b 100644 --- a/assets/js/previews/cart.ts +++ b/assets/js/previews/cart.ts @@ -174,7 +174,6 @@ export const previewCart: CartResponse = { ], cross_sells: [ { - key: '1', id: 1, name: __( 'Polo', 'woo-gutenberg-products-block' ), permalink: 'https://example.org', @@ -210,7 +209,6 @@ export const previewCart: CartResponse = { average_rating: 4.5, }, { - key: '2', id: 2, name: __( 'Long Sleeve Tee', 'woo-gutenberg-products-block' ), permalink: 'https://example.org', @@ -247,7 +245,6 @@ export const previewCart: CartResponse = { average_rating: 4, }, { - key: '3', id: 3, name: __( 'Hoodie with Zipper', 'woo-gutenberg-products-block' ), permalink: 'https://example.org', @@ -285,6 +282,117 @@ export const previewCart: CartResponse = { ], average_rating: 1, }, + { + id: 4, + name: __( 'Hoodie with Logo', 'woo-gutenberg-products-block' ), + permalink: 'https://example.org', + on_sale: false, + prices: { + currency_code: 'USD', + currency_symbol: '$', + currency_minor_unit: 2, + currency_decimal_separator: '.', + currency_thousand_separator: ',', + currency_prefix: '$', + currency_suffix: '', + price: displayWithTax ? '4500' : '4250', + regular_price: displayWithTax ? '4500' : '4250', + sale_price: displayWithTax ? '4500' : '4250', + raw_prices: { + precision: 6, + price: displayWithTax ? '45000000' : '42500000', + regular_price: displayWithTax ? '45000000' : '42500000', + sale_price: displayWithTax ? '45000000' : '42500000', + }, + }, + images: [ + { + id: 17, + src: WC_BLOCKS_IMAGE_URL + 'previews/hoodie-with-logo.jpg', + thumbnail: + WC_BLOCKS_IMAGE_URL + 'previews/hoodie-with-logo.jpg', + srcset: '', + sizes: '', + name: '', + alt: '', + }, + ], + average_rating: 5, + }, + { + id: 5, + name: __( 'Hoodie with Pocket', 'woo-gutenberg-products-block' ), + permalink: 'https://example.org', + on_sale: true, + prices: { + currency_code: 'USD', + currency_symbol: '$', + currency_minor_unit: 2, + currency_decimal_separator: '.', + currency_thousand_separator: ',', + currency_prefix: '$', + currency_suffix: '', + price: displayWithTax ? '3500' : '3250', + regular_price: displayWithTax ? '4500' : '4250', + sale_price: displayWithTax ? '3500' : '3250', + raw_prices: { + precision: 6, + price: displayWithTax ? '35000000' : '32500000', + regular_price: displayWithTax ? '45000000' : '42500000', + sale_price: displayWithTax ? '35000000' : '32500000', + }, + }, + images: [ + { + id: 17, + src: + WC_BLOCKS_IMAGE_URL + 'previews/hoodie-with-pocket.jpg', + thumbnail: + WC_BLOCKS_IMAGE_URL + 'previews/hoodie-with-pocket.jpg', + srcset: '', + sizes: '', + name: '', + alt: '', + }, + ], + average_rating: 3.75, + }, + { + id: 6, + name: __( 'T-Shirt', 'woo-gutenberg-products-block' ), + permalink: 'https://example.org', + on_sale: false, + prices: { + currency_code: 'USD', + currency_symbol: '$', + currency_minor_unit: 2, + currency_decimal_separator: '.', + currency_thousand_separator: ',', + currency_prefix: '$', + currency_suffix: '', + price: displayWithTax ? '1800' : '1500', + regular_price: displayWithTax ? '1800' : '1500', + sale_price: displayWithTax ? '1800' : '1500', + raw_prices: { + precision: 6, + price: displayWithTax ? '1800000' : '1500000', + regular_price: displayWithTax ? '1800000' : '1500000', + sale_price: displayWithTax ? '1800000' : '1500000', + }, + }, + images: [ + { + id: 17, + src: WC_BLOCKS_IMAGE_URL + 'previews/tshirt.jpg', + thumbnail: WC_BLOCKS_IMAGE_URL + 'previews/tshirt.jpg', + srcset: '', + sizes: '', + name: '', + alt: '', + }, + ], + average_rating: 3, + }, ], fees: [ { diff --git a/assets/js/types/type-defs/hooks.ts b/assets/js/types/type-defs/hooks.ts index 9b007723075..09cead7e6c8 100644 --- a/assets/js/types/type-defs/hooks.ts +++ b/assets/js/types/type-defs/hooks.ts @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import { ProductResponseItem } from '@woocommerce/type-defs/product-response'; + /** * Internal dependencies */ @@ -34,7 +39,7 @@ export interface StoreCartCoupon { export interface StoreCart { cartCoupons: CartResponseCoupons; cartItems: Array< CartResponseItem >; - crossSellsItems: Array< CartResponseItem >; + crossSellsProducts: Array< ProductResponseItem >; cartFees: Array< CartResponseFeeItem >; cartItemsCount: number; cartItemsWeight: number; diff --git a/composer.json b/composer.json index f76be912842..69b22e9f166 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,8 @@ "name": "woocommerce/woocommerce-blocks", "description": "WooCommerce blocks for the Gutenberg editor.", "homepage": "https://woocommerce.com/", - "type": "wordpress-plugin", + "type":"wordpress-plugin", + "version": "7.9.0-dev", "keywords": [ "gutenberg", "woocommerce", diff --git a/images/previews/hoodie-with-logo.jpg b/images/previews/hoodie-with-logo.jpg new file mode 100644 index 00000000000..9609e3bf856 Binary files /dev/null and b/images/previews/hoodie-with-logo.jpg differ diff --git a/images/previews/hoodie-with-pocket.jpg b/images/previews/hoodie-with-pocket.jpg new file mode 100644 index 00000000000..72c3272d0cb Binary files /dev/null and b/images/previews/hoodie-with-pocket.jpg differ diff --git a/images/previews/tshirt.jpg b/images/previews/tshirt.jpg new file mode 100644 index 00000000000..d775d53efd3 Binary files /dev/null and b/images/previews/tshirt.jpg differ