diff --git a/packages/block-editor/src/components/block-edit/edit.js b/packages/block-editor/src/components/block-edit/edit.js
index 31344b54337935..89d156c7f4f49b 100644
--- a/packages/block-editor/src/components/block-edit/edit.js
+++ b/packages/block-editor/src/components/block-edit/edit.js
@@ -13,6 +13,10 @@ import {
getBlockType,
} from '@wordpress/blocks';
import { useContext, useMemo } from '@wordpress/element';
+/**
+ * Internal dependencies
+ */
+import { InspectorControls, BlockControls } from '../../components';
/**
* Internal dependencies
@@ -37,12 +41,31 @@ const Edit = ( props ) => {
return null;
}
+ const controls = [];
+
+ if ( blockType.attributeControls?.length > 0 ) {
+ for ( const control of blockType.attributeControls ) {
+ const Wrapper =
+ control.type === 'toolbar' ? BlockControls : InspectorControls;
+
+ controls.push(
+
+
+
+ );
+ }
+ }
+
// `edit` and `save` are functions or components describing the markup
// with which a block is displayed. If `blockType` is valid, assign
// them preferentially as the render value for the block.
const Component = blockType.edit || blockType.save;
- return ;
+ return [
+
+ { controls }
+ ,
+ ];
};
const EditWithFilters = withFilters( 'editor.BlockEdit' )( Edit );
diff --git a/packages/block-library/src/paragraph/edit.js b/packages/block-library/src/paragraph/edit.js
index c3e434e93b714c..32d6cded3ce5b3 100644
--- a/packages/block-library/src/paragraph/edit.js
+++ b/packages/block-library/src/paragraph/edit.js
@@ -6,23 +6,9 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
-import { __, _x, isRTL } from '@wordpress/i18n';
-import {
- ToolbarButton,
- ToggleControl,
- __experimentalToolsPanelItem as ToolsPanelItem,
-} from '@wordpress/components';
-import {
- AlignmentControl,
- BlockControls,
- InspectorControls,
- RichText,
- useBlockProps,
- useSettings,
- useBlockEditingMode,
-} from '@wordpress/block-editor';
+import { __, isRTL } from '@wordpress/i18n';
+import { RichText, useBlockProps } from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
-import { formatLtr } from '@wordpress/icons';
/**
* Internal dependencies
@@ -31,67 +17,10 @@ import { useOnEnter } from './use-enter';
const name = 'core/paragraph';
-function ParagraphRTLControl( { direction, setDirection } ) {
- return (
- isRTL() && (
- {
- setDirection( direction === 'ltr' ? undefined : 'ltr' );
- } }
- />
- )
- );
-}
-
function hasDropCapDisabled( align ) {
return align === ( isRTL() ? 'left' : 'right' ) || align === 'center';
}
-function DropCapControl( { clientId, attributes, setAttributes } ) {
- // Please do not add a useSelect call to the paragraph block unconditionally.
- // Every useSelect added to a (frequently used) block will degrade load
- // and type performance. By moving it within InspectorControls, the subscription is
- // now only added for the selected block(s).
- const [ isDropCapFeatureEnabled ] = useSettings( 'typography.dropCap' );
-
- if ( ! isDropCapFeatureEnabled ) {
- return null;
- }
-
- const { align, dropCap } = attributes;
-
- let helpText;
- if ( hasDropCapDisabled( align ) ) {
- helpText = __( 'Not available for aligned text.' );
- } else if ( dropCap ) {
- helpText = __( 'Showing large initial letter.' );
- } else {
- helpText = __( 'Toggle to show a large initial letter.' );
- }
-
- return (
- !! dropCap }
- label={ __( 'Drop cap' ) }
- onDeselect={ () => setAttributes( { dropCap: undefined } ) }
- resetAllFilter={ () => ( { dropCap: undefined } ) }
- panelId={ clientId }
- >
- setAttributes( { dropCap: ! dropCap } ) }
- help={ helpText }
- disabled={ hasDropCapDisabled( align ) ? true : false }
- />
-
- );
-}
-
function ParagraphBlock( {
attributes,
mergeBlocks,
@@ -109,81 +38,49 @@ function ParagraphBlock( {
} ),
style: { direction },
} );
- const blockEditingMode = useBlockEditingMode();
-
return (
- <>
- { blockEditingMode === 'default' && (
-
-
- setAttributes( {
- align: newAlign,
- dropCap: hasDropCapDisabled( newAlign )
- ? false
- : dropCap,
- } )
- }
- />
-
- setAttributes( { direction: newDirection } )
- }
- />
-
- ) }
-
-
-
-
- setAttributes( { content: newContent } )
+
+ setAttributes( { content: newContent } )
+ }
+ onSplit={ ( value, isOriginal ) => {
+ let newAttributes;
+
+ if ( isOriginal || value ) {
+ newAttributes = {
+ ...attributes,
+ content: value,
+ };
}
- onSplit={ ( value, isOriginal ) => {
- let newAttributes;
-
- if ( isOriginal || value ) {
- newAttributes = {
- ...attributes,
- content: value,
- };
- }
- const block = createBlock( name, newAttributes );
+ const block = createBlock( name, newAttributes );
- if ( isOriginal ) {
- block.clientId = clientId;
- }
-
- return block;
- } }
- onMerge={ mergeBlocks }
- onReplace={ onReplace }
- onRemove={ onRemove }
- aria-label={
- RichText.isEmpty( content )
- ? __(
- 'Empty block; start writing or type forward slash to choose a block'
- )
- : __( 'Block: Paragraph' )
+ if ( isOriginal ) {
+ block.clientId = clientId;
}
- data-empty={ RichText.isEmpty( content ) }
- placeholder={ placeholder || __( 'Type / to choose a block' ) }
- data-custom-placeholder={ placeholder ? true : undefined }
- __unstableEmbedURLOnPaste
- __unstableAllowPrefixTransformations
- />
- >
+
+ return block;
+ } }
+ onMerge={ mergeBlocks }
+ onReplace={ onReplace }
+ onRemove={ onRemove }
+ aria-label={
+ RichText.isEmpty( content )
+ ? __(
+ 'Empty block; start writing or type forward slash to choose a block'
+ )
+ : __( 'Block: Paragraph' )
+ }
+ data-empty={ RichText.isEmpty( content ) }
+ placeholder={ placeholder || __( 'Type / to choose a block' ) }
+ data-custom-placeholder={ placeholder ? true : undefined }
+ __unstableEmbedURLOnPaste
+ __unstableAllowPrefixTransformations
+ />
);
}
diff --git a/packages/block-library/src/paragraph/index.js b/packages/block-library/src/paragraph/index.js
index 715fb35ec05ab1..82c5257d58bde6 100644
--- a/packages/block-library/src/paragraph/index.js
+++ b/packages/block-library/src/paragraph/index.js
@@ -1,8 +1,14 @@
/**
* WordPress dependencies
*/
-import { __ } from '@wordpress/i18n';
-import { paragraph as icon } from '@wordpress/icons';
+import { __, _x, isRTL } from '@wordpress/i18n';
+import { paragraph as icon, formatLtr } from '@wordpress/icons';
+import { AlignmentControl, useSettings } from '@wordpress/block-editor';
+import {
+ ToolbarButton,
+ ToggleControl,
+ __experimentalToolsPanelItem as ToolsPanelItem,
+} from '@wordpress/components';
/**
* Internal dependencies
@@ -18,6 +24,10 @@ const { name } = metadata;
export { metadata, name };
+function hasDropCapDisabled( align ) {
+ return align === ( isRTL() ? 'left' : 'right' ) || align === 'center';
+}
+
export const settings = {
icon,
example: {
@@ -54,6 +64,101 @@ export const settings = {
},
edit,
save,
+ attributeControls: [
+ {
+ key: 'align',
+ type: 'toolbar',
+ group: 'block',
+ Control( { attributes, setAttributes } ) {
+ const { align, dropCap } = attributes;
+ return (
+
+ setAttributes( {
+ align: newAlign,
+ dropCap: hasDropCapDisabled( newAlign )
+ ? false
+ : dropCap,
+ } )
+ }
+ />
+ );
+ },
+ },
+ {
+ key: 'direction',
+ type: 'toolbar',
+ group: 'block',
+ Control( { attributes, setAttributes } ) {
+ const { direction } = attributes;
+ return (
+ isRTL() && (
+ {
+ setAttributes( {
+ direction:
+ direction === 'ltr' ? undefined : 'ltr',
+ } );
+ } }
+ />
+ )
+ );
+ },
+ },
+ {
+ key: 'dropCap',
+ type: 'inspector',
+ group: 'typography',
+ Control( { attributes, setAttributes, clientId } ) {
+ const [ isDropCapFeatureEnabled ] =
+ useSettings( 'typography.dropCap' );
+
+ if ( ! isDropCapFeatureEnabled ) {
+ return null;
+ }
+
+ const { align, dropCap } = attributes;
+
+ let helpText;
+ if ( hasDropCapDisabled( align ) ) {
+ helpText = __( 'Not available for aligned text.' );
+ } else if ( dropCap ) {
+ helpText = __( 'Showing large initial letter.' );
+ } else {
+ helpText = __( 'Toggle to show a large initial letter.' );
+ }
+
+ return (
+ !! dropCap }
+ label={ __( 'Drop cap' ) }
+ onDeselect={ () =>
+ setAttributes( { dropCap: undefined } )
+ }
+ resetAllFilter={ () => ( { dropCap: undefined } ) }
+ panelId={ clientId }
+ >
+
+ setAttributes( { dropCap: ! dropCap } )
+ }
+ help={ helpText }
+ disabled={
+ hasDropCapDisabled( align ) ? true : false
+ }
+ />
+
+ );
+ },
+ },
+ ],
};
export const init = () => initBlock( { name, metadata, settings } );