Files
CHIEFSOFT\ameye e9e5c0546c first commit
2023-11-30 13:20:54 -05:00

289 lines
7.3 KiB
React
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* Internal dependencies
*/
import isCoreBlockWithExt from '../../utils/is-core-block-with-ext';
import getParentBlock from '../../utils/get-parent-block';
const {
canvasBreakpoints,
} = window;
/**
* WordPress dependencies
*/
const {
addFilter,
} = wp.hooks;
const {
Component,
} = wp.element;
const {
createHigherOrderComponent,
} = wp.compose;
const {
hasBlockSupport,
} = wp.blocks;
const { select, subscribe } = wp.data;
/**
* Extend block attributes with unique class name.
*
* @param {Object} blockSettings Original block settings.
* @param {String} name Original block name.
*
* @return {Object} Filtered block settings.
*/
function addAttribute( blockSettings, name ) {
let supports = (
hasBlockSupport( blockSettings, 'canvasUniqueClass', false ) ||
hasBlockSupport( blockSettings, 'canvasBackgroundImage', false ) ||
hasBlockSupport( blockSettings, 'canvasSpacings', false ) ||
hasBlockSupport( blockSettings, 'canvasBorder', false ) ||
hasBlockSupport( blockSettings, 'canvasResponsive', false )
);
// add support to core blocks
if ( isCoreBlockWithExt( name ) ) {
blockSettings.supports = {
...blockSettings.supports,
canvasUniqueClass: true,
};
supports = true;
}
if ( supports ) {
if ( blockSettings.attributes && ! blockSettings.attributes.canvasClassName ) {
blockSettings.attributes.canvasClassName = {
type: 'string',
};
}
}
return blockSettings;
}
/**
* Override the default edit UI to include a new block inspector control for
* assigning the custom spacings if needed.
*
* @param {function|Component} BlockEdit Original component.
*
* @return {string} Wrapped component.
*/
const withInspectorControl = createHigherOrderComponent( ( OriginalComponent ) => {
class CanvasUniqueClassNameWrapper extends Component {
constructor() {
super( ...arguments );
this.getAllBlocks = this.getAllBlocks.bind( this );
this.maybeCreateUniqueClassName = this.maybeCreateUniqueClassName.bind( this );
}
componentDidMount() {
this.maybeCreateUniqueClassName( true );
}
componentDidUpdate() {
this.maybeCreateUniqueClassName();
}
/**
* Get recursive all blocks of the current page
*/
getAllBlocks( blocks = false ) {
let result = [];
if ( ! blocks ) {
blocks = wp.data.select( 'core/block-editor' ).getBlocks();
}
if ( ! blocks ) {
return result;
}
blocks.forEach( ( data ) => {
result.push( data );
if ( data.innerBlocks && data.innerBlocks.length ) {
result = [
...result,
...this.getAllBlocks( data.innerBlocks ),
];
}
} );
return result;
}
/**
* Generate unique block class name
*/
maybeCreateUniqueClassName( checkDuplicates ) {
const {
name,
attributes,
setAttributes,
clientId,
} = this.props;
const {
getBlockHierarchyRootClientId,
getBlock,
} = select('core/block-editor');
const rootBlock = getBlock(getBlockHierarchyRootClientId(clientId));
if ( rootBlock && rootBlock.hasOwnProperty( 'name' ) && 'core/gallery' === rootBlock.name ) {
return;
}
if (
! hasBlockSupport( name, 'canvasUniqueClass', false ) &&
! hasBlockSupport( name, 'canvasBackgroundImage', false ) &&
! hasBlockSupport( name, 'canvasSpacings', false ) &&
! hasBlockSupport( name, 'canvasBorder', false ) &&
! hasBlockSupport( name, 'canvasResponsive', false )
) {
return;
}
let {
canvasClassName,
} = attributes;
// prevent unique ID duplication after block duplicated.
if ( checkDuplicates ) {
const allBlocks = this.getAllBlocks();
allBlocks.forEach( ( data ) => {
if (
data.clientId !== clientId &&
data.attributes &&
data.attributes.canvasClassName &&
data.attributes.canvasClassName === canvasClassName
) {
canvasClassName = '';
}
} );
}
if ( ! canvasClassName ) {
const newId = new Date().getTime();
// Generated HTML classes for blocks follow the `cnvs-block-{name}` nomenclature.
// Blocks provided by Canvas drop the prefixes 'canvas/'.
const className = 'cnvs-block-' + name.replace( /\//, '-' ).replace( /^canvas-/, '' );
setAttributes( {
canvasClassName: className + '-' + newId,
} );
}
}
render() {
return <OriginalComponent { ...this.props } />;
}
}
return CanvasUniqueClassNameWrapper;
}, 'withInspectorControl' );
/**
* Override props assigned to save component to inject custom styles.
* This is only applied if the block's save result is an
* element and not a markup string.
*
* @param {Object} extraProps Additional props applied to save element.
* @param {Object} blockType Block type.
* @param {Object} attributes Current block attributes.
*
* @return {Object} Filtered props applied to save element.
*/
function addSaveProps( extraProps, blockType, attributes ) {
// add custom classname to non-canvas blocks.
// we need this class only when Spacings or Responsive controls added on the block.
if ( blockType.name && ! /^canvas/.test( name ) && attributes.canvasClassName ) {
const extAttrs = [
'backgroundImage',
'backgroundPosition',
'backgroundPositionXUnit',
'backgroundPositionXVal',
'backgroundPositionYUnit',
'backgroundPositionYVal',
'backgroundAttachment',
'backgroundRepeat',
'backgroundSize',
'backgroundSizeUnit',
'backgroundSizeVal',
'marginTop',
'marginRight',
'marginBottom',
'marginLeft',
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
'borderRadiusTopLeft',
'borderRadiusTopRight',
'borderRadiusBottomLeft',
'borderRadiusBottomRight',
'borderStyle',
'canvasResponsiveHide',
];
let isCustomClassRequired = false;
// responsive attributes.
extAttrs.forEach( ( attr ) => {
if ( typeof attributes[ attr ] !== 'undefined' ) {
isCustomClassRequired = true;
}
Object.keys( canvasBreakpoints ).forEach( ( breakpoint ) => {
if ( ! isCustomClassRequired && typeof attributes[ `${ attr }_${ breakpoint }` ] !== 'undefined' ) {
isCustomClassRequired = true;
}
} );
} );
if ( isCustomClassRequired ) {
extraProps.className = classnames(
extraProps.className,
attributes.canvasClassName
);
}
}
return extraProps;
}
// Init filters.
addFilter( 'blocks.registerBlockType', 'canvas/unique-classname/additional-attributes', addAttribute );
addFilter( 'editor.BlockEdit', 'canvas/unique-classname/additional-attributes', withInspectorControl );
addFilter( 'blocks.getSaveContent.extraProps', 'canvas/unique-classname/save-props', addSaveProps );
/**
* Used to modify the blocks wrapper component containing the blocks edit
* component and all toolbars. It receives the original BlockListBlock
* component and returns a new wrapped component.
*/
const withClientIdClassName = createHigherOrderComponent( ( BlockListBlock ) => {
return ( props ) => {
if ( props.name && ! /^canvas/.test( props.name ) && props.attributes.canvasClassName ) {
return <BlockListBlock { ...props } className={ classnames( props.className, props.attributes.canvasClassName ) } />;
} else {
return <BlockListBlock { ...props } />;
}
};
}, 'withClientIdClassName' );
addFilter( 'editor.BlockListBlock', 'canvas/with-client-id-class-name', withClientIdClassName );