Add/empty and fillted cart wrapper (https://github.com/woocommerce/woocommerce-blocks/pull/4803)
* Update area/types * Add empty and filled block wrappers * Add missing useBlockProps * Add templates and inner block structure
This commit is contained in:
parent
614c7205ef
commit
2af90f301c
|
@ -3,7 +3,8 @@
|
|||
*/
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
|
||||
const blockAttributes = {
|
||||
export const blockName = 'woocommerce/cart-i2';
|
||||
export const blockAttributes = {
|
||||
isPreview: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
|
@ -26,5 +27,3 @@ const blockAttributes = {
|
|||
default: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default blockAttributes;
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
import classnames from 'classnames';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { CartCheckoutFeedbackPrompt } from '@woocommerce/editor-components/feedback-prompt';
|
||||
import { InnerBlocks, InspectorControls } from '@wordpress/block-editor';
|
||||
import {
|
||||
InnerBlocks,
|
||||
useBlockProps,
|
||||
InspectorControls,
|
||||
} from '@wordpress/block-editor';
|
||||
import { PanelBody, ToggleControl, Notice } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CartCheckoutCompatibilityNotice } from '@woocommerce/editor-components/compatibility-notices';
|
||||
import ViewSwitcher from '@woocommerce/editor-components/view-switcher';
|
||||
import { CART_PAGE_ID } from '@woocommerce/block-settings';
|
||||
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
|
||||
import {
|
||||
|
@ -20,15 +22,30 @@ import {
|
|||
import { createInterpolateElement } from '@wordpress/element';
|
||||
import { getAdminLink, getSetting } from '@woocommerce/settings';
|
||||
import { previewCart } from '@woocommerce/resource-previews';
|
||||
import { SidebarLayout } from '@woocommerce/base-components/sidebar-layout';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import { Columns } from './columns';
|
||||
import { addClassToBody } from './hacks';
|
||||
import type { Attributes } from './types';
|
||||
|
||||
const BlockSettings = ( { attributes, setAttributes } ) => {
|
||||
// This is adds a class to body to signal if the selected block is locked
|
||||
addClassToBody();
|
||||
|
||||
// Array of allowed block names.
|
||||
const ALLOWED_BLOCKS: string[] = [
|
||||
'woocommerce/filled-cart-block',
|
||||
'woocommerce/empty-cart-block',
|
||||
];
|
||||
|
||||
const BlockSettings = ( {
|
||||
attributes,
|
||||
setAttributes,
|
||||
}: {
|
||||
attributes: Attributes;
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => undefined;
|
||||
} ): JSX.Element => {
|
||||
const { isShippingCalculatorEnabled, showRateAfterTaxName } = attributes;
|
||||
const { currentPostId } = useEditorContext();
|
||||
return (
|
||||
|
@ -113,42 +130,43 @@ const BlockSettings = ( { attributes, setAttributes } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
const ALLOWED_BLOCKS: string[] = [
|
||||
'woocommerce/cart-items-block',
|
||||
'woocommerce/cart-totals-block',
|
||||
];
|
||||
/**
|
||||
* Component to handle edit mode of "Cart Block".
|
||||
*
|
||||
* Note: We need to always render `<InnerBlocks>` in the editor. Otherwise,
|
||||
* if the user saves the page without having triggered the 'Empty Cart'
|
||||
* view, inner blocks would not be saved and they wouldn't be visible
|
||||
* in the frontend.
|
||||
*
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {string} props.className CSS class used.
|
||||
* @param {Object} props.attributes Attributes available.
|
||||
* @param {function(any):any} props.setAttributes Setter for attributes.
|
||||
*/
|
||||
const CartEditor = ( { className, attributes, setAttributes } ) => {
|
||||
const cartClassName = classnames( 'wc-block-cart', {
|
||||
export const Edit = ( {
|
||||
className,
|
||||
attributes,
|
||||
setAttributes,
|
||||
}: {
|
||||
className: string;
|
||||
attributes: Attributes;
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => undefined;
|
||||
} ): JSX.Element => {
|
||||
const cartClassName = classnames( {
|
||||
'has-dark-controls': attributes.hasDarkControls,
|
||||
} );
|
||||
const defaultInnerBlocksTemplate = [
|
||||
[
|
||||
'woocommerce/cart-items-block',
|
||||
{},
|
||||
[ [ 'woocommerce/cart-line-items-block', {}, [] ] ],
|
||||
],
|
||||
[
|
||||
'woocommerce/cart-totals-block',
|
||||
'woocommerce/filled-cart-block',
|
||||
{},
|
||||
[
|
||||
[ 'woocommerce/cart-order-summary-block', {}, [] ],
|
||||
[ 'woocommerce/cart-express-payment-block', {}, [] ],
|
||||
[ 'woocommerce/proceed-to-checkout-block', {}, [] ],
|
||||
[
|
||||
'woocommerce/cart-items-block',
|
||||
{},
|
||||
[ [ 'woocommerce/cart-line-items-block', {}, [] ] ],
|
||||
],
|
||||
[
|
||||
'woocommerce/cart-totals-block',
|
||||
{},
|
||||
[
|
||||
[ 'woocommerce/cart-order-summary-block', {}, [] ],
|
||||
[ 'woocommerce/cart-express-payment-block', {}, [] ],
|
||||
[ 'woocommerce/proceed-to-checkout-block', {}, [] ],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
[ 'woocommerce/empty-cart-block', {}, [] ],
|
||||
];
|
||||
return (
|
||||
<div
|
||||
|
@ -156,75 +174,50 @@ const CartEditor = ( { className, attributes, setAttributes } ) => {
|
|||
'is-editor-preview': attributes.isPreview,
|
||||
} ) }
|
||||
>
|
||||
<ViewSwitcher
|
||||
label={ __( 'Edit', 'woo-gutenberg-products-block' ) }
|
||||
views={ [
|
||||
{
|
||||
value: 'full',
|
||||
name: __( 'Full Cart', 'woo-gutenberg-products-block' ),
|
||||
},
|
||||
{
|
||||
value: 'empty',
|
||||
name: __(
|
||||
'Empty Cart',
|
||||
'woo-gutenberg-products-block'
|
||||
),
|
||||
},
|
||||
] }
|
||||
defaultView={ 'full' }
|
||||
render={ ( currentView ) => (
|
||||
<BlockErrorBoundary
|
||||
header={ __(
|
||||
'Cart Block Error',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
text={ __(
|
||||
'There was an error whilst rendering the cart block. If this problem continues, try re-creating the block.',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
showErrorMessage={ true }
|
||||
errorMessagePrefix={ __(
|
||||
'Error message:',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
>
|
||||
{ currentView === 'full' && (
|
||||
<>
|
||||
<EditorProvider previewData={ { previewCart } }>
|
||||
<BlockSettings
|
||||
attributes={ attributes }
|
||||
setAttributes={ setAttributes }
|
||||
/>
|
||||
<CartProvider>
|
||||
<Columns>
|
||||
<SidebarLayout
|
||||
className={ cartClassName }
|
||||
>
|
||||
<InnerBlocks
|
||||
allowedBlocks={
|
||||
ALLOWED_BLOCKS
|
||||
}
|
||||
template={
|
||||
defaultInnerBlocksTemplate
|
||||
}
|
||||
templateLock="insert"
|
||||
/>
|
||||
</SidebarLayout>
|
||||
</Columns>
|
||||
</CartProvider>
|
||||
</EditorProvider>
|
||||
</>
|
||||
) }
|
||||
</BlockErrorBoundary>
|
||||
<BlockErrorBoundary
|
||||
header={ __(
|
||||
'Cart Block Error',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
/>
|
||||
text={ __(
|
||||
'There was an error whilst rendering the cart block. If this problem continues, try re-creating the block.',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
showErrorMessage={ true }
|
||||
errorMessagePrefix={ __(
|
||||
'Error message:',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
>
|
||||
<EditorProvider previewData={ { previewCart } }>
|
||||
<BlockSettings
|
||||
attributes={ attributes }
|
||||
setAttributes={ setAttributes }
|
||||
/>
|
||||
<CartProvider>
|
||||
<div className={ cartClassName }>
|
||||
<InnerBlocks
|
||||
allowedBlocks={ ALLOWED_BLOCKS }
|
||||
template={ defaultInnerBlocksTemplate }
|
||||
templateLock="insert"
|
||||
/>
|
||||
</div>
|
||||
</CartProvider>
|
||||
</EditorProvider>
|
||||
</BlockErrorBoundary>
|
||||
<CartCheckoutCompatibilityNotice blockName="cart" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
CartEditor.propTypes = {
|
||||
className: PropTypes.string,
|
||||
export const Save = (): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
{ ...useBlockProps.save( {
|
||||
className: 'wc-block-cart is-loading',
|
||||
} ) }
|
||||
>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CartEditor;
|
||||
|
|
|
@ -2,39 +2,6 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-cart.is-editor-preview {
|
||||
max-height: 1000px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-cart-i2 {
|
||||
.wc-block-components-sidebar-layout {
|
||||
display: block;
|
||||
}
|
||||
.block-editor-block-list__layout {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-start;
|
||||
|
||||
.wc-block-cart__additional_fields {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.wc-block-components-main,
|
||||
.wc-block-components-sidebar,
|
||||
.block-editor-block-list__layout {
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
.wp-block-woocommerce-cart-totals-block,
|
||||
.wp-block-woocommerce-cart-items-block {
|
||||
.block-editor-block-list__layout {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.wc-lock-selected-block--move {
|
||||
.block-editor-block-mover__move-button-container,
|
||||
.block-editor-block-mover {
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block.js';
|
||||
import blockAttributes from './attributes';
|
||||
import { blockAttributes } from './attributes';
|
||||
|
||||
const reloadPage = () => void window.location.reload( true );
|
||||
/**
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { InnerBlocks } from '@wordpress/block-editor';
|
||||
import { Icon, cart } from '@woocommerce/icons';
|
||||
import classnames from 'classnames';
|
||||
import { registerFeaturePluginBlockType } from '@woocommerce/block-settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import edit from './edit';
|
||||
import { Edit, Save } from './edit';
|
||||
import './style.scss';
|
||||
import blockAttributes from './attributes';
|
||||
import { blockName, blockAttributes } from './attributes';
|
||||
import './inner-blocks';
|
||||
|
||||
/**
|
||||
* Register and run the Cart block.
|
||||
*/
|
||||
|
@ -36,16 +36,8 @@ const settings = {
|
|||
},
|
||||
},
|
||||
attributes: blockAttributes,
|
||||
edit,
|
||||
|
||||
// Save the props to post content.
|
||||
save( { attributes } ) {
|
||||
return (
|
||||
<div className={ classnames( 'is-loading', attributes.className ) }>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
edit: Edit,
|
||||
save: Save,
|
||||
};
|
||||
|
||||
registerFeaturePluginBlockType( 'woocommerce/cart-i2', settings );
|
||||
registerFeaturePluginBlockType( blockName, settings );
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"parent": [ "woocommerce/cart-i2" ],
|
||||
"parent": [ "woocommerce/filled-cart-block" ],
|
||||
"textdomain": "woo-gutenberg-products-block",
|
||||
"apiVersion": 2
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"parent": [ "woocommerce/cart-i2" ],
|
||||
"parent": [ "woocommerce/filled-cart-block" ],
|
||||
"textdomain": "woo-gutenberg-products-block",
|
||||
"apiVersion": 2
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "woocommerce/empty-cart-block",
|
||||
"version": "1.0.0",
|
||||
"title": "Empty Cart",
|
||||
"description": "Contains blocks that are displayed when the cart is empty.",
|
||||
"category": "woocommerce",
|
||||
"supports": {
|
||||
"align": false,
|
||||
"html": false,
|
||||
"multiple": false,
|
||||
"reusable": false,
|
||||
"inserter": false
|
||||
},
|
||||
"attributes": {
|
||||
"lock": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"remove": true,
|
||||
"move": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"parent": [ "woocommerce/cart-i2" ],
|
||||
"textdomain": "woo-gutenberg-products-block",
|
||||
"apiVersion": 2
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
|
||||
import { innerBlockAreas } from '@woocommerce/blocks-checkout';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useForcedLayout } from '../../use-forced-layout';
|
||||
import { getAllowedBlocks } from '../../editor-utils';
|
||||
|
||||
export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
const allowedBlocks = getAllowedBlocks( innerBlockAreas.EMPTY_CART );
|
||||
|
||||
useForcedLayout( {
|
||||
clientId,
|
||||
template: allowedBlocks,
|
||||
} );
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
This is the empty cart block.
|
||||
<InnerBlocks
|
||||
allowedBlocks={ allowedBlocks }
|
||||
templateLock={ false }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Save = (): JSX.Element => {
|
||||
return (
|
||||
<div { ...useBlockProps.save() }>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Icon, removeCart } from '@woocommerce/icons';
|
||||
import { registerFeaturePluginBlockType } from '@woocommerce/block-settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Edit, Save } from './edit';
|
||||
import metadata from './block.json';
|
||||
|
||||
registerFeaturePluginBlockType( metadata, {
|
||||
icon: {
|
||||
src: <Icon srcElement={ removeCart } />,
|
||||
foreground: '#874FB9',
|
||||
},
|
||||
edit: Edit,
|
||||
save: Save,
|
||||
} );
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "woocommerce/filled-cart-block",
|
||||
"version": "1.0.0",
|
||||
"title": "Filled Cart",
|
||||
"description": "Contains blocks that are displayed when the cart contains products.",
|
||||
"category": "woocommerce",
|
||||
"supports": {
|
||||
"align": false,
|
||||
"html": false,
|
||||
"multiple": false,
|
||||
"reusable": false,
|
||||
"inserter": false
|
||||
},
|
||||
"attributes": {
|
||||
"lock": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"remove": true,
|
||||
"move": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"parent": [ "woocommerce/cart-i2" ],
|
||||
"textdomain": "woo-gutenberg-products-block",
|
||||
"apiVersion": 2
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
|
||||
import { innerBlockAreas } from '@woocommerce/blocks-checkout';
|
||||
import { SidebarLayout } from '@woocommerce/base-components/sidebar-layout';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useForcedLayout } from '../../use-forced-layout';
|
||||
import { getAllowedBlocks } from '../../editor-utils';
|
||||
import { Columns } from './../../columns';
|
||||
import './editor.scss';
|
||||
|
||||
export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
const allowedBlocks = getAllowedBlocks( innerBlockAreas.FILLED_CART );
|
||||
|
||||
useForcedLayout( {
|
||||
clientId,
|
||||
template: allowedBlocks,
|
||||
} );
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<Columns>
|
||||
<SidebarLayout className={ 'wc-block-cart' }>
|
||||
<InnerBlocks
|
||||
allowedBlocks={ allowedBlocks }
|
||||
templateLock={ false }
|
||||
/>
|
||||
</SidebarLayout>
|
||||
</Columns>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Save = (): JSX.Element => {
|
||||
return (
|
||||
<div { ...useBlockProps.save() }>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
.wp-block-woocommerce-filled-cart-block {
|
||||
.wc-block-components-sidebar-layout {
|
||||
display: block;
|
||||
}
|
||||
.block-editor-block-list__layout {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.wc-block-components-main,
|
||||
.wc-block-components-sidebar,
|
||||
.block-editor-block-list__layout {
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
.wp-block-woocommerce-cart-totals-block,
|
||||
.wp-block-woocommerce-cart-items-block {
|
||||
.block-editor-block-list__layout {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Icon, cart } from '@woocommerce/icons';
|
||||
import { registerFeaturePluginBlockType } from '@woocommerce/block-settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Edit, Save } from './edit';
|
||||
import metadata from './block.json';
|
||||
|
||||
registerFeaturePluginBlockType( metadata, {
|
||||
icon: {
|
||||
src: <Icon srcElement={ cart } />,
|
||||
foreground: '#874FB9',
|
||||
},
|
||||
edit: Edit,
|
||||
save: Save,
|
||||
} );
|
|
@ -1,9 +1,11 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './filled-cart-block';
|
||||
import './cart-items-block';
|
||||
import './cart-totals-block';
|
||||
import './cart-line-items-block';
|
||||
import './cart-totals-block';
|
||||
import './cart-order-summary-block';
|
||||
import './cart-express-payment-block';
|
||||
import './proceed-to-checkout-block';
|
||||
import './empty-cart-block';
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
export type InnerBlockTemplate = [
|
||||
string,
|
||||
Record< string, unknown >,
|
||||
InnerBlockTemplate[] | undefined
|
||||
];
|
||||
|
||||
export interface Attributes {
|
||||
isPreview: boolean;
|
||||
isShippingCalculatorEnabled: boolean;
|
||||
hasDarkControls: boolean;
|
||||
showRateAfterTaxName: boolean;
|
||||
checkoutPageId: number;
|
||||
}
|
|
@ -13,7 +13,8 @@ export enum innerBlockAreas {
|
|||
BILLING_ADDRESS = 'woocommerce/checkout-billing-address-block',
|
||||
SHIPPING_METHODS = 'woocommerce/checkout-shipping-methods-block',
|
||||
PAYMENT_METHODS = 'woocommerce/checkout-payment-methods-block',
|
||||
CART = 'woocommerce/cart-i2',
|
||||
EMPTY_CART = 'woocommerce/empty-cart-block',
|
||||
FILLED_CART = 'woocommerce/filled-cart-block',
|
||||
CART_ITEMS = 'woocommerce/cart-items-block',
|
||||
CART_TOTALS = 'woocommerce/cart-totals-block',
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue