diff --git a/packages/block-editor/src/components/block-alignment-control/use-available-alignments.js b/packages/block-editor/src/components/block-alignment-control/use-available-alignments.js
index d77eb2af2a5976..67e92b012a53bf 100644
--- a/packages/block-editor/src/components/block-alignment-control/use-available-alignments.js
+++ b/packages/block-editor/src/components/block-alignment-control/use-available-alignments.js
@@ -19,29 +19,43 @@ export default function useAvailableAlignments( controls = DEFAULT_CONTROLS ) {
if ( ! controls.includes( 'none' ) ) {
controls = [ 'none', ...controls ];
}
- const {
- wideControlsEnabled = false,
- themeSupportsLayout,
- isBlockBasedTheme,
- } = useSelect( ( select ) => {
- const { getSettings } = select( blockEditorStore );
- const settings = getSettings();
- return {
- wideControlsEnabled: settings.alignWide,
- themeSupportsLayout: settings.supportsLayout,
- isBlockBasedTheme: settings.__unstableIsBlockBasedTheme,
- };
- }, [] );
+ const isNoneOnly = controls.length === 1 && controls[ 0 ] === 'none';
+
+ const [ wideControlsEnabled, themeSupportsLayout, isBlockBasedTheme ] =
+ useSelect(
+ ( select ) => {
+ // If `isNoneOnly` is true, we'll be returning early because there is
+ // nothing to filter on an empty array. We won't need the info from
+ // the `useSelect` but we must call it anyway because Rules of Hooks.
+ // So the callback returns early to avoid block editor subscription.
+ if ( isNoneOnly ) {
+ return [ false, false, false ];
+ }
+
+ const settings = select( blockEditorStore ).getSettings();
+ return [
+ settings.alignWide ?? false,
+ settings.supportsLayout,
+ settings.__unstableIsBlockBasedTheme,
+ ];
+ },
+ [ isNoneOnly ]
+ );
const layout = useLayout();
+
+ if ( isNoneOnly ) {
+ return EMPTY_ARRAY;
+ }
+
const layoutType = getLayoutType( layout?.type );
- const layoutAlignments = layoutType.getAlignments(
- layout,
- isBlockBasedTheme
- );
if ( themeSupportsLayout ) {
- const alignments = layoutAlignments.filter(
- ( { name: alignmentName } ) => controls.includes( alignmentName )
+ const layoutAlignments = layoutType.getAlignments(
+ layout,
+ isBlockBasedTheme
+ );
+ const alignments = layoutAlignments.filter( ( alignment ) =>
+ controls.includes( alignment.name )
);
// While we treat `none` as an alignment, we shouldn't return it if no
// other alignments exist.
@@ -55,25 +69,26 @@ export default function useAvailableAlignments( controls = DEFAULT_CONTROLS ) {
if ( layoutType.name !== 'default' && layoutType.name !== 'constrained' ) {
return EMPTY_ARRAY;
}
- const { alignments: availableAlignments = DEFAULT_CONTROLS } = layout;
- const enabledControls = controls
- .filter(
- ( control ) =>
- ( layout.alignments || // Ignore the global wideAlignment check if the layout explicitely defines alignments.
- wideControlsEnabled ||
- ! WIDE_CONTROLS.includes( control ) ) &&
- availableAlignments.includes( control )
- )
- .map( ( enabledControl ) => ( { name: enabledControl } ) );
+
+ const alignments = controls
+ .filter( ( control ) => {
+ if ( layout.alignments ) {
+ return layout.alignments.includes( control );
+ }
+
+ if ( ! wideControlsEnabled && WIDE_CONTROLS.includes( control ) ) {
+ return false;
+ }
+
+ return DEFAULT_CONTROLS.includes( control );
+ } )
+ .map( ( name ) => ( { name } ) );
// While we treat `none` as an alignment, we shouldn't return it if no
// other alignments exist.
- if (
- enabledControls.length === 1 &&
- enabledControls[ 0 ].name === 'none'
- ) {
+ if ( alignments.length === 1 && alignments[ 0 ].name === 'none' ) {
return EMPTY_ARRAY;
}
- return enabledControls;
+ return alignments;
}
diff --git a/packages/block-editor/src/hooks/align.js b/packages/block-editor/src/hooks/align.js
index a417d11d900431..f266bb32e18197 100644
--- a/packages/block-editor/src/hooks/align.js
+++ b/packages/block-editor/src/hooks/align.js
@@ -120,20 +120,17 @@ export const withToolbarControls = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
const blockEdit = ;
const { name: blockName } = props;
- // Compute the block valid alignments by taking into account,
- // if the theme supports wide alignments or not and the layout's
- // availble alignments. We do that for conditionally rendering
- // Slot.
+
+ const blockEditingMode = useBlockEditingMode();
+ if ( blockEditingMode !== 'default' ) {
+ return blockEdit;
+ }
+
const blockAllowedAlignments = getValidAlignments(
getBlockSupport( blockName, 'align' ),
hasBlockSupport( blockName, 'alignWide', true )
);
-
- const validAlignments = useAvailableAlignments(
- blockAllowedAlignments
- ).map( ( { name } ) => name );
- const blockEditingMode = useBlockEditingMode();
- if ( ! validAlignments.length || blockEditingMode !== 'default' ) {
+ if ( blockAllowedAlignments.length === 0 ) {
return blockEdit;
}
@@ -154,7 +151,7 @@ export const withToolbarControls = createHigherOrderComponent(
{ blockEdit }
@@ -164,6 +161,23 @@ export const withToolbarControls = createHigherOrderComponent(
'withToolbarControls'
);
+function BlockListBlockWithDataAlign( { block: BlockListBlock, props } ) {
+ const { name, attributes } = props;
+ const { align } = attributes;
+ const blockAllowedAlignments = getValidAlignments(
+ getBlockSupport( name, 'align' ),
+ hasBlockSupport( name, 'alignWide', true )
+ );
+ const validAlignments = useAvailableAlignments( blockAllowedAlignments );
+
+ let wrapperProps = props.wrapperProps;
+ if ( validAlignments.some( ( alignment ) => alignment.name === align ) ) {
+ wrapperProps = { ...wrapperProps, 'data-align': align };
+ }
+
+ return ;
+}
+
/**
* Override the default block element to add alignment wrapper props.
*
@@ -173,30 +187,18 @@ export const withToolbarControls = createHigherOrderComponent(
*/
export const withDataAlign = createHigherOrderComponent(
( BlockListBlock ) => ( props ) => {
- const { name, attributes } = props;
- const { align } = attributes;
- const blockAllowedAlignments = getValidAlignments(
- getBlockSupport( name, 'align' ),
- hasBlockSupport( name, 'alignWide', true )
- );
- const validAlignments = useAvailableAlignments(
- blockAllowedAlignments
- );
-
// If an alignment is not assigned, there's no need to go through the
// effort to validate or assign its value.
- if ( align === undefined ) {
+ if ( props.attributes.align === undefined ) {
return ;
}
- let wrapperProps = props.wrapperProps;
- if (
- validAlignments.some( ( alignment ) => alignment.name === align )
- ) {
- wrapperProps = { ...wrapperProps, 'data-align': align };
- }
-
- return ;
+ return (
+
+ );
},
'withDataAlign'
);