Update `@woocommerce/extend-checkout-block` to include an example of a forced inner block (#33833)

* Update main integration file to register newsletter block scripts/styles

* Add files for example newsletter block

* Use only one internal dependencies comment

* Include newsletter block in index

* Move entry to correct position in webpack

* Rename functions to register scripts and styles

* Add changelog

* Remove block registration code

* Register slug as a block category to prevent warnings in console

* Add comment explaining the purpose of the function

* Bring templates up to date with latest changes to WC Blocks

The way the validation store selectors work was updated, so this template will use the new selectors.

* Ensure error message shows when box is not checked

* Ensure checkbox is targeted with CSS in editor
This commit is contained in:
Thomas Roberts 2022-10-27 09:28:44 +01:00 committed by GitHub
parent bfe0e958b8
commit c539e5614f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 343 additions and 12 deletions

View File

@ -19,9 +19,18 @@ class {{slugPascalCase}}_Blocks_Integration implements IntegrationInterface {
/**
* When called invokes any initialization/setup for the integration.
*
*/
public function initialize() {
$this->register_newsletter_block_frontend_scripts();
$this->register_newsletter_block_editor_scripts();
$this->register_newsletter_block_editor_styles();
$this->register_main_integration();
}
/**
* Registers the main JS file required to add filters and Slot/Fills.
*/
public function register_main_integration() {
$script_path = '/build/index.js';
$style_path = '/build/style-index.css';
@ -53,7 +62,6 @@ class {{slugPascalCase}}_Blocks_Integration implements IntegrationInterface {
wp_set_script_translations(
'{{slug}}-blocks-integration',
'{{slug}}',
'{{slug}}',
dirname( __FILE__ ) . '/languages'
);
}
@ -64,7 +72,7 @@ class {{slugPascalCase}}_Blocks_Integration implements IntegrationInterface {
* @return string[]
*/
public function get_script_handles() {
return array( '{{slug}}-blocks-integration' );
return array( '{{slug}}-blocks-integration', '{{slug}}-checkout-newsletter-subscription-block-frontend' );
}
/**
@ -73,7 +81,7 @@ class {{slugPascalCase}}_Blocks_Integration implements IntegrationInterface {
* @return string[]
*/
public function get_editor_script_handles() {
return array( '{{slug}}-blocks-integration' );
return array( '{{slug}}-blocks-integration', '{{slug}}-checkout-newsletter-subscription-block-editor' );
}
/**
@ -84,13 +92,77 @@ class {{slugPascalCase}}_Blocks_Integration implements IntegrationInterface {
public function get_script_data() {
$data = array(
'{{slug}}-active' => true,
'example-data' => 'This is some example data from the server',
'example-data' => __( 'This is some example data from the server', '{{slug}}' ),
'optInDefaultText' => __( 'I want to receive updates about products and promotions.', '{{ slug }}' ),
);
return $data;
}
public function register_newsletter_block_editor_styles() {
$style_path = '/build/style-{{slug}}-checkout-newsletter-subscription-block.css';
$style_url = plugins_url( $style_path, __FILE__ );
wp_enqueue_style(
'{{slug}}-blocks-integration',
$style_url,
[],
$this->get_file_version( $style_path )
);
}
public function register_newsletter_block_editor_scripts() {
$script_path = '/build/{{slug}}-checkout-newsletter-subscription-block.js';
$script_url = plugins_url( $script_path, __FILE__ );
$script_asset_path = dirname( __FILE__ ) . '/build/{{slug}}-checkout-newsletter-subscription-block.asset.php';
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array(),
'version' => $this->get_file_version( $script_asset_path ),
);
wp_register_script(
'{{slug}}-checkout-newsletter-subscription-block-editor',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'{{slug}}-newsletter-block-editor', // script handle
'{{slug}}', // text domain
dirname( __FILE__ ) . '/languages'
);
}
public function register_newsletter_block_frontend_scripts() {
$script_path = '/build/{{slug}}-checkout-newsletter-subscription-block-frontend.js';
$script_url = plugins_url( $script_path, __FILE__ );
$script_asset_path = dirname( __FILE__ ) . '/build/newsletter-block-frontend.asset.php';
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array(),
'version' => $this->get_file_version( $script_asset_path ),
);
wp_register_script(
'{{slug}}-checkout-newsletter-subscription-block-frontend',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'{{slug}}-checkout-newsletter-subscription-block-frontend', // script handle
'{{slug}}', // text domain
dirname( __FILE__ ) . '/languages'
);
}
/**
* Get the file modified time as a cache buster if we're in dev mode.
*
@ -103,4 +175,4 @@ class {{slugPascalCase}}_Blocks_Integration implements IntegrationInterface {
}
return {{slugPascalCase}}_VERSION;
}
}
}

View File

@ -33,3 +33,19 @@ add_action('woocommerce_blocks_loaded', function() {
}
);
});
/**
* Registers the slug as a block category with WordPress.
*/
function register_{{slugPascalCase}}_block_category( $categories ) {
return array_merge(
$categories,
[
[
'slug' => '{{slug}}',
'title' => __( '{{slugPascalCase}} Blocks', '{{slug}}' ),
],
]
);
}
add_action( 'block_categories_all', 'register_{{slugPascalCase}}_block_category', 10, 2 );

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Include an example of adding an inner block to the WooCommerce Blocks Checkout Block

View File

@ -1 +1,2 @@
import './js/index';
import './js/index';
import './js/checkout-newsletter-subscription-block';

View File

@ -0,0 +1,67 @@
/**
* External dependencies
*/
import { useEffect, useState } from '@wordpress/element';
import { CheckboxControl } from '@woocommerce/blocks-checkout';
import { getSetting } from '@woocommerce/settings';
import { useSelect, useDispatch } from '@wordpress/data';
const { optInDefaultText } = getSetting( '{{slug}}_data', '' );
const Block = ( { children, checkoutExtensionData } ) => {
const [ checked, setChecked ] = useState( false );
const { setExtensionData } = checkoutExtensionData;
const { setValidationErrors, clearValidationError } = useDispatch(
'wc/store/validation'
);
useEffect( () => {
setExtensionData( '{{slug}}', 'optin', checked );
if ( ! checked ) {
setValidationErrors( {
'{{slug}}': {
message: 'Please tick the box',
hidden: false,
},
} );
return;
}
clearValidationError( '{{slug}}' );
}, [
clearValidationError,
setValidationErrors,
checked,
setExtensionData,
] );
const { validationError } = useSelect( ( select ) => {
const store = select( 'wc/store/validation' );
return {
validationError: store.getValidationError( '{{slug}}' ),
};
} );
return (
<>
<CheckboxControl
id="subscribe-to-newsletter"
checked={ checked }
onChange={ setChecked }
>
{ children || optInDefaultText }
</CheckboxControl>
{ validationError?.hidden === false && (
<div>
<span role="img" aria-label="Warning emoji">
⚠️
</span>
{ validationError?.message }
</div>
) }
</>
);
};
export default Block;

View File

@ -0,0 +1,34 @@
{
"apiVersion": 2,
"name": "{{slug}}/checkout-newsletter-subscription",
"version": "2.0.0",
"title": "Newsletter Subscription!",
"category": "{{slug}}",
"description": "Adds a newsletter subscription checkbox to the checkout.",
"supports": {
"html": false,
"align": false,
"multiple": false,
"reusable": false
},
"parent": [
"woocommerce/checkout-contact-information-block"
],
"attributes": {
"lock": {
"type": "object",
"default": {
"remove": true,
"move": true
}
},
"text": {
"type": "string",
"source": "html",
"selector": ".wp-block-{{slug}}-checkout-newsletter-subscription",
"default": ""
}
},
"textdomain": "{{slug}}",
"editorStyle": "file:../../../build/style-{{slug}}-checkout-newsletter-subscription-block.css"
}

View File

@ -0,0 +1,49 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import {
useBlockProps,
RichText,
InspectorControls,
} from '@wordpress/block-editor';
import { PanelBody } from '@wordpress/components';
import { CheckboxControl } from '@woocommerce/blocks-checkout';
import { getSetting } from '@woocommerce/settings';
/**
* Internal dependencies
*/
import './style.scss';
const { optInDefaultText } = getSetting( '{{slug}}_data', '' );
export const Edit = ( { attributes, setAttributes } ) => {
const { text } = attributes;
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<InspectorControls>
<PanelBody title={ __( 'Block options', '{{slug}}' ) }>
Options for the block go here.
</PanelBody>
</InspectorControls>
<CheckboxControl
id="newsletter-text"
checked={ false }
disabled={ true }
/>
<RichText
value={ text || optInDefaultText }
onChange={ ( value ) => setAttributes( { text: value } ) }
/>
</div>
);
};
export const Save = ( { attributes } ) => {
const { text } = attributes;
return (
<div { ...useBlockProps.save() }>
<RichText.Content value={ text } />
</div>
);
};

View File

@ -0,0 +1,14 @@
/**
* External dependencies
*/
import { registerCheckoutBlock } from '@woocommerce/blocks-checkout';
/**
* Internal dependencies
*/
import Block from './block';
import metadata from './block.json';
registerCheckoutBlock( {
metadata,
component: Block,
} );

View File

@ -0,0 +1,33 @@
/**
* External dependencies
*/
import { SVG } from '@wordpress/components';
import { registerBlockType } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { Edit, Save } from './edit';
import metadata from './block.json';
registerBlockType( metadata, {
icon: {
src: (
<SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 16">
<g fill="none" fillRule="evenodd">
<path
stroke="currentColor"
strokeWidth="1.5"
d="M2 .75h16c.69 0 1.25.56 1.25 1.25v12c0 .69-.56 1.25-1.25 1.25H2c-.69 0-1.25-.56-1.25-1.25V2C.75 1.31 1.31.75 2 .75z"
/>
<path
fill="currentColor"
d="M7.667 7.667A2.34 2.34 0 0010 5.333 2.34 2.34 0 007.667 3a2.34 2.34 0 00-2.334 2.333 2.34 2.34 0 002.334 2.334zM11.556 3H17v3.889h-5.444V3zm2.722 2.916l1.944-1.36v-.779L14.278 5.14l-1.945-1.362v.778l1.945 1.361zm-5.834-.583a.78.78 0 00-.777-.777.78.78 0 00-.778.777c0 .428.35.778.778.778a.78.78 0 00.777-.778zm3.89 5.904c0-1.945-3.088-2.785-4.667-2.785-1.58 0-4.667.84-4.667 2.785v1.097h9.333v-1.097zM7.666 10c-1.012 0-2.163.389-2.738.778h5.475C9.821 10.38 8.678 10 7.667 10z"
/>
</g>
</SVG>
),
foreground: '#874FB9',
},
edit: Edit,
save: Save,
} );

View File

@ -0,0 +1,27 @@
.wp-block-{{slug}}-checkout-newsletter-subscription {
margin: 20px 0;
padding-top: 4px;
padding-bottom: 4px;
display: flex;
align-items: flex-start;
.block-editor-rich-text__editable {
vertical-align: middle;
line-height: 24px;
}
.wc-block-components-checkbox {
margin-right: 16px;
margin-top: 0;
}
}
.editor-styles-wrapper {
.wp-block-{{slug}}-checkout-newsletter-subscription {
.wc-block-components-checkbox {
margin-right: 0;
margin-top: 0;
}
}
}

View File

@ -9,14 +9,11 @@ import { getSetting } from '@woocommerce/settings';
*/
import './style.scss';
const exampleDataFromSettings = getSetting( '{{slug}}_data' );
/**
* Internal dependencies
*/
import { registerFilters } from './filters';
import { ExampleComponent } from './ExampleComponent';
const exampleDataFromSettings = getSetting( '{{slug}}_data' );
const render = () => {
return (
<>

View File

@ -10,6 +10,23 @@ const defaultRules = defaultConfig.module.rules.filter( ( rule ) => {
module.exports = {
...defaultConfig,
entry: {
index: path.resolve(process.cwd(), 'src', 'js', 'index.js'),
'{{slug}}-checkout-newsletter-subscription-block': path.resolve(
process.cwd(),
'src',
'js',
'checkout-newsletter-subscription-block',
'index.js'
),
'{{slug}}-checkout-newsletter-subscription-block-frontend': path.resolve(
process.cwd(),
'src',
'js',
'checkout-newsletter-subscription-block',
'frontend.js'
),
},
module: {
...defaultConfig.module,
rules: [