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

Commit afc750d

Browse files
authored
Update checkout block registration API to consume Block Metadata (#4684)
* Update registry to register components with block JSON metadata * Use updated registration API in sample block * remove editorScript * Rename area and allow forced blocks to do it's thing without defining a template manually * More naming consistency * Validate a registered checkout block has at least one valid parent
1 parent 0509a6c commit afc750d

File tree

23 files changed

+295
-333
lines changed

23 files changed

+295
-333
lines changed

assets/js/atomic/utils/render-parent-block.tsx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
import parse from 'html-react-parser';
1212
import {
1313
getRegisteredBlocks,
14-
isInnerBlockArea,
14+
hasInnerBlocks,
1515
} from '@woocommerce/blocks-checkout';
1616

1717
/**
@@ -32,11 +32,11 @@ import {
3232
* Gets a component from the block map for a given block name, or returns null if a component is not registered.
3333
*/
3434
const getBlockComponentFromMap = (
35-
blockName: string,
35+
block: string,
3636
blockMap: Record< string, React.ReactNode >
3737
): React.ElementType | null => {
38-
return blockName && blockMap[ blockName ]
39-
? ( blockMap[ blockName ] as React.ElementType )
38+
return block && blockMap[ block ]
39+
? ( blockMap[ block ] as React.ElementType )
4040
: null;
4141
};
4242

@@ -50,12 +50,12 @@ const getBlockComponentFromMap = (
5050
* @see registerCheckoutBlock
5151
*/
5252
const renderForcedBlocks = (
53-
blockName: string,
53+
block: string,
5454
blockMap: Record< string, React.ReactNode >,
5555
// Current children from the parent (siblings of the forced block)
5656
blockChildren: HTMLCollection | null
5757
) => {
58-
if ( ! isInnerBlockArea( blockName ) ) {
58+
if ( ! hasInnerBlocks( block ) ) {
5959
return null;
6060
}
6161

@@ -69,16 +69,16 @@ const renderForcedBlocks = (
6969
.filter( Boolean ) as string[] )
7070
: [];
7171

72-
const forcedBlocks = getRegisteredBlocks( blockName ).filter(
73-
( { block, force } ) =>
74-
force === true && ! currentBlocks.includes( block )
72+
const forcedBlocks = getRegisteredBlocks( block ).filter(
73+
( { blockName, force } ) =>
74+
force === true && ! currentBlocks.includes( blockName )
7575
);
7676

7777
return forcedBlocks.map(
78-
( { block, component }, index: number ): JSX.Element | null => {
78+
( { blockName, component }, index: number ): JSX.Element | null => {
7979
const ForcedComponent = component
8080
? component
81-
: getBlockComponentFromMap( block, blockMap );
81+
: getBlockComponentFromMap( blockName, blockMap );
8282
return ForcedComponent ? (
8383
<ForcedComponent key={ `${ blockName }_forced_${ index }` } />
8484
) : null;
@@ -91,7 +91,7 @@ const renderForcedBlocks = (
9191
*/
9292
const renderInnerBlocks = ( {
9393
// This is the parent block we're working within (see renderParentBlock)
94-
blockName: parentBlockName,
94+
block,
9595
// This is the map of blockNames->components
9696
blockMap,
9797
// Component which inner blocks are wrapped with.
@@ -101,8 +101,8 @@ const renderInnerBlocks = ( {
101101
// Current depth of the children. Used to ensure keys are unique.
102102
depth = 1,
103103
}: {
104-
// Parent Block Name. Used for inner block component mapping.
105-
blockName: string;
104+
// Block (parent) being rendered. Used for inner block component mapping.
105+
block: string;
106106
// Map of block names to block components for children.
107107
blockMap: Record< string, React.ReactNode >;
108108
// Wrapper for inner components.
@@ -121,7 +121,7 @@ const renderInnerBlocks = ( {
121121
* convert the HTMLElement to a React component.
122122
*/
123123
const { blockName = '', ...componentProps } = {
124-
key: `${ parentBlockName }_${ depth }_${ index }`,
124+
key: `${ block }_${ depth }_${ index }`,
125125
...( element instanceof HTMLElement ? element.dataset : {} ),
126126
};
127127

@@ -141,9 +141,9 @@ const renderInnerBlocks = ( {
141141
const elementChildren =
142142
element.children && element.children.length
143143
? renderInnerBlocks( {
144-
children: element.children,
145-
blockName: parentBlockName,
144+
block,
146145
blockMap,
146+
children: element.children,
147147
depth: depth + 1,
148148
blockWrapper,
149149
} )
@@ -166,7 +166,7 @@ const renderInnerBlocks = ( {
166166

167167
return (
168168
<Suspense
169-
key={ `${ parentBlockName }_${ depth }_${ index }_suspense` }
169+
key={ `${ block }_${ depth }_${ index }_suspense` }
170170
fallback={ <div className="wc-block-placeholder" /> }
171171
>
172172
<InnerBlockComponentWrapper>
@@ -178,9 +178,9 @@ const renderInnerBlocks = ( {
178178
* children from this element.
179179
*/
180180
renderInnerBlocks( {
181-
children: element.children,
182-
blockName: parentBlockName,
181+
block,
183182
blockMap,
183+
children: element.children,
184184
depth: depth + 1,
185185
blockWrapper,
186186
} )
@@ -246,7 +246,7 @@ export const renderParentBlock = ( {
246246
const children =
247247
element.children && element.children.length
248248
? renderInnerBlocks( {
249-
blockName,
249+
block: blockName,
250250
blockMap,
251251
children: element.children,
252252
blockWrapper,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { getBlockTypes } from '@wordpress/blocks';
5+
6+
// List of core block types to allow in inner block areas.
7+
const coreBlockTypes = [ 'core/paragraph', 'core/image', 'core/separator' ];
8+
9+
/**
10+
* Gets a list of allowed blocks types under a specific parent block type.
11+
*/
12+
export const getAllowedBlocks = ( block: string ): string[] => [
13+
...getBlockTypes()
14+
.filter( ( blockType ) =>
15+
( blockType?.parent || [] ).includes( block )
16+
)
17+
.map( ( { name } ) => name ),
18+
...coreBlockTypes,
19+
];

assets/js/blocks/cart-checkout/checkout-i2/form-step/additional-fields.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,31 @@
22
* External dependencies
33
*/
44
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
5-
import {
6-
RegisteredBlocks,
7-
getRegisteredBlockTemplate,
8-
} from '@woocommerce/blocks-checkout';
95

106
/**
117
* Internal dependencies
128
*/
139
import './editor.scss';
1410
import { useForcedLayout } from '../use-forced-layout';
11+
import { getAllowedBlocks } from '../editor-utils';
1512

1613
export const AdditionalFields = ( {
17-
area,
14+
block,
1815
}: {
19-
area: keyof RegisteredBlocks;
16+
// Name of the parent block.
17+
block: string;
2018
} ): JSX.Element => {
21-
const registeredBlocks = getRegisteredBlockTemplate( area );
2219
const { 'data-block': clientId } = useBlockProps();
23-
const template = useForcedLayout( {
20+
const allowedBlocks = getAllowedBlocks( block );
21+
22+
useForcedLayout( {
2423
clientId,
25-
template: registeredBlocks,
24+
template: allowedBlocks,
2625
} );
26+
2727
return (
2828
<div className="wc-block-checkout__additional_fields">
29-
<InnerBlocks allowedBlocks={ template } />
29+
<InnerBlocks allowedBlocks={ allowedBlocks } />
3030
</div>
3131
);
3232
};

assets/js/blocks/cart-checkout/checkout-i2/inner-blocks/checkout-billing-address-block/edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const Edit = ( {
6060
showPhoneField={ showPhoneField }
6161
requirePhoneField={ requirePhoneField }
6262
/>
63-
<AdditionalFields area={ innerBlockAreas.BILLING_ADDRESS } />
63+
<AdditionalFields block={ innerBlockAreas.BILLING_ADDRESS } />
6464
</FormStepBlock>
6565
);
6666
};

assets/js/blocks/cart-checkout/checkout-i2/inner-blocks/checkout-contact-information-block/edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const Edit = ( {
4141
<Disabled>
4242
<Block allowCreateAccount={ allowCreateAccount } />
4343
</Disabled>
44-
<AdditionalFields area={ innerBlockAreas.CONTACT_INFORMATION } />
44+
<AdditionalFields block={ innerBlockAreas.CONTACT_INFORMATION } />
4545
</FormStepBlock>
4646
);
4747
};

assets/js/blocks/cart-checkout/checkout-i2/inner-blocks/checkout-fields-block/edit.tsx

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,34 @@
33
*/
44
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
55
import { Main } from '@woocommerce/base-components/sidebar-layout';
6-
import {
7-
getRegisteredBlockTemplate,
8-
innerBlockAreas,
9-
} from '@woocommerce/blocks-checkout';
6+
import { innerBlockAreas } from '@woocommerce/blocks-checkout';
7+
108
/**
119
* Internal dependencies
1210
*/
1311
import { useCheckoutBlockControlsContext } from '../../context';
1412
import { useForcedLayout } from '../../use-forced-layout';
15-
16-
const ALLOWED_BLOCKS = [
17-
'woocommerce/checkout-express-payment-block',
18-
'woocommerce/checkout-shipping-address-block',
19-
'woocommerce/checkout-shipping-methods-block',
20-
'woocommerce/checkout-contact-information-block',
21-
'woocommerce/checkout-billing-address-block',
22-
'woocommerce/checkout-payment-block',
23-
'woocommerce/checkout-order-note-block',
24-
'woocommerce/checkout-actions-block',
25-
'woocommerce/checkout-terms-block',
26-
'core/paragraph',
27-
'core/heading',
28-
'core/separator',
29-
];
13+
import { getAllowedBlocks } from '../../editor-utils';
3014

3115
export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
3216
const blockProps = useBlockProps();
17+
const allowedBlocks = getAllowedBlocks( innerBlockAreas.CHECKOUT_FIELDS );
3318

3419
const {
3520
addressFieldControls: Controls,
3621
} = useCheckoutBlockControlsContext();
37-
const registeredBlocks = getRegisteredBlockTemplate(
38-
innerBlockAreas.CHECKOUT_FIELDS
39-
);
40-
const template = useForcedLayout( {
22+
23+
useForcedLayout( {
4124
clientId,
42-
template: [ ...ALLOWED_BLOCKS, ...registeredBlocks ],
25+
template: allowedBlocks,
4326
} );
4427
return (
4528
<Main className="wc-block-checkout__main">
4629
<div { ...blockProps }>
4730
<Controls />
4831
<form className="wc-block-components-form wc-block-checkout__form">
4932
<InnerBlocks
50-
allowedBlocks={ template }
33+
allowedBlocks={ allowedBlocks }
5134
templateLock={ false }
5235
renderAppender={ InnerBlocks.ButtonBlockAppender }
5336
/>

assets/js/blocks/cart-checkout/checkout-i2/inner-blocks/checkout-payment-block/edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const Edit = ( props: FormStepBlockProps ): JSX.Element => {
7373
<Disabled>
7474
<Block />
7575
</Disabled>
76-
<AdditionalFields area={ innerBlockAreas.PAYMENT_METHODS } />
76+
<AdditionalFields block={ innerBlockAreas.PAYMENT_METHODS } />
7777
</FormStepBlock>
7878
);
7979
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "woocommerce/checkout-sample-block",
3+
"version": "1.0.0",
4+
"title": "Checkout Sample Block",
5+
"category": "woocommerce",
6+
"description": "An example block showing how to integrate with Checkout i2.",
7+
"supports": {
8+
"html": false,
9+
"align": true,
10+
"multiple": true,
11+
"reusable": false
12+
},
13+
"attributes": {
14+
"lock": {
15+
"type": "object",
16+
"default": {
17+
"remove": true
18+
}
19+
}
20+
},
21+
"parent": [
22+
"woocommerce/checkout-shipping-address-block",
23+
"woocommerce/checkout-billing-address-block",
24+
"woocommerce/checkout-fields-block",
25+
"woocommerce/checkout-totals-block"
26+
],
27+
"textdomain": "woo-gutenberg-products-block"
28+
}
Lines changed: 8 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,20 @@
11
/**
22
* External dependencies
33
*/
4-
import { __ } from '@wordpress/i18n';
54
import { Icon, asterisk } from '@woocommerce/icons';
6-
import {
7-
registerCheckoutBlock,
8-
innerBlockAreas,
9-
} from '@woocommerce/blocks-checkout';
10-
import { lazy } from '@wordpress/element';
11-
import { WC_BLOCKS_BUILD_URL } from '@woocommerce/block-settings';
12-
13-
// Modify webpack publicPath at runtime based on location of WordPress Plugin.
14-
// eslint-disable-next-line no-undef,camelcase
15-
__webpack_public_path__ = WC_BLOCKS_BUILD_URL;
5+
import { registerExperimentalBlockType } from '@woocommerce/block-settings';
166

177
/**
188
* Internal dependencies
199
*/
2010
import { Edit, Save } from './edit';
11+
import metadata from './block.json';
2112

22-
registerCheckoutBlock( 'woocommerce/checkout-sample-block', {
23-
component: lazy( () =>
24-
import( /* webpackChunkName: "checkout-blocks/sample" */ './frontend' )
25-
),
26-
areas: [
27-
innerBlockAreas.SHIPPING_ADDRESS,
28-
innerBlockAreas.BILLING_ADDRESS,
29-
innerBlockAreas.CONTACT_INFORMATION,
30-
innerBlockAreas.CHECKOUT_FIELDS,
31-
innerBlockAreas.CHECKOUT_TOTALS,
32-
],
33-
force: true,
34-
configuration: {
35-
title: __( 'Sample Block', 'woo-gutenberg-products-block' ),
36-
category: 'woocommerce',
37-
description: __(
38-
'A sample block showing how to integrate with Checkout i2.',
39-
'woo-gutenberg-products-block'
40-
),
41-
icon: {
42-
src: <Icon srcElement={ asterisk } />,
43-
foreground: '#874FB9',
44-
},
45-
supports: {
46-
align: false,
47-
html: false,
48-
multiple: true,
49-
reusable: false,
50-
},
51-
attributes: {},
52-
edit: Edit,
53-
save: Save,
13+
registerExperimentalBlockType( metadata, {
14+
icon: {
15+
src: <Icon srcElement={ asterisk } />,
16+
foreground: '#874FB9',
5417
},
18+
edit: Edit,
19+
save: Save,
5520
} );

assets/js/blocks/cart-checkout/checkout-i2/inner-blocks/checkout-shipping-address-block/edit.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const Edit = ( {
5353
showPhoneField={ showPhoneField }
5454
requirePhoneField={ requirePhoneField }
5555
/>
56-
<AdditionalFields area={ innerBlockAreas.SHIPPING_ADDRESS } />
56+
<AdditionalFields block={ innerBlockAreas.SHIPPING_ADDRESS } />
5757
</FormStepBlock>
5858
);
5959
};

0 commit comments

Comments
 (0)