From 2b135933a9a0a5cca8ff5ca414dafc49a2bd7c92 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 16:56:40 +0200 Subject: [PATCH] refactor BlockSwitcher to function component and use the new hook --- .../block-switcher/block-styles-menu.js | 36 ++ .../src/components/block-switcher/index.js | 348 +++++++----------- .../block-switcher/preview-block-popover.js | 57 +++ 3 files changed, 221 insertions(+), 220 deletions(-) create mode 100644 packages/block-editor/src/components/block-switcher/block-styles-menu.js create mode 100644 packages/block-editor/src/components/block-switcher/preview-block-popover.js diff --git a/packages/block-editor/src/components/block-switcher/block-styles-menu.js b/packages/block-editor/src/components/block-switcher/block-styles-menu.js new file mode 100644 index 00000000000000..01d47a66e462f1 --- /dev/null +++ b/packages/block-editor/src/components/block-switcher/block-styles-menu.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { MenuGroup } from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import BlockStyles from '../block-styles'; +import PreviewBlockPopover from './preview-block-popover'; + +const BlockStylesMenu = ( { hoveredBlock, onSwitch } ) => { + const [ hoveredClassName, setHoveredClassName ] = useState(); + return ( + + { hoveredClassName && ( + + ) } + + + ); +}; +export default BlockStylesMenu; diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index e1444dcde54689..6694ac1795092f 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { castArray, filter, mapKeys, orderBy, uniq, map } from 'lodash'; +import { castArray, filter, mapKeys, orderBy, uniq } from 'lodash'; /** * WordPress dependencies @@ -12,247 +12,155 @@ import { ToolbarButton, ToolbarGroup, ToolbarItem, - MenuGroup, - Popover, } from '@wordpress/components'; import { - getBlockType, getPossibleBlockTransformations, switchToBlockType, - cloneBlock, - getBlockFromExample, store as blocksStore, } from '@wordpress/blocks'; -import { Component } from '@wordpress/element'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useSelect, useDispatch } from '@wordpress/data'; import { stack } from '@wordpress/icons'; /** * Internal dependencies */ import BlockIcon from '../block-icon'; -import BlockStyles from '../block-styles'; -import BlockPreview from '../block-preview'; import BlockTransformationsMenu from './block-transformations-menu'; +import BlockStylesMenu from './block-styles-menu'; +import useMatchingVariationInformation from '../use-matching-variation-information'; -function PreviewBlockPopover( { hoveredBlock, hoveredClassName } ) { - const hoveredBlockType = getBlockType( hoveredBlock.name ); - return ( -
-
- -
-
- { __( 'Preview' ) } -
- -
-
-
-
+const BlockSwitcher = ( { clientIds } ) => { + const blocks = useSelect( + ( select ) => + select( 'core/block-editor' ).getBlocksByClientId( clientIds ), + [ clientIds ] ); -} - -export class BlockSwitcher extends Component { - constructor() { - super( ...arguments ); - this.state = { - hoveredClassName: null, - }; - this.onHoverClassName = this.onHoverClassName.bind( this ); - } - - onHoverClassName( className ) { - this.setState( { hoveredClassName: className } ); - } - - render() { - const { - blocks, - onTransform, - inserterItems, - hasBlockStyles, - } = this.props; - const { hoveredClassName } = this.state; - - if ( ! Array.isArray( blocks ) || ! blocks.length ) { - return null; - } + return blocks?.length ? ( + + ) : null; +}; - const [ hoveredBlock ] = blocks; - const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); - const possibleBlockTransformations = orderBy( - filter( - getPossibleBlockTransformations( blocks ), - ( block ) => block && !! itemsByName[ block.name ] - ), - ( block ) => itemsByName[ block.name ].frecency, - 'desc' - ); - - // When selection consists of blocks of multiple types, display an - // appropriate icon to communicate the non-uniformity. - const isSelectionOfSameType = - uniq( map( blocks, 'name' ) ).length === 1; - - const blockIconProps = isSelectionOfSameType - ? { clientId: hoveredBlock.clientId } - : { icon: stack }; - - const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; - - if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { - return ( - - } - /> - +const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { + const { replaceBlocks } = useDispatch( 'core/block-editor' ); + const { inserterItems, hasBlockStyles } = useSelect( + ( select ) => { + const { getBlockRootClientId, getInserterItems } = select( + 'core/block-editor' + ); + const { getBlockStyles } = select( blocksStore ); + const rootClientId = getBlockRootClientId( + castArray( clientIds )[ 0 ] ); - } + const firstBlock = blocks.length === 1 ? blocks[ 0 ] : null; + const styles = firstBlock && getBlockStyles( firstBlock.name ); + return { + inserterItems: getInserterItems( rootClientId ), + hasBlockStyles: !! styles?.length, + }; + }, + [ clientIds, blocks ] + ); + const [ hoveredBlock ] = blocks; + const blockInformation = useMatchingVariationInformation( + hoveredBlock.clientId + ); + const onTransform = ( name ) => + replaceBlocks( clientIds, switchToBlockType( blocks, name ) ); - const blockSwitcherLabel = - 1 === blocks.length - ? __( 'Change block type or style' ) - : sprintf( - /* translators: %s: number of blocks. */ - _n( - 'Change type of %d block', - 'Change type of %d blocks', - blocks.length - ), - blocks.length - ); + // When selection consists of blocks of multiple types, display an + // appropriate icon to communicate the non-uniformity. + const isSelectionOfSameType = + uniq( blocks.map( ( { name } ) => name ) ).length === 1; + const icon = isSelectionOfSameType ? blockInformation.icon : stack; + const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); + const possibleBlockTransformations = orderBy( + filter( + getPossibleBlockTransformations( blocks ), + ( block ) => block && !! itemsByName[ block.name ] + ), + ( block ) => itemsByName[ block.name ].frecency, + 'desc' + ); + const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; + if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { return ( - - { ( toggleProps ) => ( - - } - toggleProps={ toggleProps } - menuProps={ { orientation: 'both' } } - > - { ( { onClose } ) => - ( hasBlockStyles || - hasPossibleBlockTransformations ) && ( -
- { hasPossibleBlockTransformations && ( - { - onTransform( blocks, name ); - onClose(); - } } - /> - ) } - { hasBlockStyles && ( - - { hoveredClassName !== null && ( - - ) } - - - ) } -
- ) - } -
- ) } -
+ } + />
); } -} -export default compose( - withSelect( ( select, { clientIds } ) => { - const { - getBlocksByClientId, - getBlockRootClientId, - getInserterItems, - } = select( 'core/block-editor' ); - const { getBlockStyles } = select( blocksStore ); - const rootClientId = getBlockRootClientId( - castArray( clientIds )[ 0 ] - ); - const blocks = getBlocksByClientId( clientIds ); - const firstBlock = blocks && blocks.length === 1 ? blocks[ 0 ] : null; - const styles = firstBlock && getBlockStyles( firstBlock.name ); - return { - blocks, - inserterItems: getInserterItems( rootClientId ), - hasBlockStyles: styles && styles.length > 0, - }; - } ), - withDispatch( ( dispatch, ownProps ) => ( { - onTransform( blocks, name ) { - dispatch( 'core/block-editor' ).replaceBlocks( - ownProps.clientIds, - switchToBlockType( blocks, name ) - ); - }, - } ) ) -)( BlockSwitcher ); + const blockSwitcherLabel = + 1 === blocks.length + ? __( 'Change block type or style' ) + : sprintf( + /* translators: %s: number of blocks. */ + _n( + 'Change type of %d block', + 'Change type of %d blocks', + blocks.length + ), + blocks.length + ); + + return ( + + + { ( toggleProps ) => ( + + } + toggleProps={ toggleProps } + menuProps={ { orientation: 'both' } } + > + { ( { onClose } ) => + ( hasBlockStyles || + hasPossibleBlockTransformations ) && ( +
+ { hasPossibleBlockTransformations && ( + { + onTransform( name ); + onClose(); + } } + /> + ) } + { hasBlockStyles && ( + + ) } +
+ ) + } +
+ ) } +
+
+ ); +}; + +export default BlockSwitcher; diff --git a/packages/block-editor/src/components/block-switcher/preview-block-popover.js b/packages/block-editor/src/components/block-switcher/preview-block-popover.js new file mode 100644 index 00000000000000..4e8e0cd0b66842 --- /dev/null +++ b/packages/block-editor/src/components/block-switcher/preview-block-popover.js @@ -0,0 +1,57 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Popover } from '@wordpress/components'; +import { + getBlockType, + cloneBlock, + getBlockFromExample, +} from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import BlockPreview from '../block-preview'; + +export default function PreviewBlockPopover( { + hoveredBlock, + hoveredClassName, +} ) { + const hoveredBlockType = getBlockType( hoveredBlock.name ); + return ( +
+
+ +
+
+ { __( 'Preview' ) } +
+ +
+
+
+
+ ); +}