diff --git a/assets/css/style.scss b/assets/css/style.scss index ab4af14111a..787fcf3f1e2 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -236,7 +236,7 @@ } .wc-block-grid__products .wc-block-grid__product-onsale, - .wc-block-layout .wc-block-components-product-sale-badge { + .wc-block-components-product-sale-badge { background: $twentytwenty-highlights-color; color: #fff; font-family: $twentytwenty-headings; diff --git a/assets/js/atomic/blocks/component-init.js b/assets/js/atomic/blocks/component-init.js index c3a721df8a1..7cb50775594 100644 --- a/assets/js/atomic/blocks/component-init.js +++ b/assets/js/atomic/blocks/component-init.js @@ -13,7 +13,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-price', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/price" */ './product/price/block' + /* webpackChunkName: "atomic-block-components/price" */ './product-elements/price/block' ) ), } ); @@ -22,7 +22,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-image', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/image" */ './product/image/frontend' + /* webpackChunkName: "atomic-block-components/image" */ './product-elements/image/frontend' ) ), } ); @@ -31,7 +31,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-title', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/title" */ './product/title/frontend' + /* webpackChunkName: "atomic-block-components/title" */ './product-elements/title/frontend' ) ), } ); @@ -40,7 +40,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-rating', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/rating" */ './product/rating/block' + /* webpackChunkName: "atomic-block-components/rating" */ './product-elements/rating/block' ) ), } ); @@ -49,7 +49,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-button', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/button" */ './product/button/block' + /* webpackChunkName: "atomic-block-components/button" */ './product-elements/button/block' ) ), } ); @@ -58,7 +58,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-summary', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/summary" */ './product/summary/block' + /* webpackChunkName: "atomic-block-components/summary" */ './product-elements/summary/block' ) ), } ); @@ -67,7 +67,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-sale-badge', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/sale-badge" */ './product/sale-badge/block' + /* webpackChunkName: "atomic-block-components/sale-badge" */ './product-elements/sale-badge/block' ) ), } ); @@ -76,7 +76,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-sku', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/sku" */ './product/sku/block' + /* webpackChunkName: "atomic-block-components/sku" */ './product-elements/sku/block' ) ), } ); @@ -85,7 +85,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-category-list', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/category-list" */ './product/category-list/block' + /* webpackChunkName: "atomic-block-components/category-list" */ './product-elements/category-list/block' ) ), } ); @@ -94,7 +94,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-tag-list', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/tag-list" */ './product/tag-list/block' + /* webpackChunkName: "atomic-block-components/tag-list" */ './product-elements/tag-list/block' ) ), } ); @@ -103,7 +103,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-stock-indicator', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/stock-indicator" */ './product/stock-indicator/block' + /* webpackChunkName: "atomic-block-components/stock-indicator" */ './product-elements/stock-indicator/block' ) ), } ); @@ -112,7 +112,7 @@ registerBlockComponent( { blockName: 'woocommerce/product-add-to-cart', component: lazy( () => import( - /* webpackChunkName: "atomic-block-components/add-to-cart" */ './product/add-to-cart/frontend' + /* webpackChunkName: "atomic-block-components/add-to-cart" */ './product-elements/add-to-cart/frontend' ) ), } ); diff --git a/assets/js/atomic/blocks/index.js b/assets/js/atomic/blocks/index.js index 1c55feb04e6..5a1ff791cbd 100644 --- a/assets/js/atomic/blocks/index.js +++ b/assets/js/atomic/blocks/index.js @@ -1,15 +1,15 @@ /** * Internal dependencies */ -import './product/title'; -import './product/price'; -import './product/image'; -import './product/rating'; -import './product/button'; -import './product/summary'; -import './product/sale-badge'; -import './product/sku'; -import './product/category-list'; -import './product/tag-list'; -import './product/stock-indicator'; -import './product/add-to-cart'; +import './product-elements/title'; +import './product-elements/price'; +import './product-elements/image'; +import './product-elements/rating'; +import './product-elements/button'; +import './product-elements/summary'; +import './product-elements/sale-badge'; +import './product-elements/sku'; +import './product-elements/category-list'; +import './product-elements/tag-list'; +import './product-elements/stock-indicator'; +import './product-elements/add-to-cart'; diff --git a/assets/js/atomic/blocks/product/add-to-cart/attributes.js b/assets/js/atomic/blocks/product-elements/add-to-cart/attributes.js similarity index 72% rename from assets/js/atomic/blocks/product/add-to-cart/attributes.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/attributes.js index dd6bdd2c27f..993ebcc8ec6 100644 --- a/assets/js/atomic/blocks/product/add-to-cart/attributes.js +++ b/assets/js/atomic/blocks/product-elements/add-to-cart/attributes.js @@ -3,6 +3,10 @@ export const blockAttributes = { type: 'boolean', default: false, }, + productId: { + type: 'number', + default: 0, + }, }; export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/add-to-cart/block.js b/assets/js/atomic/blocks/product-elements/add-to-cart/block.js similarity index 77% rename from assets/js/atomic/blocks/product/add-to-cart/block.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/block.js index 59cde68d877..be555fb5029 100644 --- a/assets/js/atomic/blocks/product/add-to-cart/block.js +++ b/assets/js/atomic/blocks/product-elements/add-to-cart/block.js @@ -6,6 +6,7 @@ import classnames from 'classnames'; import { AddToCartFormContextProvider } from '@woocommerce/base-context'; import { useProductDataContext } from '@woocommerce/shared-context'; import { isEmpty } from 'lodash'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; /** * Internal dependencies @@ -25,13 +26,10 @@ import { * @param {Object} props Incoming props. * @param {string} [props.className] CSS Class name for the component. * @param {boolean} [props.showFormElements] Should form elements be shown? - * @param {Object} [props.product] Optional product object. Product from context will be - * used if this is not provided. * @return {*} The component. */ -const Block = ( { className, showFormElements, ...props } ) => { - const productDataContext = useProductDataContext(); - const product = props.product || productDataContext.product || {}; +const Block = ( { className, showFormElements } ) => { + const { product } = useProductDataContext(); const componentClass = classnames( className, 'wc-block-components-product-add-to-cart', @@ -50,9 +48,7 @@ const Block = ( { className, showFormElements, ...props } ) => {
<> { showFormElements ? ( - + ) : ( ) } @@ -80,7 +76,6 @@ const AddToCartForm = ( { productType } ) => { Block.propTypes = { className: PropTypes.string, - product: PropTypes.object, }; -export default Block; +export default withProductDataContext( Block ); diff --git a/assets/js/atomic/blocks/product-elements/add-to-cart/constants.js b/assets/js/atomic/blocks/product-elements/add-to-cart/constants.js new file mode 100644 index 00000000000..b01bd0f7f3b --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/add-to-cart/constants.js @@ -0,0 +1,12 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { cart, Icon } from '@woocommerce/icons'; + +export const BLOCK_TITLE = __( 'Add to Cart', 'woo-gutenberg-products-block' ); +export const BLOCK_ICON = ; +export const BLOCK_DESCRIPTION = __( + 'Displays an add to cart button. Optionally displays other add to cart form elements.', + 'woo-gutenberg-products-block' +); diff --git a/assets/js/atomic/blocks/product/add-to-cart/edit.js b/assets/js/atomic/blocks/product-elements/add-to-cart/edit.js similarity index 74% rename from assets/js/atomic/blocks/product/add-to-cart/edit.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/edit.js index 35ad598ba62..091e68ea5d3 100644 --- a/assets/js/atomic/blocks/product/add-to-cart/edit.js +++ b/assets/js/atomic/blocks/product-elements/add-to-cart/edit.js @@ -13,10 +13,11 @@ import { InspectorControls } from '@wordpress/block-editor'; */ import './style.scss'; import Block from './block'; +import withProductSelector from '../shared/with-product-selector'; +import { BLOCK_TITLE, BLOCK_ICON } from './constants'; -export default ( { attributes, setAttributes } ) => { - const productDataContext = useProductDataContext(); - const product = productDataContext.product || {}; +const Edit = ( { attributes, setAttributes } ) => { + const { product } = useProductDataContext(); const { className, showFormElements } = attributes; return ( @@ -26,7 +27,7 @@ export default ( { attributes, setAttributes } ) => { 'wc-block-components-product-add-to-cart' ) } > - + { product.type !== 'external' && ( {
); }; + +export default withProductSelector( { + icon: BLOCK_ICON, + label: BLOCK_TITLE, + description: __( + "Choose a product to display it's add to cart form.", + 'woo-gutenberg-products-block' + ), +} )( Edit ); diff --git a/assets/js/atomic/blocks/product/add-to-cart/frontend.js b/assets/js/atomic/blocks/product-elements/add-to-cart/frontend.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/frontend.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/frontend.js diff --git a/assets/js/atomic/blocks/product-elements/add-to-cart/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/index.js new file mode 100644 index 00000000000..d807f143175 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/add-to-cart/index.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { registerExperimentalBlockType } from '@woocommerce/block-settings'; + +/** + * Internal dependencies + */ +import sharedConfig from '../shared/config'; +import edit from './edit'; +import attributes from './attributes'; +import { + BLOCK_TITLE as title, + BLOCK_ICON as icon, + BLOCK_DESCRIPTION as description, +} from './constants'; + +const blockConfig = { + title, + description, + icon: { + src: icon, + foreground: '#874FB9', + }, + edit, + attributes, +}; + +registerExperimentalBlockType( 'woocommerce/product-add-to-cart', { + ...sharedConfig, + ...blockConfig, +} ); diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/external.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/external.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/external.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/external.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/grouped/group-list/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/grouped/group-list/index.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/grouped/group-list/index.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/grouped/group-list/index.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/grouped/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/grouped/index.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/grouped/index.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/grouped/index.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/index.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/index.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/index.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/simple.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/simple.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/simple.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/simple.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/variable/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/index.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/variable/index.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/index.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/attribute-picker.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/attribute-picker.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/attribute-picker.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/attribute-picker.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/attribute-select-control.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/attribute-select-control.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/attribute-select-control.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/attribute-select-control.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/index.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/index.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/index.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/style.scss b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/style.scss similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/style.scss rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/style.scss diff --git a/assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/utils.js b/assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/utils.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/product-types/variable/variation-attributes/utils.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/product-types/variable/variation-attributes/utils.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/shared/add-to-cart-button.js b/assets/js/atomic/blocks/product-elements/add-to-cart/shared/add-to-cart-button.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/shared/add-to-cart-button.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/shared/add-to-cart-button.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/shared/index.js b/assets/js/atomic/blocks/product-elements/add-to-cart/shared/index.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/shared/index.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/shared/index.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/shared/product-unavailable.js b/assets/js/atomic/blocks/product-elements/add-to-cart/shared/product-unavailable.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/shared/product-unavailable.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/shared/product-unavailable.js diff --git a/assets/js/atomic/blocks/product/add-to-cart/shared/quantity-input.js b/assets/js/atomic/blocks/product-elements/add-to-cart/shared/quantity-input.js similarity index 100% rename from assets/js/atomic/blocks/product/add-to-cart/shared/quantity-input.js rename to assets/js/atomic/blocks/product-elements/add-to-cart/shared/quantity-input.js diff --git a/assets/js/atomic/blocks/product-elements/add-to-cart/style.scss b/assets/js/atomic/blocks/product-elements/add-to-cart/style.scss new file mode 100644 index 00000000000..e3eb377ace2 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/add-to-cart/style.scss @@ -0,0 +1,43 @@ +.wc-block-components-product-add-to-cart { + margin: 0; + display: flex; + flex-wrap: wrap; + + .wc-block-components-product-add-to-cart-button { + margin: 0 0 em($gap-small) 0; + + .wc-block-components-button__text { + display: block; + + > svg { + fill: currentColor; + vertical-align: top; + width: 1.5em; + height: 1.5em; + margin: -0.25em 0 -0.25em 0.5em; + } + } + } + + .wc-block-components-product-add-to-cart-quantity { + margin: 0 1em em($gap-small) 0; + width: 5em; + padding: 0.618em; + background: $white; + border: 1px solid #ccc; + border-radius: 2px; + color: #43454b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.125); + text-align: center; + } +} +.wc-block-components-product-add-to-cart--placeholder { + .wc-block-components-product-add-to-cart-quantity, + .wc-block-components-product-add-to-cart-button { + @include placeholder(); + } +} + +.wc-block-grid .wc-block-components-product-add-to-cart { + justify-content: center; +} diff --git a/assets/js/atomic/blocks/product-elements/button/attributes.js b/assets/js/atomic/blocks/product-elements/button/attributes.js new file mode 100644 index 00000000000..5bac8820c40 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/button/attributes.js @@ -0,0 +1,8 @@ +export const blockAttributes = { + productId: { + type: 'number', + default: 0, + }, +}; + +export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/button/block.js b/assets/js/atomic/blocks/product-elements/button/block.js similarity index 87% rename from assets/js/atomic/blocks/product/button/block.js rename to assets/js/atomic/blocks/product-elements/button/block.js index 9a8c7089d22..15e1ed4483d 100644 --- a/assets/js/atomic/blocks/product/button/block.js +++ b/assets/js/atomic/blocks/product-elements/button/block.js @@ -12,6 +12,7 @@ import { useInnerBlockLayoutContext, useProductDataContext, } from '@woocommerce/shared-context'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; /** * Internal dependencies @@ -23,14 +24,11 @@ import './style.scss'; * * @param {Object} props Incoming props. * @param {string} [props.className] CSS Class name for the component. - * @param {Object} [props.product] Optional product object. Product from context will be used if - * this is not provided. * @return {*} The component. */ -const Block = ( { className, ...props } ) => { +const Block = ( { className } ) => { const { parentClassName } = useInnerBlockLayoutContext(); - const productDataContext = useProductDataContext(); - const product = props.product || productDataContext.product; + const { product } = useProductDataContext(); return (
{ className, 'wp-block-button', 'wc-block-components-product-button', - `${ parentClassName }__product-add-to-cart` + { + [ `${ parentClassName }__product-add-to-cart` ]: parentClassName, + } ) } > - { product ? ( + { product.id ? ( ) : ( @@ -142,7 +142,6 @@ const AddToCartButtonPlaceholder = () => { Block.propTypes = { className: PropTypes.string, - product: PropTypes.object, }; -export default Block; +export default withProductDataContext( Block ); diff --git a/assets/js/atomic/blocks/product-elements/button/constants.js b/assets/js/atomic/blocks/product-elements/button/constants.js new file mode 100644 index 00000000000..75a90cb397f --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/button/constants.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { cart, Icon } from '@woocommerce/icons'; + +export const BLOCK_TITLE = __( + 'Add to Cart Button', + 'woo-gutenberg-products-block' +); +export const BLOCK_ICON = ; +export const BLOCK_DESCRIPTION = __( + 'Display a call to action button which either adds the product to the cart, or links to the product page.', + 'woo-gutenberg-products-block' +); diff --git a/assets/js/atomic/blocks/product-elements/button/edit.js b/assets/js/atomic/blocks/product-elements/button/edit.js new file mode 100644 index 00000000000..7259d387c8f --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/button/edit.js @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Disabled } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import Block from './block'; +import withProductSelector from '../shared/with-product-selector'; +import { BLOCK_TITLE, BLOCK_ICON } from './constants'; + +const Edit = ( { attributes } ) => { + return ( + + + + ); +}; + +export default withProductSelector( { + icon: BLOCK_ICON, + label: BLOCK_TITLE, + description: __( + "Choose a product to display it's add to cart button.", + 'woo-gutenberg-products-block' + ), +} )( Edit ); diff --git a/assets/js/atomic/blocks/product-elements/button/index.js b/assets/js/atomic/blocks/product-elements/button/index.js new file mode 100644 index 00000000000..305b9c520d7 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/button/index.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import sharedConfig from '../shared/config'; +import attributes from './attributes'; +import edit from './edit'; +import { + BLOCK_TITLE as title, + BLOCK_ICON as icon, + BLOCK_DESCRIPTION as description, +} from './constants'; + +const blockConfig = { + title, + description, + icon: { + src: icon, + foreground: '#874FB9', + }, + attributes, + edit, +}; + +registerBlockType( 'woocommerce/product-button', { + ...sharedConfig, + ...blockConfig, +} ); diff --git a/assets/js/atomic/blocks/product/button/style.scss b/assets/js/atomic/blocks/product-elements/button/style.scss similarity index 72% rename from assets/js/atomic/blocks/product/button/style.scss rename to assets/js/atomic/blocks/product-elements/button/style.scss index 197205468db..aead6e03a94 100644 --- a/assets/js/atomic/blocks/product/button/style.scss +++ b/assets/js/atomic/blocks/product-elements/button/style.scss @@ -1,4 +1,4 @@ -.wc-block-layout .wc-block-components-product-button { +.wp-block-button.wc-block-components-product-button { word-break: break-word; white-space: normal; margin-top: 0; @@ -19,7 +19,7 @@ } } -.wc-block-layout--is-loading .wc-block-components-product-button > .wc-block-components-product-button__button { +.is-loading .wc-block-components-product-button > .wc-block-components-product-button__button { @include placeholder(); min-width: 8em; min-height: 3em; diff --git a/assets/js/atomic/blocks/product-elements/category-list/attributes.js b/assets/js/atomic/blocks/product-elements/category-list/attributes.js new file mode 100644 index 00000000000..5bac8820c40 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/category-list/attributes.js @@ -0,0 +1,8 @@ +export const blockAttributes = { + productId: { + type: 'number', + default: 0, + }, +}; + +export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/category-list/block.js b/assets/js/atomic/blocks/product-elements/category-list/block.js similarity index 70% rename from assets/js/atomic/blocks/product/category-list/block.js rename to assets/js/atomic/blocks/product-elements/category-list/block.js index 7a4ce4c4a7e..0f8ef195d36 100644 --- a/assets/js/atomic/blocks/product/category-list/block.js +++ b/assets/js/atomic/blocks/product-elements/category-list/block.js @@ -9,6 +9,7 @@ import { useProductDataContext, } from '@woocommerce/shared-context'; import { isEmpty } from 'lodash'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; /** * Internal dependencies @@ -20,16 +21,13 @@ import './style.scss'; * * @param {Object} props Incoming props. * @param {string} [props.className] CSS Class name for the component. - * @param {Object} [props.product] Optional product object. Product from context will be used if - * this is not provided. * @return {*} The component. */ -const Block = ( { className, ...props } ) => { +const Block = ( { className } ) => { const { parentClassName } = useInnerBlockLayoutContext(); - const productDataContext = useProductDataContext(); - const { product } = productDataContext || props || {}; + const { product } = useProductDataContext(); - if ( isEmpty( product ) || isEmpty( product.categories ) ) { + if ( isEmpty( product.categories ) ) { return null; } @@ -38,7 +36,9 @@ const Block = ( { className, ...props } ) => { className={ classnames( className, 'wc-block-components-product-category-list', - `${ parentClassName }__product-category-list` + { + [ `${ parentClassName }__product-category-list` ]: parentClassName, + } ) } > { __( 'Categories:', 'woo-gutenberg-products-block' ) }{ ' ' } @@ -59,7 +59,6 @@ const Block = ( { className, ...props } ) => { Block.propTypes = { className: PropTypes.string, - product: PropTypes.object, }; -export default Block; +export default withProductDataContext( Block ); diff --git a/assets/js/atomic/blocks/product-elements/category-list/constants.js b/assets/js/atomic/blocks/product-elements/category-list/constants.js new file mode 100644 index 00000000000..18b53f405a2 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/category-list/constants.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { folder, Icon } from '@woocommerce/icons'; + +export const BLOCK_TITLE = __( + 'Product Category List', + 'woo-gutenberg-products-block' +); +export const BLOCK_ICON = ; +export const BLOCK_DESCRIPTION = __( + 'Display a list of categories belonging to a product.', + 'woo-gutenberg-products-block' +); diff --git a/assets/js/atomic/blocks/product-elements/category-list/edit.js b/assets/js/atomic/blocks/product-elements/category-list/edit.js new file mode 100644 index 00000000000..01fb2104a70 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/category-list/edit.js @@ -0,0 +1,33 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Disabled } from '@wordpress/components'; +import EditProductLink from '@woocommerce/block-components/edit-product-link'; + +/** + * Internal dependencies + */ +import Block from './block'; +import withProductSelector from '../shared/with-product-selector'; +import { BLOCK_TITLE, BLOCK_ICON } from './constants'; + +const Edit = ( { attributes } ) => { + return ( + <> + + + + + + ); +}; + +export default withProductSelector( { + icon: BLOCK_ICON, + label: BLOCK_TITLE, + description: __( + "Choose a product to display it's categories.", + 'woo-gutenberg-products-block' + ), +} )( Edit ); diff --git a/assets/js/atomic/blocks/product-elements/category-list/index.js b/assets/js/atomic/blocks/product-elements/category-list/index.js new file mode 100644 index 00000000000..34c818ff92d --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/category-list/index.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { registerExperimentalBlockType } from '@woocommerce/block-settings'; + +/** + * Internal dependencies + */ +import sharedConfig from '../shared/config'; +import attributes from './attributes'; +import edit from './edit'; +import { + BLOCK_TITLE as title, + BLOCK_ICON as icon, + BLOCK_DESCRIPTION as description, +} from './constants'; + +const blockConfig = { + title, + description, + icon: { + src: icon, + foreground: '#874FB9', + }, + attributes, + edit, +}; + +registerExperimentalBlockType( 'woocommerce/product-category-list', { + ...sharedConfig, + ...blockConfig, +} ); diff --git a/assets/js/atomic/blocks/product/tag-list/style.scss b/assets/js/atomic/blocks/product-elements/category-list/style.scss similarity index 80% rename from assets/js/atomic/blocks/product/tag-list/style.scss rename to assets/js/atomic/blocks/product-elements/category-list/style.scss index df535224e68..b3fa4fd4c10 100644 --- a/assets/js/atomic/blocks/product/tag-list/style.scss +++ b/assets/js/atomic/blocks/product-elements/category-list/style.scss @@ -1,4 +1,4 @@ -.wc-block-layout .wc-block-components-product-tag-list { +.wc-block-components-product-category-list { margin-top: 0; margin-bottom: em($gap-small); diff --git a/assets/js/atomic/blocks/product/image/attributes.js b/assets/js/atomic/blocks/product-elements/image/attributes.js similarity index 85% rename from assets/js/atomic/blocks/product/image/attributes.js rename to assets/js/atomic/blocks/product-elements/image/attributes.js index c1190c99448..bff0b5f4a79 100644 --- a/assets/js/atomic/blocks/product/image/attributes.js +++ b/assets/js/atomic/blocks/product-elements/image/attributes.js @@ -15,6 +15,10 @@ export const blockAttributes = { type: 'string', default: 'full-size', }, + productId: { + type: 'number', + default: 0, + }, }; export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/image/block.js b/assets/js/atomic/blocks/product-elements/image/block.js similarity index 82% rename from assets/js/atomic/blocks/product/image/block.js rename to assets/js/atomic/blocks/product-elements/image/block.js index 46fb1631e8a..c9a59e8bf7e 100644 --- a/assets/js/atomic/blocks/product/image/block.js +++ b/assets/js/atomic/blocks/product-elements/image/block.js @@ -9,6 +9,8 @@ import { useInnerBlockLayoutContext, useProductDataContext, } from '@woocommerce/shared-context'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; +import { isEmpty } from 'lodash'; /** * Internal dependencies @@ -21,11 +23,10 @@ import './style.scss'; * * @param {Object} props Incoming props. * @param {string} [props.className] CSS Class name for the component. + * @param {string} [props.imageSizing] Size of image to use. * @param {boolean} [props.productLink] Whether or not to display a link to the product page. * @param {boolean} [props.showSaleBadge] Whether or not to display the on sale badge. * @param {string} [props.saleBadgeAlign] How should the sale badge be aligned if displayed. - * @param {Object} [props.product] Optional product object. Product from context will be used if - * this is not provided. * @return {*} The component. */ const Block = ( { @@ -34,21 +35,21 @@ const Block = ( { productLink = true, showSaleBadge, saleBadgeAlign = 'right', - ...props } ) => { const { parentClassName } = useInnerBlockLayoutContext(); - const productDataContext = useProductDataContext(); - const product = props.product || productDataContext.product; + const { product } = useProductDataContext(); const [ imageLoaded, setImageLoaded ] = useState( false ); - if ( ! product ) { + if ( ! product.id ) { return (
@@ -56,15 +57,16 @@ const Block = ( { ); } - const image = - product?.images && product.images.length ? product.images[ 0 ] : null; + const image = ! isEmpty( product.images ) ? product.images[ 0 ] : null; return (
{ productLink ? ( @@ -103,7 +105,9 @@ const Block = ( { }; const ImagePlaceholder = () => { - return ; + return ( + + ); }; const Image = ( { image, onLoad, loaded, showFullSize } ) => { @@ -135,10 +139,9 @@ const Image = ( { image, onLoad, loaded, showFullSize } ) => { Block.propTypes = { className: PropTypes.string, - product: PropTypes.object, productLink: PropTypes.bool, showSaleBadge: PropTypes.bool, saleBadgeAlign: PropTypes.string, }; -export default Block; +export default withProductDataContext( Block ); diff --git a/assets/js/atomic/blocks/product-elements/image/constants.js b/assets/js/atomic/blocks/product-elements/image/constants.js new file mode 100644 index 00000000000..eeedac58c8a --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/image/constants.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { image, Icon } from '@woocommerce/icons'; + +export const BLOCK_TITLE = __( + 'Product Image', + 'woo-gutenberg-products-block' +); +export const BLOCK_ICON = ; +export const BLOCK_DESCRIPTION = __( + 'Display the main product image', + 'woo-gutenberg-products-block' +); diff --git a/assets/js/atomic/blocks/product/image/edit.js b/assets/js/atomic/blocks/product-elements/image/edit.js similarity index 90% rename from assets/js/atomic/blocks/product/image/edit.js rename to assets/js/atomic/blocks/product-elements/image/edit.js index 228aec31776..a0f62ec9165 100644 --- a/assets/js/atomic/blocks/product/image/edit.js +++ b/assets/js/atomic/blocks/product-elements/image/edit.js @@ -12,8 +12,10 @@ import { getAdminLink } from '@woocommerce/settings'; * Internal dependencies */ import Block from './block'; +import withProductSelector from '../shared/with-product-selector'; +import { BLOCK_TITLE, BLOCK_ICON } from './constants'; -export default ( { attributes, setAttributes } ) => { +const Edit = ( { attributes, setAttributes } ) => { const { productLink, imageSizing, @@ -146,3 +148,12 @@ export default ( { attributes, setAttributes } ) => { ); }; + +export default withProductSelector( { + icon: BLOCK_ICON, + label: BLOCK_TITLE, + description: __( + "Choose a product to display it's image.", + 'woo-gutenberg-products-block' + ), +} )( Edit ); diff --git a/assets/js/atomic/blocks/product/image/frontend.js b/assets/js/atomic/blocks/product-elements/image/frontend.js similarity index 100% rename from assets/js/atomic/blocks/product/image/frontend.js rename to assets/js/atomic/blocks/product-elements/image/frontend.js diff --git a/assets/js/atomic/blocks/product-elements/image/index.js b/assets/js/atomic/blocks/product-elements/image/index.js new file mode 100644 index 00000000000..07dd162514d --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/image/index.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import sharedConfig from '../shared/config'; +import attributes from './attributes'; +import edit from './edit'; +import { + BLOCK_TITLE as title, + BLOCK_ICON as icon, + BLOCK_DESCRIPTION as description, +} from './constants'; + +const blockConfig = { + title, + description, + icon: { + src: icon, + foreground: '#874FB9', + }, + attributes, + edit, +}; + +registerBlockType( 'woocommerce/product-image', { + ...sharedConfig, + ...blockConfig, +} ); diff --git a/assets/js/atomic/blocks/product/image/style.scss b/assets/js/atomic/blocks/product-elements/image/style.scss similarity index 75% rename from assets/js/atomic/blocks/product/image/style.scss rename to assets/js/atomic/blocks/product-elements/image/style.scss index f7401e8e6d8..bc85701726f 100644 --- a/assets/js/atomic/blocks/product/image/style.scss +++ b/assets/js/atomic/blocks/product-elements/image/style.scss @@ -1,5 +1,5 @@ -.editor-styles-wrapper .wc-block-layout .wc-block-grid__products .wc-block-grid__product .wc-block-components-product-image, -.wc-block-layout .wc-block-components-product-image { +.editor-styles-wrapper .wc-block-grid__products .wc-block-grid__product .wc-block-components-product-image, +.wc-block-components-product-image { margin-top: 0; margin-bottom: $gap-small; text-decoration: none; @@ -48,6 +48,6 @@ } } -.wc-block-layout--is-loading .wc-block-components-product-image { +.is-loading .wc-block-components-product-image { @include placeholder(); } diff --git a/assets/js/atomic/blocks/product-elements/price/attributes.js b/assets/js/atomic/blocks/product-elements/price/attributes.js new file mode 100644 index 00000000000..7ade4214318 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price/attributes.js @@ -0,0 +1,45 @@ +/** + * External dependencies + */ +import { isFeaturePluginBuild } from '@woocommerce/block-settings'; + +let blockAttributes = { + productId: { + type: 'number', + default: 0, + }, +}; + +if ( isFeaturePluginBuild() ) { + blockAttributes = { + ...blockAttributes, + align: { + type: 'string', + }, + fontSize: { + type: 'string', + }, + customFontSize: { + type: 'number', + }, + saleFontSize: { + type: 'string', + }, + customSaleFontSize: { + type: 'number', + }, + color: { + type: 'string', + }, + saleColor: { + type: 'string', + }, + customColor: { + type: 'string', + }, + customSaleColor: { + type: 'string', + }, + }; +} +export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/price/block.js b/assets/js/atomic/blocks/product-elements/price/block.js similarity index 89% rename from assets/js/atomic/blocks/product/price/block.js rename to assets/js/atomic/blocks/product-elements/price/block.js index 1c9b05fc579..dcb261e6e66 100644 --- a/assets/js/atomic/blocks/product/price/block.js +++ b/assets/js/atomic/blocks/product-elements/price/block.js @@ -11,6 +11,8 @@ import { } from '@woocommerce/shared-context'; import { getColorClassName, getFontSizeClass } from '@wordpress/block-editor'; import { isFeaturePluginBuild } from '@woocommerce/block-settings'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; + /** * Internal dependencies */ @@ -45,11 +47,9 @@ const Block = ( { customColor, saleColor, customSaleColor, - ...props } ) => { const { parentClassName } = useInnerBlockLayoutContext(); - const productDataContext = useProductDataContext(); - const product = props.product || productDataContext.product; + const { product } = useProductDataContext(); const colorClass = getColorClassName( 'color', color ); const fontSizeClass = getFontSizeClass( fontSize ); @@ -80,20 +80,22 @@ const Block = ( { fontSize: customSaleFontSize, }; - if ( ! product ) { + if ( ! product.id ) { return (
); } - const prices = product.prices || {}; + const prices = product.prices; const currency = getCurrencyFromPriceResponse( prices ); return ( @@ -102,8 +104,8 @@ const Block = ( { className, 'price', 'wc-block-components-product-price', - `${ parentClassName }__product-price`, { + [ `${ parentClassName }__product-price` ]: parentClassName, [ `wc-block-components-product-price__align-${ align }` ]: align && isFeaturePluginBuild(), } @@ -155,8 +157,10 @@ const PriceRange = ( { currency, minAmount, maxAmount, classes, style } ) => { @@ -188,8 +192,9 @@ const SalePrice = ( { @@ -201,8 +206,9 @@ const SalePrice = ( { @@ -245,4 +251,4 @@ Block.propTypes = { customSaleColor: PropTypes.string, }; -export default Block; +export default withProductDataContext( Block ); diff --git a/assets/js/atomic/blocks/product-elements/price/constants.js b/assets/js/atomic/blocks/product-elements/price/constants.js new file mode 100644 index 00000000000..bee87dc6221 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price/constants.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { bill, Icon } from '@woocommerce/icons'; + +export const BLOCK_TITLE = __( + 'Product Price', + 'woo-gutenberg-products-block' +); +export const BLOCK_ICON = ; +export const BLOCK_DESCRIPTION = __( + 'Display the price of a product.', + 'woo-gutenberg-products-block' +); diff --git a/assets/js/atomic/blocks/product/price/edit.js b/assets/js/atomic/blocks/product-elements/price/edit.js similarity index 89% rename from assets/js/atomic/blocks/product/price/edit.js rename to assets/js/atomic/blocks/product-elements/price/edit.js index fba9b11b446..58054ee4847 100644 --- a/assets/js/atomic/blocks/product/price/edit.js +++ b/assets/js/atomic/blocks/product-elements/price/edit.js @@ -18,6 +18,8 @@ import { isFeaturePluginBuild } from '@woocommerce/block-settings'; * Internal dependencies */ import Block from './block'; +import withProductSelector from '../shared/with-product-selector'; +import { BLOCK_TITLE, BLOCK_ICON } from './constants'; const TextControl = ( { fontSize, @@ -117,6 +119,14 @@ const Price = isFeaturePluginBuild() withColors( 'color', { textColor: 'color' } ), withColors( 'saleColor', { textColor: 'saleColor' } ), withColors( 'originalColor', { textColor: 'originalColor' } ), + withProductSelector( { + icon: BLOCK_ICON, + label: BLOCK_TITLE, + description: __( + "Choose a product to display it's price.", + 'woo-gutenberg-products-block' + ), + } ), ] )( PriceEdit ) : PriceEdit; diff --git a/assets/js/atomic/blocks/product-elements/price/index.js b/assets/js/atomic/blocks/product-elements/price/index.js new file mode 100644 index 00000000000..15115a01fb5 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price/index.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import sharedConfig from '../shared/config'; +import edit from './edit'; +import attributes from './attributes'; +import { + BLOCK_TITLE as title, + BLOCK_ICON as icon, + BLOCK_DESCRIPTION as description, +} from './constants'; + +const blockConfig = { + title, + description, + icon: { + src: icon, + foreground: '#874FB9', + }, + attributes, + edit, +}; + +registerBlockType( 'woocommerce/product-price', { + ...sharedConfig, + ...blockConfig, +} ); diff --git a/assets/js/atomic/blocks/product-elements/price/style.scss b/assets/js/atomic/blocks/product-elements/price/style.scss new file mode 100644 index 00000000000..c03543c9de8 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/price/style.scss @@ -0,0 +1,28 @@ +.wc-block-components-product-price { + margin-top: 0; + margin-bottom: $gap-small; + display: block; + + &__regular { + margin-right: 0.5em; + } +} +.is-loading { + .wc-block-components-product-price::before { + @include placeholder(); + content: "."; + display: inline-block; + width: 5em; + } + /*rtl:begin:ignore*/ + .wc-block-components-product-price__align-left { + text-align: left; + } + .wc-block-components-product-price__align-center { + text-align: center; + } + .wc-block-components-product-price__align-right { + text-align: right; + } + /*rtl:end:ignore*/ +} diff --git a/assets/js/atomic/blocks/product-elements/rating/attributes.js b/assets/js/atomic/blocks/product-elements/rating/attributes.js new file mode 100644 index 00000000000..5bac8820c40 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/rating/attributes.js @@ -0,0 +1,8 @@ +export const blockAttributes = { + productId: { + type: 'number', + default: 0, + }, +}; + +export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/rating/block.js b/assets/js/atomic/blocks/product-elements/rating/block.js similarity index 75% rename from assets/js/atomic/blocks/product/rating/block.js rename to assets/js/atomic/blocks/product-elements/rating/block.js index 56db48fc58f..e0e19433793 100644 --- a/assets/js/atomic/blocks/product/rating/block.js +++ b/assets/js/atomic/blocks/product-elements/rating/block.js @@ -8,6 +8,7 @@ import { useInnerBlockLayoutContext, useProductDataContext, } from '@woocommerce/shared-context'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; /** * Internal dependencies @@ -19,14 +20,11 @@ import './style.scss'; * * @param {Object} props Incoming props. * @param {string} [props.className] CSS Class name for the component. - * @param {Object} [props.product] Optional product object. Product from context will be used if - * this is not provided. * @return {*} The component. */ -const Block = ( { className, ...props } ) => { +const Block = ( { className } ) => { const { parentClassName } = useInnerBlockLayoutContext(); - const productDataContext = useProductDataContext(); - const product = props.product || productDataContext.product; + const { product } = useProductDataContext(); const rating = getAverageRating( product ); if ( ! rating ) { @@ -48,7 +46,9 @@ const Block = ( { className, ...props } ) => { className, 'star-rating', 'wc-block-components-product-rating', - `${ parentClassName }__product-rating` + { + [ `${ parentClassName }__product-rating` ]: parentClassName, + } ) } >
{ const getAverageRating = ( product ) => { // eslint-disable-next-line camelcase - const rating = parseFloat( product?.average_rating || 0 ); + const rating = parseFloat( product.average_rating ); return Number.isFinite( rating ) && rating > 0 ? rating : 0; }; Block.propTypes = { className: PropTypes.string, - product: PropTypes.object, }; -export default Block; +export default withProductDataContext( Block ); diff --git a/assets/js/atomic/blocks/product-elements/rating/constants.js b/assets/js/atomic/blocks/product-elements/rating/constants.js new file mode 100644 index 00000000000..4e20ec561af --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/rating/constants.js @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { star, Icon } from '@woocommerce/icons'; + +export const BLOCK_TITLE = __( + 'Product Rating', + 'woo-gutenberg-products-block' +); +export const BLOCK_ICON = ; +export const BLOCK_DESCRIPTION = __( + 'Display the average rating of a product.', + 'woo-gutenberg-products-block' +); diff --git a/assets/js/atomic/blocks/product-elements/rating/edit.js b/assets/js/atomic/blocks/product-elements/rating/edit.js new file mode 100644 index 00000000000..c37381a3186 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/rating/edit.js @@ -0,0 +1,23 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import Block from './block'; +import withProductSelector from '../shared/with-product-selector'; +import { BLOCK_TITLE, BLOCK_ICON } from './constants'; + +const Edit = ( { attributes } ) => { + return ; +}; +export default withProductSelector( { + icon: BLOCK_ICON, + label: BLOCK_TITLE, + description: __( + "Choose a product to display it's rating.", + 'woo-gutenberg-products-block' + ), +} )( Edit ); diff --git a/assets/js/atomic/blocks/product-elements/rating/index.js b/assets/js/atomic/blocks/product-elements/rating/index.js new file mode 100644 index 00000000000..ce926cb1421 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/rating/index.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import sharedConfig from '../shared/config'; +import attributes from './attributes'; +import edit from './edit'; +import { + BLOCK_TITLE as title, + BLOCK_ICON as icon, + BLOCK_DESCRIPTION as description, +} from './constants'; + +const blockConfig = { + title, + description, + icon: { + src: icon, + foreground: '#874FB9', + }, + attributes, + edit, +}; + +registerBlockType( 'woocommerce/product-rating', { + ...sharedConfig, + ...blockConfig, +} ); diff --git a/assets/js/atomic/blocks/product-elements/rating/style.scss b/assets/js/atomic/blocks/product-elements/rating/style.scss new file mode 100644 index 00000000000..816673c2716 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/rating/style.scss @@ -0,0 +1,52 @@ +.wc-block-components-product-rating { + display: block; + margin-top: 0; + margin-bottom: $gap-small; + + &__stars { + overflow: hidden; + position: relative; + width: 5.3em; + height: 1.618em; + line-height: 1.618; + font-size: 1em; + /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ + font-family: star; + font-weight: 400; + margin: 0 auto; + text-align: left; + + &::before { + content: "\53\53\53\53\53"; + top: 0; + left: 0; + right: 0; + position: absolute; + opacity: 0.5; + color: #aaa; + white-space: nowrap; + } + span { + overflow: hidden; + top: 0; + left: 0; + right: 0; + position: absolute; + padding-top: 1.5em; + } + span::before { + content: "\53\53\53\53\53"; + top: 0; + left: 0; + right: 0; + position: absolute; + color: #000; + white-space: nowrap; + } + } +} +.wc-block-single-product { + .wc-block-components-product-rating__stars { + margin: 0; + } +} diff --git a/assets/js/atomic/blocks/product-elements/sale-badge/attributes.js b/assets/js/atomic/blocks/product-elements/sale-badge/attributes.js new file mode 100644 index 00000000000..5bac8820c40 --- /dev/null +++ b/assets/js/atomic/blocks/product-elements/sale-badge/attributes.js @@ -0,0 +1,8 @@ +export const blockAttributes = { + productId: { + type: 'number', + default: 0, + }, +}; + +export default blockAttributes; diff --git a/assets/js/atomic/blocks/product/sale-badge/block.js b/assets/js/atomic/blocks/product-elements/sale-badge/block.js similarity index 72% rename from assets/js/atomic/blocks/product/sale-badge/block.js rename to assets/js/atomic/blocks/product-elements/sale-badge/block.js index b586bdff490..b12056d56d9 100644 --- a/assets/js/atomic/blocks/product/sale-badge/block.js +++ b/assets/js/atomic/blocks/product-elements/sale-badge/block.js @@ -9,6 +9,7 @@ import { useInnerBlockLayoutContext, useProductDataContext, } from '@woocommerce/shared-context'; +import { withProductDataContext } from '@woocommerce/shared-hocs'; /** * Internal dependencies @@ -21,16 +22,13 @@ import './style.scss'; * @param {Object} props Incoming props. * @param {string} [props.className] CSS Class name for the component. * @param {string} [props.align] Alignment of the badge. - * @param {Object} [props.product] Optional product object. Product from context will be used if - * this is not provided. * @return {*} The component. */ -const Block = ( { className, align, ...props } ) => { +const Block = ( { className, align } ) => { const { parentClassName } = useInnerBlockLayoutContext(); - const productDataContext = useProductDataContext(); - const product = props.product || productDataContext.product; + const { product } = useProductDataContext(); - if ( ! product || ! product.on_sale ) { + if ( ! product.id || ! product.on_sale ) { return null; } @@ -45,7 +43,9 @@ const Block = ( { className, align, ...props } ) => { 'wc-block-components-product-sale-badge', className, alignClass, - `${ parentClassName }__product-onsale` + { + [ `${ parentClassName }__product-onsale` ]: parentClassName, + } ) } >