diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 56d893ae7d3dfb..bd0a758b5cdad5 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -29,7 +29,7 @@ function gutenberg_register_layout_support( $block_type ) { * Generates the CSS corresponding to the provided layout. * * @param string $selector CSS selector. - * @param array $layout Layout object. + * @param array $layout Layout object. The one that is passed has already checked the existance of default block layout. * * @return string CSS style. */ @@ -70,6 +70,14 @@ function gutenberg_get_layout_style( $selector, $layout ) { $style .= 'gap: var( --wp--style--block-gap, 0.5em );'; $style .= 'flex-wrap: wrap;'; $style .= 'align-items: center;'; + /** + * Add this style only if is not empty for backwards compatibility, + * since we intend to convert blocks that had flex layout implemented + * by custom css. + */ + if ( ! empty( $layout['justifyContent'] ) ) { + $style .= "justify-content: {$layout['justifyContent']};"; + } $style .= '}'; $style .= "$selector > * { margin: 0; }"; diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index d130468b93ceec..a55253c8c43033 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -1,7 +1,11 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, _x } from '@wordpress/i18n'; +import { + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, +} from '@wordpress/components'; /** * Internal dependencies @@ -10,14 +14,43 @@ import { appendSelectors } from './utils'; export default { name: 'flex', - label: __( 'Flex' ), - - edit() { - return null; + edit: function LayoutFlexEdit( { layout = {}, onChange } ) { + const { justifyContent = 'flex-start' } = layout; + return ( + { + onChange( { + ...layout, + justifyContent: value, + } ); + } } + isBlock + > + + + + + + ); }, - - save: function FlexLayoutStyle( { selector } ) { + save: function FlexLayoutStyle( { selector, layout } ) { + const { justifyContent = 'flex-start' } = layout; return ( ); }, - getOrientation() { return 'horizontal'; }, - getAlignments() { return []; }, diff --git a/packages/block-library/src/social-links/block.json b/packages/block-library/src/social-links/block.json index 73ac6142c7042e..b9c8eddbdc4d6f 100644 --- a/packages/block-library/src/social-links/block.json +++ b/packages/block-library/src/social-links/block.json @@ -41,7 +41,14 @@ "supports": { "align": [ "left", "center", "right" ], "anchor": true, - "__experimentalExposeControlsToChildren": true + "__experimentalExposeControlsToChildren": true, + "__experimentalLayout": { + "allowSwitching": false, + "allowInheriting": false, + "default": { + "type": "flex" + } + } }, "styles": [ { "name": "default", "label": "Default", "isDefault": true }, diff --git a/packages/block-library/src/social-links/deprecated.js b/packages/block-library/src/social-links/deprecated.js index e8615282201f56..c140a6e36b4dae 100644 --- a/packages/block-library/src/social-links/deprecated.js +++ b/packages/block-library/src/social-links/deprecated.js @@ -8,8 +8,102 @@ import classNames from 'classnames'; */ import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +const justifyContentMap = { + left: 'flex-start', + right: 'flex-end', + center: 'center', + 'space-between': 'space-between', +}; + +// TODO: this is temp implementation to test quickly. +// This will need to be applied to the others migrations. +// The problem exists because `itemsJustification` was introduced in https://github.com/WordPress/gutenberg/pull/28980/files +// and wasn't declared in block.json (https://github.com/WordPress/gutenberg/issues/34003). +const migrateWithLayout = ( attributes ) => { + if ( !! attributes.layout ) { + return attributes; + } + + let justifyContent = 'flex-start'; + let className = attributes.className; + const cssClasses = className?.split( ' ' ); + if ( cssClasses ) { + const prefix = 'item-justified-'; + className = cssClasses.reduce( ( accumulator, cssClass ) => { + if ( ! cssClass.startsWith( prefix ) ) { + justifyContent = + justifyContentMap[ cssClass.slice( prefix.length + 1 ) ]; + return accumulator; + } + return `${ accumulator } ${ cssClass }`; + }, '' ); + } + return { + ...attributes, + className, + layout: { + type: 'flex', + justifyContent, + }, + }; +}; + // Social Links block deprecations. const deprecated = [ + // Implement `flex` layout. + { + attributes: { + iconColor: { + type: 'string', + }, + customIconColor: { + type: 'string', + }, + iconColorValue: { + type: 'string', + }, + iconBackgroundColor: { + type: 'string', + }, + customIconBackgroundColor: { + type: 'string', + }, + iconBackgroundColorValue: { + type: 'string', + }, + openInNewTab: { + type: 'boolean', + default: false, + }, + size: { + type: 'string', + }, + }, + isEligible: ( { layout } ) => ! layout, + migrate: migrateWithLayout, + save( props ) { + const { + attributes: { + iconBackgroundColorValue, + iconColorValue, + itemsJustification, + size, + }, + } = props; + + const className = classNames( size, { + 'has-icon-color': iconColorValue, + 'has-icon-background-color': iconBackgroundColorValue, + [ `items-justified-${ itemsJustification }` ]: itemsJustification, + } ); + + return ( + + ); + }, + }, // V1. Remove CSS variable use for colors. { attributes: { diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index cd4a10b171adb5..8675f31b0ed13c 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -6,18 +6,18 @@ import classNames from 'classnames'; /** * WordPress dependencies */ - +import { getBlockSupport } from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; import { Fragment, useEffect } from '@wordpress/element'; - import { BlockControls, __experimentalUseInnerBlocksProps as useInnerBlocksProps, useBlockProps, InspectorControls, - JustifyContentControl, ContrastChecker, PanelColorSettings, withColors, + store as blockEditorStore, } from '@wordpress/block-editor'; import { MenuGroup, @@ -38,8 +38,18 @@ const sizeOptions = [ { name: __( 'Huge' ), value: 'has-huge-icon-size' }, ]; +const getDefaultBlockLayout = ( blockTypeOrName ) => { + const layoutBlockSupportConfig = getBlockSupport( + blockTypeOrName, + '__experimentalLayout' + ); + return layoutBlockSupportConfig?.default; +}; + export function SocialLinksEdit( props ) { const { + name, + clientId, attributes, iconBackgroundColor, iconColor, @@ -52,10 +62,23 @@ export function SocialLinksEdit( props ) { const { iconBackgroundColorValue, iconColorValue, - itemsJustification, openInNewTab, size, + layout, } = attributes; + // This probably should not be used/checked here. We need to make all `social-links` + // blocks to use `flex` layout. + const { themeSupportsLayout } = useSelect( + ( select ) => { + const { getSettings } = select( blockEditorStore ); + return { + themeSupportsLayout: getSettings()?.supportsLayout, + }; + }, + [ clientId ] + ); + + const usedLayout = !! layout || getDefaultBlockLayout( name ); // Remove icon background color if logos only style selected. const logosOnly = @@ -93,16 +116,16 @@ export function SocialLinksEdit( props ) { 'has-icon-color': iconColor.color || iconColorValue, 'has-icon-background-color': iconBackgroundColor.color || iconBackgroundColorValue, - [ `items-justified-${ itemsJustification }` ]: itemsJustification, } ); const blockProps = useBlockProps( { className } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { allowedBlocks: ALLOWED_BLOCKS, - orientation: 'horizontal', placeholder: isSelected ? SelectedSocialPlaceholder : SocialPlaceholder, templateLock: false, __experimentalAppenderTagName: 'li', + __experimentalLayout: + themeSupportsLayout && usedLayout ? usedLayout : undefined, } ); const POPOVER_PROPS = { @@ -111,24 +134,6 @@ export function SocialLinksEdit( props ) { return ( - - - setAttributes( { itemsJustification: value } ) - } - popoverProps={ { - position: 'bottom right', - isAlternate: true, - } } - /> -