diff --git a/package-lock.json b/package-lock.json
index 5f31410669743..ed407df5473a7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17338,7 +17338,8 @@
"react-easy-crop": "^4.5.1",
"rememo": "^4.0.0",
"remove-accents": "^0.4.2",
- "traverse": "^0.6.6"
+ "traverse": "^0.6.6",
+ "uuid": "8.3.0"
}
},
"@wordpress/block-library": {
diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json
index 9874171ffc95c..bb67634256277 100644
--- a/packages/block-editor/package.json
+++ b/packages/block-editor/package.json
@@ -74,7 +74,8 @@
"react-easy-crop": "^4.5.1",
"rememo": "^4.0.0",
"remove-accents": "^0.4.2",
- "traverse": "^0.6.6"
+ "traverse": "^0.6.6",
+ "uuid": "8.3.0"
},
"peerDependencies": {
"react": "^18.0.0",
diff --git a/packages/block-editor/src/components/block-edit/index.js b/packages/block-editor/src/components/block-edit/index.js
index d24f8301c85fb..311ac80a3a407 100644
--- a/packages/block-editor/src/components/block-edit/index.js
+++ b/packages/block-editor/src/components/block-edit/index.js
@@ -1,14 +1,23 @@
+/**
+ * External dependencies
+ */
+import { v4 as uuid } from 'uuid';
+
/**
* WordPress dependencies
*/
-import { useMemo } from '@wordpress/element';
+import { useMemo, useEffect, useReducer } from '@wordpress/element';
import { hasBlockSupport } from '@wordpress/blocks';
+import { filters, addAction, removeAction } from '@wordpress/hooks';
+import { useSelect } from '@wordpress/data';
+
/**
* Internal dependencies
*/
import Edit from './edit';
import { BlockEditContextProvider, useBlockEditContext } from './context';
+import { store as blockEditorStore } from '../../store';
/**
* The `useBlockEditContext` hook provides information about the block this hook is being used in.
@@ -20,6 +29,79 @@ import { BlockEditContextProvider, useBlockEditContext } from './context';
*/
export { useBlockEditContext };
+// Please do not export this at the package level until we have a stable API.
+// Hook names must start with a letter.
+export const blockControlsFilterName = 'a' + uuid();
+
+function BlockControlFilters( props ) {
+ const { name, isSelected, clientId } = props;
+ const shouldDisplayControls = useSelect(
+ ( select ) => {
+ if ( isSelected ) {
+ return true;
+ }
+
+ const {
+ getBlockName,
+ isFirstMultiSelectedBlock,
+ getMultiSelectedBlockClientIds,
+ hasSelectedInnerBlock,
+ } = select( blockEditorStore );
+
+ if ( isFirstMultiSelectedBlock( clientId ) ) {
+ return getMultiSelectedBlockClientIds().every(
+ ( id ) => getBlockName( id ) === name
+ );
+ }
+
+ return (
+ hasBlockSupport(
+ getBlockName( clientId ),
+ '__experimentalExposeControlsToChildren',
+ false
+ ) && hasSelectedInnerBlock( clientId )
+ );
+ },
+ [ clientId, isSelected, name ]
+ );
+
+ const [ , forceRender ] = useReducer( () => [] );
+
+ useEffect( () => {
+ const namespace = 'core/block-edit/block-controls';
+
+ function onHooksUpdated( updatedHookName ) {
+ if ( updatedHookName === blockControlsFilterName ) {
+ forceRender();
+ }
+ }
+
+ addAction( 'hookRemoved', namespace, onHooksUpdated );
+ addAction( 'hookAdded', namespace, onHooksUpdated );
+
+ return () => {
+ removeAction( 'hookRemoved', namespace );
+ removeAction( 'hookAdded', namespace );
+ };
+ }, [] );
+
+ if ( ! shouldDisplayControls ) {
+ return;
+ }
+
+ const blockControlFilters = filters[ blockControlsFilterName ];
+
+ if ( ! blockControlFilters ) {
+ return;
+ }
+
+ return blockControlFilters.handlers.map(
+ ( { callback: Controls, namespace } ) => {
+ return ;
+ }
+ );
+}
+
export default function BlockEdit( props ) {
const {
name,
@@ -48,6 +130,7 @@ export default function BlockEdit( props ) {
// See https://reactjs.org/docs/context.html#caveats.
value={ useMemo( () => context, Object.values( context ) ) }
>
+
);
diff --git a/packages/block-editor/src/hooks/align.js b/packages/block-editor/src/hooks/align.js
index 8d5c7f850e89b..e3804d4c9cd8f 100644
--- a/packages/block-editor/src/hooks/align.js
+++ b/packages/block-editor/src/hooks/align.js
@@ -6,7 +6,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
-import { createHigherOrderComponent } from '@wordpress/compose';
+import { createHigherOrderComponent, ifCondition } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
import {
getBlockSupport,
@@ -21,6 +21,7 @@ import { useSelect } from '@wordpress/data';
import { BlockControls, BlockAlignmentControl } from '../components';
import useAvailableAlignments from '../components/block-alignment-control/use-available-alignments';
import { store as blockEditorStore } from '../store';
+import { blockControlsFilterName } from '../components/block-edit';
/**
* An array which includes all possible valid alignments,
@@ -113,64 +114,55 @@ export function addAttribute( settings ) {
* Override the default edit UI to include new toolbar controls for block
* alignment, if block defines support.
*
- * @param {Function} BlockEdit Original component.
- *
- * @return {Function} Wrapped component.
+ * @param {Object} props
*/
-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 blockAllowedAlignments = getValidAlignments(
- getBlockSupport( blockName, 'align' ),
- hasBlockSupport( blockName, 'alignWide', true )
- );
-
- const validAlignments = useAvailableAlignments(
- blockAllowedAlignments
- ).map( ( { name } ) => name );
- const isContentLocked = useSelect(
- ( select ) => {
- return select(
- blockEditorStore
- ).__unstableGetContentLockingParent( props.clientId );
- },
- [ props.clientId ]
- );
- if ( ! validAlignments.length || isContentLocked ) {
- return blockEdit;
- }
+export const ToolbarControls = ( props ) => {
+ 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 blockAllowedAlignments = getValidAlignments(
+ getBlockSupport( blockName, 'align' ),
+ hasBlockSupport( blockName, 'alignWide', true )
+ );
+
+ const validAlignments = useAvailableAlignments(
+ blockAllowedAlignments
+ ).map( ( { name } ) => name );
+ const isContentLocked = useSelect(
+ ( select ) => {
+ return select( blockEditorStore ).__unstableGetContentLockingParent(
+ props.clientId
+ );
+ },
+ [ props.clientId ]
+ );
+ if ( ! validAlignments.length || isContentLocked ) {
+ return null;
+ }
- const updateAlignment = ( nextAlign ) => {
- if ( ! nextAlign ) {
- const blockType = getBlockType( props.name );
- const blockDefaultAlign = blockType?.attributes?.align?.default;
- if ( blockDefaultAlign ) {
- nextAlign = '';
- }
+ const updateAlignment = ( nextAlign ) => {
+ if ( ! nextAlign ) {
+ const blockType = getBlockType( props.name );
+ const blockDefaultAlign = blockType?.attributes?.align?.default;
+ if ( blockDefaultAlign ) {
+ nextAlign = '';
}
- props.setAttributes( { align: nextAlign } );
- };
-
- return (
- <>
-
-
-
- { blockEdit }
- >
- );
- },
- 'withToolbarControls'
-);
+ }
+ props.setAttributes( { align: nextAlign } );
+ };
+
+ return (
+
+
+
+ );
+};
/**
* Override the default block element to add alignment wrapper props.
@@ -248,9 +240,11 @@ addFilter(
withDataAlign
);
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/editor/align/with-toolbar-controls',
- withToolbarControls
+ ifCondition( ( { name } ) => hasBlockSupport( name, 'align' ) )(
+ ToolbarControls
+ )
);
addFilter(
'blocks.getSaveContent.extraProps',
diff --git a/packages/block-editor/src/hooks/anchor.js b/packages/block-editor/src/hooks/anchor.js
index 65e227ab107eb..0035d821a8f42 100644
--- a/packages/block-editor/src/hooks/anchor.js
+++ b/packages/block-editor/src/hooks/anchor.js
@@ -5,13 +5,14 @@ import { addFilter } from '@wordpress/hooks';
import { PanelBody, TextControl, ExternalLink } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { hasBlockSupport } from '@wordpress/blocks';
-import { createHigherOrderComponent } from '@wordpress/compose';
import { Platform } from '@wordpress/element';
+import { ifCondition } from '@wordpress/compose';
/**
* Internal dependencies
*/
import { InspectorControls } from '../components';
+import { blockControlsFilterName } from '../components/block-edit';
/**
* Regular expression matching invalid anchor characters for replacement.
@@ -55,82 +56,72 @@ export function addAttribute( settings ) {
* Override the default edit UI to include a new block inspector control for
* assigning the anchor ID, if block supports anchor.
*
- * @param {WPComponent} BlockEdit Original component.
- *
- * @return {WPComponent} Wrapped component.
+ * @param {Object} props
*/
-export const withInspectorControl = createHigherOrderComponent(
- ( BlockEdit ) => {
- return ( props ) => {
- const hasAnchor = hasBlockSupport( props.name, 'anchor' );
-
- if ( hasAnchor && props.isSelected ) {
- const isWeb = Platform.OS === 'web';
- const textControl = (
-
- { __(
- 'Enter a word or two — without spaces — to make a unique web address just for this block, called an “anchor.” Then, you’ll be able to link directly to this section of your page.'
- ) }
+export const InspectorControl = ( props ) => {
+ if ( ! props.isSelected ) {
+ return null;
+ }
- { isWeb && (
-
- { __( 'Learn more about anchors' ) }
-
- ) }
- >
- }
- value={ props.attributes.anchor || '' }
- placeholder={ ! isWeb ? __( 'Add an anchor' ) : null }
- onChange={ ( nextValue ) => {
- nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
- props.setAttributes( {
- anchor: nextValue,
- } );
- } }
- autoCapitalize="none"
- autoComplete="off"
- />
- );
+ const isWeb = Platform.OS === 'web';
+ const textControl = (
+
+ { __(
+ 'Enter a word or two — without spaces — to make a unique web address just for this block, called an “anchor.” Then, you’ll be able to link directly to this section of your page.'
+ ) }
- return (
- <>
-
- { isWeb && (
-
- { textControl }
-
- ) }
- { /*
- * We plan to remove scoping anchors to 'core/heading' to support
- * anchors for all eligble blocks. Additionally we plan to explore
- * leveraging InspectorAdvancedControls instead of a custom
- * PanelBody title. https://github.com/WordPress/gutenberg/issues/28363
- */ }
- { ! isWeb && props.name === 'core/heading' && (
-
-
- { textControl }
-
-
- ) }
- >
- );
+ { isWeb && (
+
+ { __( 'Learn more about anchors' ) }
+
+ ) }
+ >
}
+ value={ props.attributes.anchor || '' }
+ placeholder={ ! isWeb ? __( 'Add an anchor' ) : null }
+ onChange={ ( nextValue ) => {
+ nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
+ props.setAttributes( {
+ anchor: nextValue,
+ } );
+ } }
+ autoCapitalize="none"
+ autoComplete="off"
+ />
+ );
- return ;
- };
- },
- 'withInspectorControl'
-);
+ return (
+ <>
+ { isWeb && (
+
+ { textControl }
+
+ ) }
+ { /*
+ * We plan to remove scoping anchors to 'core/heading' to support
+ * anchors for all eligble blocks. Additionally we plan to explore
+ * leveraging InspectorAdvancedControls instead of a custom
+ * PanelBody title. https://github.com/WordPress/gutenberg/issues/28363
+ */ }
+ { ! isWeb && props.name === 'core/heading' && (
+
+
+ { textControl }
+
+
+ ) }
+ >
+ );
+};
/**
* Override props assigned to save component to inject anchor ID, if block
@@ -153,9 +144,11 @@ export function addSaveProps( extraProps, blockType, attributes ) {
addFilter( 'blocks.registerBlockType', 'core/anchor/attribute', addAttribute );
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/editor/anchor/with-inspector-control',
- withInspectorControl
+ ifCondition( ( { name } ) => hasBlockSupport( name, 'anchor' ) )(
+ InspectorControl
+ )
);
addFilter(
'blocks.getSaveContent.extraProps',
diff --git a/packages/block-editor/src/hooks/content-lock-ui.js b/packages/block-editor/src/hooks/content-lock-ui.js
index 1fa8ffc29c858..463ab9f25ef4a 100644
--- a/packages/block-editor/src/hooks/content-lock-ui.js
+++ b/packages/block-editor/src/hooks/content-lock-ui.js
@@ -2,7 +2,6 @@
* WordPress dependencies
*/
import { ToolbarButton, MenuItem } from '@wordpress/components';
-import { createHigherOrderComponent } from '@wordpress/compose';
import { useDispatch, useSelect } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';
import { __ } from '@wordpress/i18n';
@@ -13,10 +12,7 @@ import { useEffect, useRef, useCallback } from '@wordpress/element';
*/
import { store as blockEditorStore } from '../store';
import { BlockControls, BlockSettingsMenuControls } from '../components';
-/**
- * External dependencies
- */
-import classnames from 'classnames';
+import { blockControlsFilterName } from '../components/block-edit';
function StopEditingAsBlocksOnOutsideSelect( {
clientId,
@@ -41,133 +37,117 @@ function StopEditingAsBlocksOnOutsideSelect( {
return null;
}
-export const withBlockControls = createHigherOrderComponent(
- ( BlockEdit ) => ( props ) => {
- const { getBlockListSettings, getSettings } =
- useSelect( blockEditorStore );
- const focusModeToRevert = useRef();
- const { templateLock, isLockedByParent, isEditingAsBlocks } = useSelect(
- ( select ) => {
- const {
- __unstableGetContentLockingParent,
- getTemplateLock,
- __unstableGetTemporarilyEditingAsBlocks,
- } = select( blockEditorStore );
- return {
- templateLock: getTemplateLock( props.clientId ),
- isLockedByParent: !! __unstableGetContentLockingParent(
- props.clientId
- ),
- isEditingAsBlocks:
- __unstableGetTemporarilyEditingAsBlocks() ===
- props.clientId,
- };
- },
- [ props.clientId ]
- );
+export const LockUIBlockControls = ( props ) => {
+ const { getBlockListSettings, getSettings } = useSelect( blockEditorStore );
+ const focusModeToRevert = useRef();
+ const { templateLock, isLockedByParent, isEditingAsBlocks } = useSelect(
+ ( select ) => {
+ const {
+ __unstableGetContentLockingParent,
+ getTemplateLock,
+ __unstableGetTemporarilyEditingAsBlocks,
+ } = select( blockEditorStore );
+ return {
+ templateLock: getTemplateLock( props.clientId ),
+ isLockedByParent: !! __unstableGetContentLockingParent(
+ props.clientId
+ ),
+ isEditingAsBlocks:
+ __unstableGetTemporarilyEditingAsBlocks() ===
+ props.clientId,
+ };
+ },
+ [ props.clientId ]
+ );
- const {
- updateSettings,
- updateBlockListSettings,
- __unstableSetTemporarilyEditingAsBlocks,
- } = useDispatch( blockEditorStore );
- const isContentLocked =
- ! isLockedByParent && templateLock === 'contentOnly';
- const {
- __unstableMarkNextChangeAsNotPersistent,
- updateBlockAttributes,
- } = useDispatch( blockEditorStore );
+ const {
+ updateSettings,
+ updateBlockListSettings,
+ __unstableSetTemporarilyEditingAsBlocks,
+ } = useDispatch( blockEditorStore );
+ const isContentLocked =
+ ! isLockedByParent && templateLock === 'contentOnly';
+ const { __unstableMarkNextChangeAsNotPersistent, updateBlockAttributes } =
+ useDispatch( blockEditorStore );
- const stopEditingAsBlock = useCallback( () => {
- __unstableMarkNextChangeAsNotPersistent();
- updateBlockAttributes( props.clientId, {
- templateLock: 'contentOnly',
- } );
- updateBlockListSettings( props.clientId, {
- ...getBlockListSettings( props.clientId ),
- templateLock: 'contentOnly',
- } );
- updateSettings( { focusMode: focusModeToRevert.current } );
- __unstableSetTemporarilyEditingAsBlocks();
- }, [
- props.clientId,
- focusModeToRevert,
- updateSettings,
- updateBlockListSettings,
- getBlockListSettings,
- __unstableMarkNextChangeAsNotPersistent,
- updateBlockAttributes,
- __unstableSetTemporarilyEditingAsBlocks,
- ] );
+ const stopEditingAsBlock = useCallback( () => {
+ __unstableMarkNextChangeAsNotPersistent();
+ updateBlockAttributes( props.clientId, {
+ templateLock: 'contentOnly',
+ } );
+ updateBlockListSettings( props.clientId, {
+ ...getBlockListSettings( props.clientId ),
+ templateLock: 'contentOnly',
+ } );
+ updateSettings( { focusMode: focusModeToRevert.current } );
+ __unstableSetTemporarilyEditingAsBlocks();
+ }, [
+ props.clientId,
+ focusModeToRevert,
+ updateSettings,
+ updateBlockListSettings,
+ getBlockListSettings,
+ __unstableMarkNextChangeAsNotPersistent,
+ updateBlockAttributes,
+ __unstableSetTemporarilyEditingAsBlocks,
+ ] );
- if ( ! isContentLocked && ! isEditingAsBlocks ) {
- return ;
- }
+ if ( ! isContentLocked && ! isEditingAsBlocks ) {
+ return null;
+ }
- return (
- <>
- { isEditingAsBlocks && ! isContentLocked && (
- <>
-
-
- {
- stopEditingAsBlock();
- } }
- >
- { __( 'Done' ) }
-
-
- >
- ) }
- { ! isEditingAsBlocks && isContentLocked && props.isSelected && (
-
- { ( { onClose } ) => (
-
- ) }
-
- ) }
-
+ { isEditingAsBlocks && ! isContentLocked && (
+ <>
+
+
+ {
+ stopEditingAsBlock();
+ } }
+ >
+ { __( 'Done' ) }
+
+
+ >
+ ) }
+ { ! isEditingAsBlocks && isContentLocked && props.isSelected && (
+
+ { ( { onClose } ) => (
+
) }
- />
- >
- );
- },
- 'withToolbarControls'
-);
+
+ ) }
+ >
+ );
+};
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/content-lock-ui/with-block-controls',
- withBlockControls
+ LockUIBlockControls
);
diff --git a/packages/block-editor/src/hooks/custom-class-name.js b/packages/block-editor/src/hooks/custom-class-name.js
index fa1a1cadc5712..58b7f4b450614 100644
--- a/packages/block-editor/src/hooks/custom-class-name.js
+++ b/packages/block-editor/src/hooks/custom-class-name.js
@@ -10,12 +10,13 @@ import { addFilter } from '@wordpress/hooks';
import { TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { hasBlockSupport } from '@wordpress/blocks';
-import { createHigherOrderComponent } from '@wordpress/compose';
+import { ifCondition } from '@wordpress/compose';
/**
* Internal dependencies
*/
import { InspectorControls } from '../components';
+import { blockControlsFilterName } from '../components/block-edit';
/**
* Filters registered block settings, extending attributes to include `className`.
@@ -43,50 +44,30 @@ export function addAttribute( settings ) {
* assigning the custom class name, if block supports custom class name.
* The control is displayed within the Advanced panel in the block inspector.
*
- * @param {WPComponent} BlockEdit Original component.
- *
- * @return {WPComponent} Wrapped component.
+ * @param {Object} props
*/
-export const withInspectorControl = createHigherOrderComponent(
- ( BlockEdit ) => {
- return ( props ) => {
- const hasCustomClassName = hasBlockSupport(
- props.name,
- 'customClassName',
- true
- );
- if ( hasCustomClassName && props.isSelected ) {
- return (
- <>
-
-
- {
- props.setAttributes( {
- className:
- nextValue !== ''
- ? nextValue
- : undefined,
- } );
- } }
- help={ __(
- 'Separate multiple classes with spaces.'
- ) }
- />
-
- >
- );
- }
+export const InspectorControl = ( props ) => {
+ if ( ! props.isSelected ) {
+ return null;
+ }
- return ;
- };
- },
- 'withInspectorControl'
-);
+ return (
+
+ {
+ props.setAttributes( {
+ className: nextValue !== '' ? nextValue : undefined,
+ } );
+ } }
+ help={ __( 'Separate multiple classes with spaces.' ) }
+ />
+
+ );
+};
/**
* Override props assigned to save component to inject the className, if block
@@ -158,9 +139,11 @@ addFilter(
addAttribute
);
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/editor/custom-class-name/with-inspector-control',
- withInspectorControl
+ ifCondition( ( { name } ) =>
+ hasBlockSupport( name, 'customClassName', true )
+ )( InspectorControl )
);
addFilter(
'blocks.getSaveContent.extraProps',
diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js
index b56d9f64b4e83..c73351469b343 100644
--- a/packages/block-editor/src/hooks/duotone.js
+++ b/packages/block-editor/src/hooks/duotone.js
@@ -9,7 +9,11 @@ import namesPlugin from 'colord/plugins/names';
* WordPress dependencies
*/
import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
-import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
+import {
+ createHigherOrderComponent,
+ ifCondition,
+ useInstanceId,
+} from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
import { useMemo, useContext, createPortal } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
@@ -29,6 +33,7 @@ import {
__unstableDuotoneUnsetStylesheet as DuotoneUnsetStylesheet,
} from '../components/duotone';
import { store as blockEditorStore } from '../store';
+import { blockControlsFilterName } from '../components/block-edit';
const EMPTY_ARRAY = [];
@@ -183,40 +188,24 @@ function addDuotoneAttributes( settings ) {
* Override the default edit UI to include toolbar controls for duotone if the
* block supports duotone.
*
- * @param {Function} BlockEdit Original component.
- *
- * @return {Function} Wrapped component.
+ * @param {Object} props
*/
-const withDuotoneControls = createHigherOrderComponent(
- ( BlockEdit ) => ( props ) => {
- const hasDuotoneSupport = hasBlockSupport(
- props.name,
- 'color.__experimentalDuotone'
- );
- const isContentLocked = useSelect(
- ( select ) => {
- return select(
- blockEditorStore
- ).__unstableGetContentLockingParent( props.clientId );
- },
- [ props.clientId ]
- );
+const DuotoneControls = ( props ) => {
+ const isContentLocked = useSelect(
+ ( select ) => {
+ return select( blockEditorStore ).__unstableGetContentLockingParent(
+ props.clientId
+ );
+ },
+ [ props.clientId ]
+ );
- // CAUTION: code added before this line will be executed
- // for all blocks, not just those that support duotone. Code added
- // above this line should be carefully evaluated for its impact on
- // performance.
- return (
- <>
- { hasDuotoneSupport && ! isContentLocked && (
-
- ) }
-
- >
- );
- },
- 'withDuotoneControls'
-);
+ // CAUTION: code added before this line will be executed
+ // for all blocks, not just those that support duotone. Code added
+ // above this line should be carefully evaluated for its impact on
+ // performance.
+ return ! isContentLocked && ;
+};
/**
* Function that scopes a selector with another one. This works a bit like
@@ -338,9 +327,11 @@ addFilter(
addDuotoneAttributes
);
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/editor/duotone/with-editor-controls',
- withDuotoneControls
+ ifCondition( ( { name } ) =>
+ hasBlockSupport( name, 'color.__experimentalDuotone' )
+ )( DuotoneControls )
);
addFilter(
'editor.BlockListBlock',
diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js
index aa2d278aee582..b45964c087e6b 100644
--- a/packages/block-editor/src/hooks/layout.js
+++ b/packages/block-editor/src/hooks/layout.js
@@ -7,7 +7,11 @@ import { kebabCase } from 'lodash';
/**
* WordPress dependencies
*/
-import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
+import {
+ createHigherOrderComponent,
+ ifCondition,
+ useInstanceId,
+} from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
@@ -29,6 +33,7 @@ import useSetting from '../components/use-setting';
import { LayoutStyle } from '../components/block-list/layout';
import BlockList from '../components/block-list';
import { getLayoutType, getLayoutTypes } from '../layouts';
+import { blockControlsFilterName } from '../components/block-edit';
const layoutBlockSupportKey = '__experimentalLayout';
@@ -319,29 +324,6 @@ export function addAttribute( settings ) {
return settings;
}
-/**
- * Override the default edit UI to include layout controls
- *
- * @param {Function} BlockEdit Original component.
- *
- * @return {Function} Wrapped component.
- */
-export const withInspectorControls = createHigherOrderComponent(
- ( BlockEdit ) => ( props ) => {
- const { name: blockName } = props;
- const supportLayout = hasBlockSupport(
- blockName,
- layoutBlockSupportKey
- );
-
- return [
- supportLayout && ,
- ,
- ];
- },
- 'withInspectorControls'
-);
-
/**
* Override the default block element to add the layout styles.
*
@@ -500,7 +482,9 @@ addFilter(
withChildLayoutStyles
);
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/editor/layout/with-inspector-controls',
- withInspectorControls
+ ifCondition( ( { name } ) =>
+ hasBlockSupport( name, layoutBlockSupportKey )
+ )( LayoutPanel )
);
diff --git a/packages/block-editor/src/hooks/layout.native.js b/packages/block-editor/src/hooks/layout.native.js
index 2e9a873bdd1ec..46ea0eb8bf96a 100644
--- a/packages/block-editor/src/hooks/layout.native.js
+++ b/packages/block-editor/src/hooks/layout.native.js
@@ -7,6 +7,7 @@ import { removeFilter } from '@wordpress/hooks';
* Internal dependencies
*/
import './layout.js';
+import { blockControlsFilterName } from '../components/block-edit';
// This filter is removed because layout styles shouldn't be added
// until layout types are supported in the native version.
@@ -18,6 +19,6 @@ removeFilter(
// This filter is removed because the layout controls shouldn't be
// enabled until layout types are supported in the native version.
removeFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/editor/layout/with-inspector-controls'
);
diff --git a/packages/block-editor/src/hooks/position.js b/packages/block-editor/src/hooks/position.js
index 2c5589c1920bb..4779c8e4179eb 100644
--- a/packages/block-editor/src/hooks/position.js
+++ b/packages/block-editor/src/hooks/position.js
@@ -12,7 +12,11 @@ import {
BaseControl,
privateApis as componentsPrivateApis,
} from '@wordpress/components';
-import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
+import {
+ createHigherOrderComponent,
+ ifCondition,
+ useInstanceId,
+} from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import {
useContext,
@@ -311,29 +315,17 @@ export function PositionPanel( props ) {
/**
* Override the default edit UI to include position controls.
*
- * @param {Function} BlockEdit Original component.
- *
- * @return {Function} Wrapped component.
+ * @param {Object} props
*/
-export const withInspectorControls = createHigherOrderComponent(
- ( BlockEdit ) => ( props ) => {
- const { name: blockName } = props;
- const positionSupport = hasBlockSupport(
- blockName,
- POSITION_SUPPORT_KEY
- );
- const showPositionControls =
- positionSupport && ! useIsPositionDisabled( props );
-
- return [
- showPositionControls && (
-
- ),
- ,
- ];
- },
- 'withInspectorControls'
-);
+export const PositionInspectorControls = ( props ) => {
+ const isPositionDisabled = useIsPositionDisabled( props );
+
+ if ( isPositionDisabled ) {
+ return null;
+ }
+
+ return ;
+};
/**
* Override the default block element to add the position styles.
@@ -395,7 +387,9 @@ addFilter(
withPositionStyles
);
addFilter(
- 'editor.BlockEdit',
+ 'editor.BlockControls',
'core/editor/position/with-inspector-controls',
- withInspectorControls
+ ifCondition( ( { name } ) =>
+ hasBlockSupport( name, POSITION_SUPPORT_KEY )
+ )( PositionInspectorControls )
);
diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js
index b6fe7b8188c2b..5e264121c036b 100644
--- a/packages/block-editor/src/hooks/style.js
+++ b/packages/block-editor/src/hooks/style.js
@@ -32,8 +32,8 @@ import {
SPACING_SUPPORT_KEY,
DimensionsPanel,
} from './dimensions';
-import useDisplayBlockControls from '../components/use-display-block-controls';
import { shouldSkipSerialization } from './utils';
+import { blockControlsFilterName } from '../components/block-edit';
const styleSupportKeys = [
...TYPOGRAPHY_SUPPORT_KEYS,
@@ -340,30 +340,18 @@ export function addEditProps( settings ) {
* Override the default edit UI to include new inspector controls for
* all the custom styles configs.
*
- * @param {Function} BlockEdit Original component.
- *
- * @return {Function} Wrapped component.
+ * @param {Object} props
*/
-export const withBlockControls = createHigherOrderComponent(
- ( BlockEdit ) => ( props ) => {
- const shouldDisplayControls = useDisplayBlockControls();
-
- return (
- <>
- { shouldDisplayControls && (
- <>
-
-
-
-
- >
- ) }
-
- >
- );
- },
- 'withToolbarControls'
-);
+export const StyleBlockControls = ( props ) => {
+ return (
+ <>
+
+
+
+
+ >
+ );
+};
/**
* Override the default block element to include elements styles.
@@ -468,9 +456,9 @@ addFilter(
);
addFilter(
- 'editor.BlockEdit',
+ blockControlsFilterName,
'core/style/with-block-controls',
- withBlockControls
+ StyleBlockControls
);
addFilter(
diff --git a/packages/block-editor/src/hooks/test/align.js b/packages/block-editor/src/hooks/test/align.js
index d6a9b3aba65ce..35cda29bf90af 100644
--- a/packages/block-editor/src/hooks/test/align.js
+++ b/packages/block-editor/src/hooks/test/align.js
@@ -22,7 +22,7 @@ import BlockEdit from '../../components/block-edit';
import BlockEditorProvider from '../../components/provider';
import {
getValidAlignments,
- withToolbarControls,
+ ToolbarControls,
withDataAlign,
addAssignedAlign,
} from '../align';
@@ -157,7 +157,7 @@ describe( 'align', () => {
} );
} );
- describe( 'withToolbarControls', () => {
+ describe( 'ToolbarControls', () => {
const componentProps = {
name: 'core/foo',
attributes: {},
@@ -167,14 +167,10 @@ describe( 'align', () => {
it( 'should do nothing if no valid alignments', () => {
registerBlockType( 'core/foo', blockSettings );
- const EnhancedComponent = withToolbarControls(
- ( { wrapperProps } ) =>
- );
-
render(
-
+
@@ -197,14 +193,10 @@ describe( 'align', () => {
},
} );
- const EnhancedComponent = withToolbarControls(
- ( { wrapperProps } ) =>
- );
-
render(
-
+
diff --git a/packages/block-library/src/query/index.js b/packages/block-library/src/query/index.js
index baf58470b76ac..e3682edf506dd 100644
--- a/packages/block-library/src/query/index.js
+++ b/packages/block-library/src/query/index.js
@@ -27,6 +27,8 @@ export const settings = {
};
export const init = () => {
+ // This is a temporary solution so the link is displayed at the top.
+ // See https://github.com/WordPress/gutenberg/pull/31833/files#r634291993.
addFilter( 'editor.BlockEdit', 'core/query', queryInspectorControls );
return initBlock( { name, metadata, settings } );