diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 7baa5fec4ffd6..1ef6092a512cf 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -65,10 +65,13 @@ function gutenberg_get_layout_style( $selector, $layout ) { $style .= "$selector .alignleft { float: left; margin-right: 2em; }"; $style .= "$selector .alignright { float: right; margin-left: 2em; }"; } elseif ( 'flex' === $layout_type ) { + $justify_content = isset( $layout['justifyContent'] ) ? $layout['justifyContent'] : 'flex-start'; + $style = "$selector {"; $style .= 'display: flex;'; + $style .= 'flex-direction: row;'; $style .= 'column-gap: 0.5em;'; - $style .= 'align-items: center;'; + $style .= "justify-content: $justify_content;"; $style .= '}'; } diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index 17bceb33a7202..8f80c52997a58 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -12,10 +12,11 @@ import { addFilter } from '@wordpress/hooks'; import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks'; import { useSelect } from '@wordpress/data'; import { - Button, - ButtonGroup, + BaseControl, ToggleControl, PanelBody, + __experimentalSegmentedControl as SegmentedControl, + __experimentalSegmentedControlOption as SegmentedControlOption, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useContext, createPortal } from '@wordpress/element'; @@ -32,40 +33,40 @@ import { getLayoutType, getLayoutTypes } from '../layouts'; const layoutBlockSupportKey = '__experimentalLayout'; -const canBlockSwitchLayout = ( blockTypeOrName ) => { - const layoutBlockSupportConfig = getBlockSupport( - blockTypeOrName, - layoutBlockSupportKey - ); - - return layoutBlockSupportConfig?.allowSwitching; -}; - function LayoutPanel( { setAttributes, attributes, name: blockName } ) { - const { layout = {} } = attributes; - const defaultLayout = useSetting( 'layout' ); + const { layout } = attributes; + // TODO: check if a theme should provide default values per `layoutType`. + // Fow now we use the values from `flow` (content, width). + const defaultThemeLayout = useSetting( 'layout' ); const themeSupportsLayout = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); return getSettings().supportsLayout; }, [] ); + // TODO: If we implement layout for blocks and replace + // current display of them like this PR explores, shouldn't this check change? if ( ! themeSupportsLayout ) { return null; } - const allowLayoutSwitching = canBlockSwitchLayout( blockName ); - const { inherit = false, type = 'default' } = layout; + const { + allowSwitching: canBlockSwitchLayout, + default: defaultBlockLayout, + } = getBlockSupport( blockName, layoutBlockSupportKey ) || {}; + + const usedLayout = layout ? layout : defaultBlockLayout || {}; + const { inherit = false, type = 'default' } = usedLayout; const layoutType = getLayoutType( type ); const onChangeType = ( newType ) => - setAttributes( { layout: { type: newType } } ); + setAttributes( { layout: { type: newType } } ); // TODO needs checking with block defaults. const onChangeLayout = ( newLayout ) => setAttributes( { layout: newLayout } ); return ( - { !! defaultLayout && ( + { inherit && !! defaultThemeLayout && ( ) } - - { ! inherit && allowLayoutSwitching && ( + { ! inherit && canBlockSwitchLayout && ( ) } @@ -95,19 +95,21 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) { function LayoutTypeSwitcher( { type, onChange } ) { return ( - - { getLayoutTypes().map( ( { name, label } ) => { - return ( - - ); - } ) } - + value={ name } + label={ label } + > + ) ) } + + ); } diff --git a/packages/block-editor/src/layouts/flex.js b/packages/block-editor/src/layouts/flex.js index 9818cfe4ff31b..5866e4dcd1438 100644 --- a/packages/block-editor/src/layouts/flex.js +++ b/packages/block-editor/src/layouts/flex.js @@ -7,22 +7,44 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import { appendSelectors } from './utils'; +import { JustifyContentControl } from '../components/justify-content-control'; + +const HORIZONTAL_JUSTIFY_CONTROLS = { + left: 'flex-start', + center: 'center', + right: 'flex-end', + 'space-between': 'space-between', +}; export default { name: 'flex', label: __( 'Flex' ), - edit() { - return null; + edit: function LayoutFlexEdit( { layout = {}, onChange } ) { + const { justifyContent = 'flex-start' } = layout; + return ( + { + onChange( { + ...layout, + justifyContent: HORIZONTAL_JUSTIFY_CONTROLS[ value ], + } ); + } } + /> + ); }, - save: function FlexLayoutStyle( { selector } ) { + save: function FlexLayoutStyle( { selector, layout = {} } ) { + const { justifyContent = 'flex-start' } = layout; return ( ); }, diff --git a/packages/block-editor/src/layouts/flow.js b/packages/block-editor/src/layouts/flow.js index 8c350f4e229fc..1b615bc467ffd 100644 --- a/packages/block-editor/src/layouts/flow.js +++ b/packages/block-editor/src/layouts/flow.js @@ -113,11 +113,9 @@ export default { margin-left: auto !important; margin-right: auto !important; } - ${ appendSelectors( selector, '> [data-align="wide"]' ) } { max-width: ${ wideSize ?? contentSize }; } - ${ appendSelectors( selector, '> [data-align="full"]' ) } { max-width: none; } @@ -129,7 +127,6 @@ export default { float: left; margin-right: 2em; } - ${ appendSelectors( selector, '> [data-align="right"]' ) } { float: right; margin-left: 2em; diff --git a/packages/block-library/src/social-links/block.json b/packages/block-library/src/social-links/block.json index b559ae04fa8a5..620b76d08c5de 100644 --- a/packages/block-library/src/social-links/block.json +++ b/packages/block-library/src/social-links/block.json @@ -40,7 +40,16 @@ }, "supports": { "align": [ "left", "center", "right" ], - "anchor": true + "anchor": true, + "__experimentalLayout": { + "allowSwitching": false, + "inherit": false, + "default": { + "type": "flex", + "justifyContent": "flex-start", + "column-gap": "normal" + } + } }, "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 e8615282201f5..fb056c9ac209a 100644 --- a/packages/block-library/src/social-links/deprecated.js +++ b/packages/block-library/src/social-links/deprecated.js @@ -8,8 +8,103 @@ 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 super 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. I'll create a separate issue for this as well. +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, + 'column-gap': 'normal', + }, + }; +}; + // 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 089dd24824b28..8cde27f3194b6 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -6,18 +6,19 @@ 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, + useSetting, + store as blockEditorStore, } from '@wordpress/block-editor'; import { MenuGroup, @@ -38,6 +39,15 @@ 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 { attributes, @@ -45,17 +55,32 @@ export function SocialLinksEdit( props ) { iconColor, isSelected, setAttributes, + name, setIconBackgroundColor, setIconColor, + clientId, } = 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 +118,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 +136,6 @@ export function SocialLinksEdit( props ) { return ( - - - setAttributes( { itemsJustification: value } ) - } - popoverProps={ { - position: 'bottom right', - isAlternate: true, - } } - /> -