Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add support for block variation styles
  • Loading branch information
ntsekouras committed Apr 20, 2023
commit 7dfd9b2ecdd03b45cfcc179be9542e4fdcc1b87e
14 changes: 14 additions & 0 deletions docs/reference-guides/data/data-core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ _Parameters_

- _state_ `Object`: Data state.
- _name_ `string`: Block type name.
- _attributes_ `[Object]`: Block attributes. If provided, will try to find and include styles for specific block variations.

_Returns_

Expand Down Expand Up @@ -246,6 +247,19 @@ _Returns_

- `(WPBlockVariation[]|void)`: Block variations.

### getBlockVariationStyles

Returns block variation styles by block name.

_Parameters_

- _state_ `Object`: Data state.
- _name_ `string`: Block type name.

_Returns_

- `Array?`: Block Styles.

### getCategories

Returns all the available block categories.
Expand Down
41 changes: 41 additions & 0 deletions lib/compat/wordpress-6.3/script-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,44 @@
remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' );


/**
* Function responsible for enqueuing the assets required for block styles functionality on the editor.
*
* @since 5.3.0
* @since 6.3.0 Support styles for block variations.
*/
function gutenberg_enqueue_editor_block_styles_assets() {
$block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered();

$register_script_lines = array( '( function() {' );
foreach ( $block_styles as $block_name => $styles ) {
foreach ( $styles as $style_properties ) {
$block_style = array(
'name' => $style_properties['name'],
'label' => $style_properties['label'],
);
if ( isset( $style_properties['is_default'] ) ) {
$block_style['isDefault'] = $style_properties['is_default'];
}
if ( isset( $style_properties['variations'] ) ) {
$block_style['variations'] = $style_properties['variations'];
}
$register_script_lines[] = sprintf(
' wp.blocks.registerBlockStyle( \'%s\', %s );',
$block_name,
wp_json_encode( $block_style )
);
}
}
$register_script_lines[] = '} )();';
$inline_script = implode( "\n", $register_script_lines );

wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, true );
wp_add_inline_script( 'wp-block-styles', $inline_script );
wp_enqueue_script( 'wp-block-styles' );
}

// Remove the Core action hook to avoid handling editor block style assets twice.
remove_action( 'enqueue_block_editor_assets', 'enqueue_editor_block_styles_assets' );
add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_editor_block_styles_assets' );
10 changes: 7 additions & 3 deletions packages/block-editor/src/components/block-inspector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,14 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => {
const hasBlockStyles = useSelect(
( select ) => {
const { getBlockStyles } = select( blocksStore );
const blockStyles = getBlockStyles( blockName );
return blockStyles && blockStyles.length > 0;
const { getBlockAttributes } = select( blockEditorStore );
const blockStyles = getBlockStyles(
blockName,
getBlockAttributes( clientId )
);
return blockStyles?.length > 0;
},
[ blockName ]
[ clientId, blockName ]
);
const blockInformation = useBlockDisplayInformation( clientId );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { useEventHandlers } from './use-selected-block-event-handlers';
import { useNavModeExit } from './use-nav-mode-exit';
import { useBlockRefProvider } from './use-block-refs';
import { useIntersectionObserver } from './use-intersection-observer';
import useCleanBlockStyles from './use-clean-block-styles';
import { store as blockEditorStore } from '../../../store';
import useBlockOverlayActive from '../../block-content-overlay';

Expand Down Expand Up @@ -116,6 +117,9 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
[ clientId ]
);

// This hook has side effects. Removes any lingering block variation styles.
useCleanBlockStyles( clientId );

const hasOverlay = useBlockOverlayActive( clientId );

// translators: %s: Type of block (i.e. Text, Image etc)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* WordPress dependencies
*/
import { useEffect } from '@wordpress/element';
import { store as blocksStore } from '@wordpress/blocks';
import { useSelect, useDispatch } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../../store';

/**
* This hook checks if any applied block variation style is set,
* but the respective block variation is not active now.
*
* In this case this hook performs a side effect to remove
* that style(class name) and doesn't create an `undo` step.
*
* @param {string} clientId The block client ID.
*
*/
export default function useCleanBlockStyles( clientId ) {
const { updateBlockAttributes } = useDispatch( blockEditorStore );
const { __unstableMarkNextChangeAsNotPersistent } =
useDispatch( blockEditorStore );
const { styleToRemove, blockClassNames } = useSelect(
( select ) => {
const { getBlockAttributes, getBlockName } =
select( blockEditorStore );
const { getActiveBlockVariation, getBlockVariationStyles } =
select( blocksStore );
const attributes = getBlockAttributes( clientId );
if ( ! attributes.className ) {
return {};
}
// Here we are checking if the block has a block style for a specific
// block variation. If it does and the block variation is no longer active,
// we need to remove the style class name.
const blockName = getBlockName( clientId );
const match = getActiveBlockVariation( blockName, attributes );
const blockVariationStyles = getBlockVariationStyles( blockName );
return {
styleToRemove: blockVariationStyles?.find(
( { name: styleName, variations } ) =>
attributes.className.includes(
`is-style-${ styleName }`
) &&
( ! match || ! variations.includes( match.name ) )
)?.name,
blockClassNames: attributes.className,
};
},
[ clientId ]
);
useEffect( () => {
if ( styleToRemove === undefined ) {
return;
}
const updatedClassNames = blockClassNames
.split( ' ' )
.filter(
( blockClassName ) =>
! blockClassName.includes( `is-style-${ styleToRemove }` )
)
.join( ' ' );
__unstableMarkNextChangeAsNotPersistent();
updateBlockAttributes( clientId, {
className: updatedClassNames,
} );
}, [ clientId, styleToRemove, blockClassNames ] );
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default function useStylesForBlocks( { clientId, onSwitch } ) {
return {
block,
blockType,
styles: getBlockStyles( block.name ),
styles: getBlockStyles( block.name, block.attributes ),
className: block.attributes.className || '',
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => {
const rootClientId = getBlockRootClientId(
Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds
);
const [ { name: firstBlockName } ] = blocks;
const [
{ name: firstBlockName, attributes: firstBlockAttributes },
] = blocks;
const _isSingleBlockSelected = blocks.length === 1;
const styles =
_isSingleBlockSelected && getBlockStyles( firstBlockName );
_isSingleBlockSelected &&
getBlockStyles( firstBlockName, firstBlockAttributes );
let _icon;
if ( _isSingleBlockSelected ) {
_icon = blockInformation?.icon; // Take into account active block variations.
Expand Down
50 changes: 45 additions & 5 deletions packages/blocks/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ export function getBlockType( state, name ) {
/**
* Returns block styles by block name.
*
* @param {Object} state Data state.
* @param {string} name Block type name.
* @param {Object} state Data state.
* @param {string} name Block type name.
* @param {Object} [attributes] Block attributes. If provided, will try to find and include styles for specific block variations.
*
* @example
* ```js
Expand All @@ -143,9 +144,48 @@ export function getBlockType( state, name ) {
*
* @return {Array?} Block Styles.
*/
export function getBlockStyles( state, name ) {
return state.blockStyles[ name ];
}
export const getBlockStyles = createSelector(
( state, name, attributes ) => {
const mainBlockStyles = state.blockStyles[ name ]?.filter(
( { variations } ) => ! variations
);
// If block attributes are provided, try to find styles for
// any active block variation.
if ( ! attributes ) {
return mainBlockStyles;
}
const activeVariation = getActiveBlockVariation(
state,
name,
attributes
);
if ( ! activeVariation ) {
return mainBlockStyles;
}
const activeVariationStyles = state.blockStyles[ name ]?.filter(
( { variations } ) => variations?.includes( activeVariation.name )
);
return [ ...activeVariationStyles, ...mainBlockStyles ];
},
( state, name ) => [ state.blockStyles[ name ] ]
);

/**
* Returns block variation styles by block name.
*
* @param {Object} state Data state.
* @param {string} name Block type name.
*
* @return {Array?} Block Styles.
*/
export const getBlockVariationStyles = createSelector(
( state, name ) => {
return state.blockStyles[ name ]?.filter(
( { variations } ) => !! variations
);
},
( state, name ) => [ state.blockStyles[ name ] ]
);

/**
* Returns block variations by block name.
Expand Down
6 changes: 6 additions & 0 deletions schemas/json/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,12 @@
"isDefault": {
"type": "boolean",
"default": false
},
"variations": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't working for me when testing this branch - I'm still getting a warning in VSCode that this property isn't allowed when adding it to block.json 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes I had that warning too in VSCode when I first check out the branch, but it goes away if I reopen that file. Probably some VSCode cache? 🤔 . Even with the warning it still works though for me? What do you mean not working?

"type": "array",
"items": {
"type": "string"
}
}
},
"required": [ "name", "label" ],
Expand Down