From c212e2cfbca7785f781788bef1587b5411b36244 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 27 Apr 2023 15:55:38 +0300 Subject: [PATCH] Add block variations transformation in block switcher --- .../block-variation-transformations-menu.js | 114 ++++++++++++++++++ .../src/components/block-switcher/index.js | 45 ++++++- 2 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 packages/block-editor/src/components/block-switcher/block-variation-transformations-menu.js diff --git a/packages/block-editor/src/components/block-switcher/block-variation-transformations-menu.js b/packages/block-editor/src/components/block-switcher/block-variation-transformations-menu.js new file mode 100644 index 00000000000000..f541f31e74a827 --- /dev/null +++ b/packages/block-editor/src/components/block-switcher/block-variation-transformations-menu.js @@ -0,0 +1,114 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { MenuGroup, MenuItem } from '@wordpress/components'; +import { + getBlockMenuDefaultClassName, + cloneBlock, + store as blocksStore, +} from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; +import { useState, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import BlockIcon from '../block-icon'; +import PreviewBlockPopover from './preview-block-popover'; + +export function useBlockVariationTransforms( { clientIds, blocks } ) { + const { activeBlockVariation, blockVariationTransformations } = useSelect( + ( select ) => { + const { + getBlockRootClientId, + getBlockAttributes, + canRemoveBlocks, + } = select( blockEditorStore ); + const { getActiveBlockVariation, getBlockVariations } = + select( blocksStore ); + const rootClientId = getBlockRootClientId( + Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds + ); + const canRemove = canRemoveBlocks( clientIds, rootClientId ); + // Only handle single selected blocks for now. + if ( blocks.length !== 1 || ! canRemove ) { + return; + } + const [ firstBlock ] = blocks; + return { + blockVariationTransformations: getBlockVariations( + firstBlock.name, + 'transform' + ), + activeBlockVariation: getActiveBlockVariation( + firstBlock.name, + getBlockAttributes( firstBlock.clientId ) + ), + }; + }, + [ clientIds, blocks ] + ); + const transformations = useMemo( () => { + return blockVariationTransformations?.filter( + ( { name } ) => name !== activeBlockVariation?.name + ); + }, [ blockVariationTransformations, activeBlockVariation ] ); + return transformations; +} + +const BlockVariationTransformationsMenu = ( { + transformations, + onSelect, + blocks, +} ) => { + const [ hoveredTransformItemName, setHoveredTransformItemName ] = + useState(); + return ( + + { hoveredTransformItemName && ( + name === hoveredTransformItemName + ).attributes + ) } + /> + ) } + { transformations?.map( ( item ) => ( + + ) ) } + + ); +}; + +function BlockVariationTranformationItem( { + item, + onSelect, + setHoveredTransformItemName, +} ) { + const { name, icon, title } = item; + return ( + { + event.preventDefault(); + onSelect( name ); + } } + onMouseLeave={ () => setHoveredTransformItemName( null ) } + onMouseEnter={ () => setHoveredTransformItemName( name ) } + > + + { title } + + ); +} + +export default BlockVariationTransformationsMenu; diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index 696b097757d335..a397d7c87c01a6 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -24,12 +24,17 @@ import { store as blockEditorStore } from '../../store'; import useBlockDisplayInformation from '../use-block-display-information'; import BlockIcon from '../block-icon'; import BlockTransformationsMenu from './block-transformations-menu'; +import { + useBlockVariationTransforms, + default as BlockVariationTransformationsMenu, +} from './block-variation-transformations-menu'; import BlockStylesMenu from './block-styles-menu'; import PatternTransformationsMenu from './pattern-transformations-menu'; import useBlockDisplayTitle from '../block-title/use-block-display-title'; export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { - const { replaceBlocks, multiSelect } = useDispatch( blockEditorStore ); + const { replaceBlocks, multiSelect, updateBlockAttributes } = + useDispatch( blockEditorStore ); const blockInformation = useBlockDisplayInformation( blocks[ 0 ].clientId ); const { possibleBlockTransformations, @@ -43,9 +48,9 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { getBlockRootClientId, getBlockTransformItems, __experimentalGetPatternTransformItems, + canRemoveBlocks, } = select( blockEditorStore ); const { getBlockStyles, getBlockType } = select( blocksStore ); - const { canRemoveBlocks } = select( blockEditorStore ); const rootClientId = getBlockRootClientId( Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds ); @@ -82,6 +87,11 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { [ clientIds, blocks, blockInformation?.icon ] ); + const blockVariationTransformations = useBlockVariationTransforms( { + clientIds, + blocks, + } ); + const blockTitle = useBlockDisplayTitle( { clientId: Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds, maximumLength: 35, @@ -105,6 +115,14 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { selectForMultipleBlocks( newBlocks ); } + function onBlockVariationTransform( name ) { + updateBlockAttributes( blocks[ 0 ].clientId, { + ...blockVariationTransformations.find( + ( { name: variationName } ) => variationName === name + ).attributes, + } ); + } + // Pattern transformation through the `Patterns` API. function onPatternTransform( transformedBlocks ) { replaceBlocks( clientIds, transformedBlocks ); @@ -118,8 +136,14 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { */ const hasPossibleBlockTransformations = !! possibleBlockTransformations.length && canRemove && ! isTemplate; + const hasPossibleBlockVariationTransformations = + !! blockVariationTransformations?.length; const hasPatternTransformation = !! patterns?.length && canRemove; - if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { + if ( + ! hasBlockStyles && + ! hasPossibleBlockTransformations && + ! hasPossibleBlockVariationTransformations + ) { return ( { const showDropDown = hasBlockStyles || hasPossibleBlockTransformations || + hasPossibleBlockVariationTransformations || hasPatternTransformation; return ( @@ -226,6 +251,20 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { } } /> ) } + { hasPossibleBlockVariationTransformations && ( + { + onBlockVariationTransform( + name + ); + onClose(); + } } + /> + ) } { hasBlockStyles && (