Custom block alignment
Mark Howells-Mead edited this page Nov 27, 2023
·
1 revision
var {
__,
} = wp.i18n;
var {
BlockControls,
useBlockProps,
} = wp.blockEditor;
var {
ToolbarDropdownMenu,
ToolbarGroup,
DropdownMenu,
MenuGroup,
MenuItem,
} = wp.components;
var {
createHigherOrderComponent,
} = wp.compose;
var {
getBlockSupport,
} = wp.blocks;
var {
Fragment,
createElement,
} = wp.element;
var el = createElement;
/*
* Disable default "align" to hide the core block alignment toolbar.
* Clone the block specific "align" supports values and store these in "alignCustom" instead.
*/
function modifyBlockAlignmentSupport( settings, name ) {
if ( ! name.includes('acf/') ) {
// Only modify our acf blocks
return settings;
}
const hasAlignSupport = getBlockSupport( name, 'align', false );
if( ! hasAlignSupport ) {
return settings;
}
// Get the original align values from the block supports settings
let originalAlignSupport = settings.supports.align;
// Modify the default block supports settings
newSettings = {
...settings,
supports: {
...settings.supports,
align: false, // <-- This will disable the default align to hide the core block alignment toolbar
alignCustom: originalAlignSupport, // <-- We clone the default align and store it here instead
}
};
return newSettings;
}
wp.hooks.addFilter( 'blocks.registerBlockType', 'plugin-name/modify-block-align-support', modifyBlockAlignmentSupport );
/*
* Function to handle the block alignment icons
*/
function blockAlignIcon( name ) {
var icons = {
'none': 'M5 15h14V9H5v6zm0 4.8h14v-1.5H5v1.5zM5 4.2v1.5h14V4.2H5z',
'full': 'M5 4v11h14V4H5zm3 15.8h8v-1.5H8v1.5z',
'wide': 'M5 9v6h14V9H5zm11-4.8H8v1.5h8V4.2zM8 19.8h8v-1.5H8v1.5z',
'narrow': 'M5 9v6h14V9H5zm11-4.8H8v1.5h8V4.2zM8 19.8h8v-1.5H8v1.5z',
'left': 'M4 9v6h14V9H4zm8-4.8H4v1.5h8V4.2zM4 19.8h8v-1.5H4v1.5z',
'center': 'M7 9v6h10V9H7zM5 19.8h14v-1.5H5v1.5zM5 4.3v1.5h14V4.3H5z',
'right': 'M6 15h14V9H6v6zm6-10.8v1.5h8V4.2h-8zm0 15.6h8v-1.5h-8v1.5z',
}
//var path = icons.name ? icons.name : icons.none;
var path = icons[name];
return el('svg', { width: 24, height: 24 },
el('path', { d: path } )
);
}
/*
* Filter to add custom block alignment toolbar controls
*/
var customBlockAlignmentControls = createHigherOrderComponent( function( BlockEdit ) {
return function( props ) {
const blockName = props.name;
const currentAlign = props.attributes.align;
const originalEdit = el( BlockEdit, props );
// Check for block align support
const blockAlignSupport = getBlockSupport( blockName, 'alignCustom', false );
// We add this custom controls to our acf blocks only
if( ! blockName.includes('acf/') ) {
// Return unmodified block edit
return originalEdit;
}
// Do not add this custom controls if the block type has no align support
if( ! blockAlignSupport ) {
// Return unmodified block edit
return originalEdit;
}
// Get the current ToolbarDropdownMenu icon, depending on the selected align
let currentIcon = currentAlign ? currentAlign : 'none';
currentIcon = blockAlignIcon( currentIcon );
/*
* Define a function to set the "align" attribute, after selecting a specific block alignment
*/
function onChangeAlignment( newAlignment ) {
let iconName = newAlignment;
if( newAlignment === 'none' ) {
// Because we don't want a "alignnone" classname in our block
newAlignment = false;
}
// Change the block align attribute
props.setAttributes( {
align: newAlignment === undefined ? 'none' : newAlignment,
} );
// Change the current ToolbarDropdownMenu icon if the block align has been changed
const alignToolbarButton = document.querySelector('[aria-label="Align"]');
if( alignToolbarButton ) {
let iconPath = blockAlignIcon( iconName );
iconPath = iconPath.props.children.props.d;
alignToolbarButton.innerHTML = '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="' + iconPath + '"/></svg>';
}
}
/*
* List all possible block alignments
*/
const alignControls = {
none: __('None', 'textdomain'),
full: __('Full width', 'textdomain'),
wide: __('Wide width', 'textdomain'),
narrow: __('Narrow width', 'textdomain'),
left: __('Align left', 'textdomain'),
center: __('Align center', 'textdomain'),
right: __('Align right', 'textdomain'),
}
/*
* Build the toolbar block alignment controls depening on the align support of the block type
*/
const allowedAlignControls = [];
for( let key in alignControls ) {
if( ! blockAlignSupport.includes( key ) && key !== 'none' ) {
// [None] should be there all the time to reset other selected alignments
// Only add the current align control if it's supported
continue;
}
let controlTitle = alignControls[key];
let newControl = {
title: controlTitle,
icon: blockAlignIcon( key ),
onClick: () => onChangeAlignment( key ),
};
allowedAlignControls.push(newControl);
}
/*
* Re-Build the block toolbar and edit
*/
return el(
Fragment,
{},
el( BlockControls, {
key: 'controls',
group: 'default',
},
el( ToolbarGroup, null,
el( ToolbarDropdownMenu, {
label: 'Align',
icon: currentIcon,
controls: allowedAlignControls,
} ),
),
), el( BlockEdit, props )
);
};
}, 'withInspectorControls' );
wp.hooks.addFilter( 'editor.BlockEdit', 'plugin-name/with-inspector-controls', customBlockAlignmentControls );
Mark Howells-Mead | https://permanenttourist.ch and https://sayhello.ch/ | Wiki since 2016
Use this code freely, widely and for free. Provision of this code provides and implies no guarantee.
Please respect the GPL v3 licence, which is available via http://www.gnu.org/licenses/gpl-3.0.html