Skip to content

Instantly share code, notes, and snippets.

@ajvillegas
Last active October 19, 2023 11:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajvillegas/ade96761ee50a09defd02883cd3f36b6 to your computer and use it in GitHub Desktop.
Save ajvillegas/ade96761ee50a09defd02883cd3f36b6 to your computer and use it in GitHub Desktop.
Sample custom WordPress editor block and sidebar controls using using ES5 JavaScript syntax.
/**
* Custom WordPress block boilerplate.
*
* @package My_Block_Package
* @author Alexis J. Villegas
* @link http://www.alexisvillegas.com
* @license GPL-2.0+
*/
( function( blocks, editor, element ) {
const __ = wp.i18n.__; // The __() for internationalization.
const el = element.createElement; // The wp.element.createElement() function to create elements.
const registerBlockType = blocks.registerBlockType; // The registerBlockType() to register blocks.
const { InnerBlocks } = editor;
const template = [
[ 'core/heading', { content: 'Title' } ],
[ 'core/paragraph', { content: 'Description...' } ]
]; // The block template to use with InnerBlocks, can add/remove/edit initial parameters.
registerBlockType( 'my-block/cta-section', { // Block name; must be a string that contains a namespace prefix followed by a forward slash.
title: __( 'My Block Title', 'my-text-domain' ),
description: __( 'My custom block description.', 'my-text-domain' ),
icon: 'smiley', // Can use Dashicons or custom SVG elements (https://developer.wordpress.org/resource/dashicons/)
category: 'common', // Group blocks together based on common traits, can be 'common', 'formatting', 'layout', 'widgets' or 'embed'.
supports: {
align: true,
align: [ 'wide', 'full' ]
},
keywords: [ 'Custom Block', 'CTA', 'Call to Action' ], // Keywords for custom block, limited to three.
attributes: { // Placeholders to store custom block setting values.
backgroundColor: {
type: 'string',
default: '#34b79d'
}
},
example: { // Structured data used to construct a block preview shown in the Block Inspector panel when inserting blocks.
attributes: {
backgroundColor: '#34b79d'
},
innerBlocks: [
{
name: 'core/heading',
attributes: {
content: __( 'Title', 'my-text-domain' )
}
},
{
name: 'core/paragraph',
attributes: {
content: __( 'Description...', 'my-text-domain' )
}
}
]
},
edit: function( props ) {
return [
el( 'div',
{
key: 'block-section', // React requires each top-level item in the returned array to have a unique key.
className: props.className, // className property is automatically enabled for each block.
style: {
backgroundColor: props.attributes.backgroundColor
}
},
el( 'div',
{
className: 'block-wrap'
},
el( InnerBlocks,
{
template: template,
templateLock: false // Can use 'all', 'block' or false.
}
)
)
)
];
},
save: function( props ) {
return (
el( 'div',
{
className: props.className, // className property is automatically enabled for each block.
style: {
backgroundColor: props.attributes.backgroundColor
}
},
el( 'div',
{
className: 'block-wrap'
},
el( InnerBlocks.Content )
)
)
);
}
});
}(
window.wp.blocks,
window.wp.blockEditor,
window.wp.element
) );
/**
* Text Control.
*
* @link https://developer.wordpress.org/block-editor/components/text-control/
*/
const { TextControl, PanelRow } = components;
el( PanelRow,
{},
el( TextControl,
{
value: props.attributes.textField,
label: __( 'Text Control Label', 'my-text-domain' ),
onChange: ( value ) => {
props.setAttributes(
{
textField: value
}
);
}
}
)
)
/**
* Textarea Control.
*
* @link https://developer.wordpress.org/block-editor/components/textarea-control/
*/
const { TextareaControl, PanelRow } = components;
el( PanelRow,
{},
el( TextareaControl,
{
value: props.attributes.textAreaField,
label: __( 'Textarea Control Label', 'my-text-domain' ),
rows: 8,
onChange: ( value ) => {
props.setAttributes(
{
textAreaField: value
}
);
}
}
)
)
/**
* Toggle Control.
*
* @link https://developer.wordpress.org/block-editor/components/toggle-control/
*/
const { ToggleControl, PanelRow } = components;
el( PanelRow,
{},
el( ToggleControl,
{
label: __( 'Toggle Control Label', 'my-text-domain' ),
onChange: ( value ) => {
props.setAttributes(
{
toggleSetting: value
}
);
},
checked: props.attributes.toggleSetting
}
)
)
/**
* Checkbox Control.
*
* @link https://developer.wordpress.org/block-editor/components/checkbox-control/
*/
const { CheckboxControl, PanelRow } = components;
el( PanelRow,
{},
el( CheckboxControl,
{
label: __( 'Checkbox Control Label', 'my-text-domain' ),
onChange: ( value ) => {
props.setAttributes(
{
checkSetting: value
}
);
},
checked: props.attributes.checkSetting
}
)
)
/**
* Radio Control.
*
* @link https://developer.wordpress.org/block-editor/components/radio-control/
*/
const { RadioControl, PanelRow } = components;
el( PanelRow,
{},
el( RadioControl,
{
label: __( 'Radio Control Label', 'my-text-domain' ),
options: [
{ label: 'Option 1', value: 'value-1' },
{ label: 'Option 2', value: 'value-2' }
],
onChange: ( value ) => {
props.setAttributes(
{
radioSetting: value
}
);
},
selected: props.attributes.radioSetting
}
)
)
/**
* Select Control.
*
* @link https://developer.wordpress.org/block-editor/components/select-control/
*/
const { SelectControl, PanelRow } = components;
el( PanelRow,
{},
el( SelectControl,
{
label: __( 'Select Control Label', 'my-text-domain' ),
options: [
{ label: 'Option 1', value: 'value-1' },
{ label: 'Option 2', value: 'value-2' },
{ label: 'Option 3', value: 'value-3' }
],
onChange: ( value ) => {
props.setAttributes(
{
selectSetting: value
}
);
},
value: props.attributes.selectSetting
}
)
)
/**
* Range Control.
*
* @link https://developer.wordpress.org/block-editor/components/range-control/
*/
const { RangeControl, PanelRow } = components;
el( PanelRow,
{},
el( RangeControl,
{
min: 10,
max: 100,
initialPosition: 40,
value: props.attributes.rangeSetting,
beforeIcon: 'minus', // Can use Dashicons or custom SVG elements (https://developer.wordpress.org/resource/dashicons/)
afterIcon: 'plus-alt2', // Can use Dashicons or custom SVG elements (https://developer.wordpress.org/resource/dashicons/)
label: __( 'Range Control Label', 'my-text-domain' ),
onChange: ( value ) => {
10 < value ? props.setAttributes({ rangeSetting: value }) : props.setAttributes({ rangeSetting: 10 });
}
}
)
)
/**
* Panel Color Control.
*
* @link https://developer.wordpress.org/block-editor/packages/packages-block-editor/#PanelColorSettings
*/
const { PanelColorSettings } = editor;
el( PanelColorSettings,
{
title: __( 'Color settings', 'my-text-domain' ),
initialOpen: true,
colorSettings: [
{
value: props.attributes.colorSetting,
label: __( 'Select color', 'my-text-domain' ),
onChange: ( value ) => {
props.setAttributes(
{
colorSetting: value
}
);
}
}
]
}
)
/**
* Media Upload Control.
*
* @link https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/media-upload/README.md
*/
const { MediaUpload } = editor;
const { PanelRow, Button } = components;
el( PanelRow,
{},
el( 'div',
{},
el( MediaUpload,
{
onSelect: ( value ) => {
props.setAttributes({
image: value.url
});
},
type: 'image', // wp.media object type (e.g, 'image', 'video', 'gallery').
value: props.attributes.image,
render: function( obj ) {
return el( Button,
{
className: props.attributes.image ? 'image-button' : 'button button-large',
style: {
height: 'auto',
padding: props.attributes.image ? 'inherit' : '0 10px'
},
title: 'Click to edit',
onClick: obj.open
},
! props.attributes.image ? __( 'Upload Image', 'my-text-domain' ) : el( 'img', { src: props.attributes.image, alt: '' })
);
}
}
)
)
),
props.attributes.image ?
el( PanelRow,
{},
el( Button,
{
className: 'button is-small',
title: 'Remove Image',
onClick: () => {
props.setAttributes({
image: ''
});
}
},
__( 'Remove Image', 'my-text-domain' )
)
) :
null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment