diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index eaffc0a875ca3b..9e9c1ef140c76a 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -1263,7 +1263,7 @@ Action that hides the insertion point. ### insertAfterBlock -Action that inserts an empty block after a given block. +Action that inserts a default block after a given block. _Parameters_ @@ -1271,7 +1271,7 @@ _Parameters_ ### insertBeforeBlock -Action that inserts an empty block before a given block. +Action that inserts a default block before a given block. _Parameters_ diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js index 5d942d2b25c708..760f0f4daabde9 100644 --- a/packages/block-editor/src/components/block-actions/index.js +++ b/packages/block-editor/src/components/block-actions/index.js @@ -20,42 +20,55 @@ export default function BlockActions( { children, __experimentalUpdateSelection: updateSelection, } ) { - const { - canInsertBlockType, - getBlockRootClientId, - getBlocksByClientId, - canMoveBlocks, - canRemoveBlocks, - } = useSelect( blockEditorStore ); const { getDefaultBlockName, getGroupingBlockName } = useSelect( blocksStore ); - - const blocks = getBlocksByClientId( clientIds ); - const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - - const canCopyStyles = blocks.every( ( block ) => { - return ( - !! block && - ( hasBlockSupport( block.name, 'color' ) || - hasBlockSupport( block.name, 'typography' ) ) - ); - } ); - - const canDuplicate = blocks.every( ( block ) => { - return ( - !! block && - hasBlockSupport( block.name, 'multiple', true ) && - canInsertBlockType( block.name, rootClientId ) - ); - } ); - - const canInsertDefaultBlock = canInsertBlockType( - getDefaultBlockName(), - rootClientId + const selected = useSelect( + ( select ) => { + const { + canInsertBlockType, + getBlockRootClientId, + getBlocksByClientId, + getDirectInsertBlock, + canMoveBlocks, + canRemoveBlocks, + } = select( blockEditorStore ); + + const blocks = getBlocksByClientId( clientIds ); + const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); + const canInsertDefaultBlock = canInsertBlockType( + getDefaultBlockName(), + rootClientId + ); + const directInsertBlock = rootClientId + ? getDirectInsertBlock( rootClientId ) + : null; + + return { + canMove: canMoveBlocks( clientIds, rootClientId ), + canRemove: canRemoveBlocks( clientIds, rootClientId ), + canInsertBlock: canInsertDefaultBlock || !! directInsertBlock, + canCopyStyles: blocks.every( ( block ) => { + return ( + !! block && + ( hasBlockSupport( block.name, 'color' ) || + hasBlockSupport( block.name, 'typography' ) ) + ); + } ), + canDuplicate: blocks.every( ( block ) => { + return ( + !! block && + hasBlockSupport( block.name, 'multiple', true ) && + canInsertBlockType( block.name, rootClientId ) + ); + } ), + }; + }, + [ clientIds, getDefaultBlockName ] ); + const { getBlocksByClientId, getBlocks } = useSelect( blockEditorStore ); - const canMove = canMoveBlocks( clientIds, rootClientId ); - const canRemove = canRemoveBlocks( clientIds, rootClientId ); + const { canMove, canRemove, canInsertBlock, canCopyStyles, canDuplicate } = + selected; const { removeBlocks, @@ -75,11 +88,9 @@ export default function BlockActions( { return children( { canCopyStyles, canDuplicate, - canInsertDefaultBlock, + canInsertBlock, canMove, canRemove, - rootClientId, - blocks, onDuplicate() { return duplicateBlocks( clientIds, updateSelection ); }, @@ -104,14 +115,17 @@ export default function BlockActions( { setBlockMovingClientId( clientIds[ 0 ] ); }, onGroup() { - if ( ! blocks.length ) { + if ( ! clientIds.length ) { return; } const groupingBlockName = getGroupingBlockName(); // Activate the `transform` on `core/group` which does the conversion. - const newBlocks = switchToBlockType( blocks, groupingBlockName ); + const newBlocks = switchToBlockType( + getBlocksByClientId( clientIds ), + groupingBlockName + ); if ( ! newBlocks ) { return; @@ -119,12 +133,11 @@ export default function BlockActions( { replaceBlocks( clientIds, newBlocks ); }, onUngroup() { - if ( ! blocks.length ) { + if ( ! clientIds.length ) { return; } - const innerBlocks = blocks[ 0 ].innerBlocks; - + const innerBlocks = getBlocks( clientIds[ 0 ] ); if ( ! innerBlocks.length ) { return; } @@ -132,16 +145,13 @@ export default function BlockActions( { replaceBlocks( clientIds, innerBlocks ); }, onCopy() { - const selectedBlockClientIds = blocks.map( - ( { clientId } ) => clientId - ); - if ( blocks.length === 1 ) { - flashBlock( selectedBlockClientIds[ 0 ] ); + if ( clientIds.length === 1 ) { + flashBlock( clientIds[ 0 ] ); } - notifyCopy( 'copy', selectedBlockClientIds ); + notifyCopy( 'copy', clientIds ); }, async onPasteStyles() { - await pasteStyles( blocks ); + await pasteStyles( getBlocksByClientId( clientIds ) ); }, } ); } diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index ae28ca6e5bad97..f3d22e6557a674 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -33,8 +33,12 @@ const POPOVER_PROPS = { placement: 'bottom-start', }; -function CopyMenuItem( { blocks, onCopy, label } ) { - const ref = useCopyToClipboard( () => serialize( blocks ), onCopy ); +function CopyMenuItem( { clientIds, onCopy, label } ) { + const { getBlocksByClientId } = useSelect( blockEditorStore ); + const ref = useCopyToClipboard( + () => serialize( getBlocksByClientId( clientIds ) ), + onCopy + ); const copyMenuItemLabel = label ? label : __( 'Copy' ); return { copyMenuItemLabel }; } @@ -198,7 +202,7 @@ export function BlockSettingsDropdown( { { ( { canCopyStyles, canDuplicate, - canInsertDefaultBlock, + canInsertBlock, canMove, canRemove, onDuplicate, @@ -208,7 +212,6 @@ export function BlockSettingsDropdown( { onCopy, onPasteStyles, onMoveTo, - blocks, } ) => ( ) } { canDuplicate && ( @@ -301,7 +304,7 @@ export function BlockSettingsDropdown( { { __( 'Duplicate' ) } ) } - { canInsertDefaultBlock && ( + { canInsertBlock && ( <> diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 33c76bd2f6e4cf..018c9ff9115185 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1539,7 +1539,7 @@ export const duplicateBlocks = }; /** - * Action that inserts an empty block before a given block. + * Action that inserts a default block before a given block. * * @param {string} clientId */ @@ -1555,16 +1555,34 @@ export const insertBeforeBlock = return; } - const firstSelectedIndex = select.getBlockIndex( clientId ); - return dispatch.insertDefaultBlock( - {}, - rootClientId, - firstSelectedIndex - ); + const blockIndex = select.getBlockIndex( clientId ); + const directInsertBlock = rootClientId + ? select.getDirectInsertBlock( rootClientId ) + : null; + + if ( ! directInsertBlock ) { + return dispatch.insertDefaultBlock( {}, rootClientId, blockIndex ); + } + + const copiedAttributes = {}; + if ( directInsertBlock.attributesToCopy ) { + const attributes = select.getBlockAttributes( clientId ); + directInsertBlock.attributesToCopy.forEach( ( key ) => { + if ( attributes[ key ] ) { + copiedAttributes[ key ] = attributes[ key ]; + } + } ); + } + + const block = createBlock( directInsertBlock.name, { + ...directInsertBlock.attributes, + ...copiedAttributes, + } ); + return dispatch.insertBlock( block, blockIndex, rootClientId ); }; /** - * Action that inserts an empty block after a given block. + * Action that inserts a default block after a given block. * * @param {string} clientId */ @@ -1580,12 +1598,34 @@ export const insertAfterBlock = return; } - const firstSelectedIndex = select.getBlockIndex( clientId ); - return dispatch.insertDefaultBlock( - {}, - rootClientId, - firstSelectedIndex + 1 - ); + const blockIndex = select.getBlockIndex( clientId ); + const directInsertBlock = rootClientId + ? select.getDirectInsertBlock( rootClientId ) + : null; + + if ( ! directInsertBlock ) { + return dispatch.insertDefaultBlock( + {}, + rootClientId, + blockIndex + 1 + ); + } + + const copiedAttributes = {}; + if ( directInsertBlock.attributesToCopy ) { + const attributes = select.getBlockAttributes( clientId ); + directInsertBlock.attributesToCopy.forEach( ( key ) => { + if ( attributes[ key ] ) { + copiedAttributes[ key ] = attributes[ key ]; + } + } ); + } + + const block = createBlock( directInsertBlock.name, { + ...directInsertBlock.attributes, + ...copiedAttributes, + } ); + return dispatch.insertBlock( block, blockIndex + 1, rootClientId ); }; /**