This repository has been archived by the owner on Feb 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 219
Block Refinement: Price Block [draft] #9398
Draft
nerrad
wants to merge
34
commits into
trunk
Choose a base branch
from
update/price-block-improvments
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
b0b059c
Rename block.
nerrad 75b60fd
Update block description.
nerrad ba2c832
Update Query Types
nerrad 40ac73d
Account for undefined in type definitions
nerrad 7681268
Implement new price block
nerrad a43d5aa
Change default template to use the core/group block with a row layout.
nerrad 0e7ab4e
Revert using core/group block as inner block for prices
nerrad 051e083
move Block defs to block.json.
nerrad b1ddfe6
remove unused file
nerrad 726567f
add support for superscript style on price values
nerrad ac25bb4
Add todo about the use of __experimentalDefaultControls
nerrad 6fcb2a3
A bunch of styles support
nerrad 13cdf51
add support for blockGap
nerrad 6411934
add discount block
nerrad ad28e2c
remove superfluous styles
nerrad fa42b3b
consider price ranges on current price
nerrad 8928045
Fix context usage
nerrad 3371590
fix missing usesContext values
nerrad 6411938
Implement discount as inner blocks
nerrad 7888559
switch to the stabilized “layout” property.
nerrad ba21592
Create server-side classes for current-price, discount-amount and ori…
tjcafferkey d2b1a3a
Merge branch 'trunk' into update/price-block-improvments
tjcafferkey 27f00c2
Add postId to context
albarin 15b594e
Fix discount class block name and add postId context
albarin 8baaec8
Fix woocommerce/isDescendentOfSingleProductTemplate context, show pre…
albarin 629a99f
Render inner block and fix class name
albarin fcf3267
Fix import an ancestor type
albarin 829eb35
Add color support for inner price blocks
albarin 20d7b5f
Refactor context and add color support for inner blocks
albarin 2e67964
Add support for typography and dimension styles
albarin e6454bb
Render price inner blocks inline in the editor
albarin beb62a2
Add original price styles
albarin d38704c
Fix css test
albarin 499f9d9
Merge branch 'trunk' into update/price-block-improvments
tjcafferkey File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
assets/js/atomic/blocks/product-elements/price-v2/block.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"$schema": "https://schemas.wp.org/trunk/block.json", | ||
"apiVersion": 2, | ||
"name": "woocommerce/product-price-v2", | ||
"title": "Price", | ||
"keywords": [ "WooCommerce" ], | ||
"category": "woocommerce-product-elements", | ||
"textdomain": "woo-gutenberg-products-block", | ||
"description": "Display the price of a product, including any discounts.", | ||
"supports": { | ||
"layout": { | ||
"allowSwitching": false, | ||
"allowInheriting": false, | ||
"default": { "type": "flex" } | ||
}, | ||
"html": false | ||
}, | ||
"usesContext": [ "queryId", "postId" ], | ||
"providesContext": { | ||
"woocommerce/isDescendentOfSingleProductTemplate": | ||
"isDescendentOfSingleProductTemplate", | ||
"woocommerce/isDescendentOfSingleProductBlock": | ||
"isDescendentOfSingleProductBlock", | ||
"woocommerce/withSuperScriptStyle": "withSuperScriptStyle" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not fully implemented yet, I added this as a context value so that it could be used to provide the ability for child blocks to keep their superscript style separate from the parent block. It's possible that isn't great UX in which case this property could potentially just be removed from block context. |
||
}, | ||
"attributes": { | ||
"isDescendentOfSingleProductTemplate": { | ||
"type": "boolean", | ||
"default": false | ||
}, | ||
"isDescendentOfSingleProductBlock": { | ||
"type": "boolean", | ||
"default": false | ||
}, | ||
"productId": { | ||
"type": "number", | ||
"default": 0 | ||
}, | ||
"withSuperScriptStyle": { | ||
"type": "boolean", | ||
"default": false | ||
} | ||
}, | ||
"styles": [ | ||
{ "name": "default", "label": "Default", "isDefault": true }, | ||
{ "name": "price-super", "label": "Superscript", "isDefault": false } | ||
Comment on lines
+45
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Block Styles are usually utilized explicitly for css styles, however given |
||
] | ||
} |
11 changes: 11 additions & 0 deletions
11
assets/js/atomic/blocks/product-elements/price-v2/constants.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { currencyDollar, Icon } from '@wordpress/icons'; | ||
|
||
export const BLOCK_ICON: JSX.Element = ( | ||
<Icon | ||
icon={ currencyDollar } | ||
className="wc-block-editor-components-block-icon" | ||
/> | ||
); |
181 changes: 181 additions & 0 deletions
181
assets/js/atomic/blocks/product-elements/price-v2/edit.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor'; | ||
import { useEffect, useMemo } from '@wordpress/element'; | ||
import { useSelect } from '@wordpress/data'; | ||
import { | ||
InnerBlockLayoutContextProvider, | ||
useInnerBlockLayoutContext, | ||
ProductDataContextProvider, | ||
} from '@woocommerce/shared-context'; | ||
import { useStoreProducts } from '@woocommerce/base-context/hooks'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { BLOCK_NAME as priceDiscountName } from './inner-blocks/discount'; | ||
import { BLOCK_NAME as originalPriceName } from './inner-blocks/original-price'; | ||
import { BLOCK_NAME as currentPriceName } from './inner-blocks/current-price'; | ||
import { TEMPLATE } from './template'; | ||
import './editor.scss'; | ||
|
||
interface Attributes { | ||
isDescendentOfSingleProductBlock: boolean; | ||
isDescendentOfSingleProductTemplate: boolean; | ||
withSuperScriptStyle: boolean; | ||
productId?: number; | ||
} | ||
|
||
interface Context { | ||
postId?: number; | ||
queryId?: number; | ||
} | ||
|
||
interface Props { | ||
context: Context; | ||
attributes: Attributes; | ||
setAttributes: ( attributes: Partial< Attributes > ) => void; | ||
} | ||
|
||
interface ContextProviderProps extends Props { | ||
children: JSX.Element | JSX.Element[] | undefined; | ||
} | ||
|
||
type ProductIdProps = Partial< ContextProviderProps > & { productId: number }; | ||
|
||
const deriveSuperScriptFromClass = ( className: string ): boolean => { | ||
if ( className ) { | ||
const classList = className.split( ' ' ); | ||
return classList.includes( 'is-style-price-super' ); | ||
} | ||
return false; | ||
}; | ||
|
||
const ProviderFromAPI = ( { | ||
productId, | ||
children, | ||
}: ProductIdProps ): JSX.Element => { | ||
// TODO: this would be good to derive from the WP entity store at some point. | ||
const { products, productsLoading } = useStoreProducts( { | ||
include: productId, | ||
} ); | ||
let product = null; | ||
if ( products.length > 0 ) { | ||
product = | ||
products.find( | ||
( productIteration ) => productIteration.id === productId | ||
) || null; | ||
} | ||
|
||
return ( | ||
<ProductDataContextProvider | ||
product={ product } | ||
isLoading={ productsLoading } | ||
> | ||
{ children } | ||
</ProductDataContextProvider> | ||
); | ||
}; | ||
|
||
const DerivedProductDataContextProvider = ( { | ||
context, | ||
attributes, | ||
setAttributes, | ||
children, | ||
}: ContextProviderProps & { withSuperScript: boolean } ): JSX.Element => { | ||
const { queryId, postId } = context; | ||
const { productId } = attributes; | ||
const isDescendentOfQueryLoop = Number.isFinite( queryId ); | ||
const id = isDescendentOfQueryLoop ? postId : productId; | ||
const isDescendentOfSingleProductTemplate = useSelect( | ||
( select ) => { | ||
const editSiteStore = select( 'core/edit-site' ); | ||
const editorPostId = editSiteStore?.getEditedPostId< | ||
string | undefined | ||
>(); | ||
|
||
return Boolean( | ||
editorPostId?.includes( '//single-product' ) && | ||
! isDescendentOfQueryLoop | ||
); | ||
}, | ||
[ isDescendentOfQueryLoop ] | ||
); | ||
|
||
useEffect( | ||
() => | ||
setAttributes( { | ||
isDescendentOfSingleProductTemplate, | ||
} ), | ||
[ isDescendentOfSingleProductTemplate, setAttributes ] | ||
); | ||
if ( id && id > 0 ) { | ||
return <ProviderFromAPI productId={ id }>{ children }</ProviderFromAPI>; | ||
} | ||
return ( | ||
<ProductDataContextProvider isLoading={ false }> | ||
{ children } | ||
</ProductDataContextProvider> | ||
); | ||
}; | ||
|
||
const EditBlock = ( { | ||
context, | ||
attributes, | ||
setAttributes, | ||
withSuperScript, | ||
}: Props & { withSuperScript: boolean } ): JSX.Element => { | ||
const { parentClassName } = useInnerBlockLayoutContext(); | ||
return ( | ||
<DerivedProductDataContextProvider | ||
context={ context } | ||
attributes={ attributes } | ||
setAttributes={ setAttributes } | ||
withSuperScript={ withSuperScript } | ||
> | ||
<div className={ parentClassName }> | ||
<InnerBlocks | ||
allowedBlocks={ [ | ||
originalPriceName, | ||
currentPriceName, | ||
priceDiscountName, | ||
] } | ||
// todo add template for initial price layout | ||
template={ TEMPLATE } | ||
/> | ||
</div> | ||
</DerivedProductDataContextProvider> | ||
); | ||
}; | ||
|
||
const Edit = ( { | ||
setAttributes, | ||
attributes, | ||
...props | ||
}: Props ): JSX.Element => { | ||
const blockProps = useBlockProps(); | ||
const withSuperScript = useMemo( | ||
() => deriveSuperScriptFromClass( blockProps.className ), | ||
[ blockProps.className ] | ||
); | ||
useEffect( () => { | ||
setAttributes( { withSuperScriptStyle: withSuperScript } ); | ||
}, [ withSuperScript, setAttributes ] ); | ||
return ( | ||
<div { ...blockProps }> | ||
<InnerBlockLayoutContextProvider | ||
parentName={ 'woocommerce/price-block' } | ||
parentClassName={ 'wc-block-price-element' } | ||
> | ||
<EditBlock | ||
{ ...props } | ||
attributes={ attributes } | ||
setAttributes={ setAttributes } | ||
/> | ||
</InnerBlockLayoutContextProvider> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Edit; |
12 changes: 12 additions & 0 deletions
12
assets/js/atomic/blocks/product-elements/price-v2/editor.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.wc-block-price-element { | ||
.block-editor-inner-blocks { | ||
.block-editor-block-list__layout { | ||
display: flex; | ||
|
||
.wp-block-woocommerce-original-price, | ||
.wp-block-woocommerce-current-price { | ||
margin-right: $gap-smaller; | ||
} | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
assets/js/atomic/blocks/product-elements/price-v2/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { registerBlockType } from '@wordpress/blocks'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import edit from './edit'; | ||
import save from './save'; | ||
import { supports } from './supports'; | ||
import metadata from './block.json'; | ||
import { BLOCK_ICON as icon } from './constants'; | ||
import './inner-blocks'; | ||
|
||
const blockConfig = { | ||
...metadata, | ||
icon: { src: icon }, | ||
supports: { ...supports, ...metadata.supports }, | ||
edit, | ||
save, | ||
}; | ||
|
||
registerBlockType( metadata.name, blockConfig ); |
19 changes: 19 additions & 0 deletions
19
assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/current-price/block.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "woocommerce/current-price", | ||
"version": "1.0.0", | ||
"icon": "info", | ||
"title": "Current Price", | ||
"description": "Display the current price for the product", | ||
"supports": { | ||
"color": { | ||
"background": true, | ||
"text": true | ||
} | ||
}, | ||
"category": "woocommerce", | ||
"keywords": [ "WooCommerce" ], | ||
"usesContext": ["woocommerce/withSuperScriptStyle", "woocommerce/isDescendentOfSingleProductTemplate", "postId"], | ||
"textdomain": "woo-gutenberg-products-block", | ||
"apiVersion": 2, | ||
"$schema": "https://schemas.wp.org/trunk/block.json" | ||
} |
62 changes: 62 additions & 0 deletions
62
assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/current-price/block.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import type { HTMLAttributes } from 'react'; | ||
import classnames from 'classnames'; | ||
import { useStyleProps } from '@woocommerce/base-hooks'; | ||
import { useInnerBlockLayoutContext } from '@woocommerce/shared-context'; | ||
import ProductPrice from '@woocommerce/base-components/product-price'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import type { PriceProps } from '../../types'; | ||
|
||
type Props = PriceProps & HTMLAttributes< HTMLDivElement >; | ||
|
||
const Block = ( { | ||
attributes, | ||
context, | ||
rawPrice, | ||
minPrice, | ||
maxPrice, | ||
currency, | ||
isDescendentOfSingleProductTemplate, | ||
}: Props ): JSX.Element | null => { | ||
const { className } = attributes; | ||
const { className: stylesClassName, style } = useStyleProps( attributes ); | ||
const { parentClassName } = useInnerBlockLayoutContext(); | ||
const wrapperClassName = classnames( | ||
className, | ||
{ | ||
[ `${ parentClassName }__product-price` ]: parentClassName, | ||
}, | ||
stylesClassName | ||
); | ||
if ( ! rawPrice && ! isDescendentOfSingleProductTemplate ) { | ||
return <ProductPrice className={ wrapperClassName } />; | ||
} | ||
|
||
const pricePreview = '3000'; | ||
const priceClassName = classnames( { | ||
[ `${ parentClassName }__product-current-price__value` ]: | ||
parentClassName, | ||
} ); | ||
|
||
return ( | ||
<ProductPrice | ||
className={ wrapperClassName } | ||
style={ style } | ||
priceClassName={ priceClassName } | ||
currency={ currency } | ||
withSuperScript={ context?.[ 'woocommerce/withSuperScriptStyle' ] } | ||
price={ | ||
isDescendentOfSingleProductTemplate ? pricePreview : rawPrice | ||
} | ||
minPrice={ minPrice } | ||
maxPrice={ maxPrice } | ||
/> | ||
); | ||
}; | ||
|
||
export default Block; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, the
layout
supports property only became recently available and will surface in WordPress 6.3. Prior to that it was__experimentalLayout
which is still supported. It may be better to ship with__experimentalLayout
if we want to support WP versions < 6.3 but even then testing should cover which versions of WP this will explicitly be supported by as that may influence what versions of WP this block is surfaced for.