diff --git a/packages/block-editor/src/components/block-controls/groups.js b/packages/block-editor/src/components/block-controls/groups.js index 9b9dfec8d8d450..391f1bf0b2279a 100644 --- a/packages/block-editor/src/components/block-controls/groups.js +++ b/packages/block-editor/src/components/block-controls/groups.js @@ -8,6 +8,7 @@ const BlockControlsBlock = createSlotFill( 'BlockControlsBlock' ); const BlockControlsInline = createSlotFill( 'BlockFormatControls' ); const BlockControlsOther = createSlotFill( 'BlockControlsOther' ); const BlockControlsParent = createSlotFill( 'BlockControlsParent' ); +const BlockControlsAlt = createSlotFill( 'BlockControlsParent' ); const groups = { default: BlockControlsDefault, @@ -15,6 +16,7 @@ const groups = { inline: BlockControlsInline, other: BlockControlsOther, parent: BlockControlsParent, + alt: BlockControlsAlt, }; export default groups; diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index def5b425760d10..762451371769f2 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -32,6 +32,7 @@ export default function BlockToolbar( { hideDragHandle } ) { hasReducedUI, isValid, isVisual, + isAltMode, } = useSelect( ( select ) => { const { getBlockName, @@ -61,6 +62,9 @@ export default function BlockToolbar( { hideDragHandle } ) { isVisual: selectedBlockClientIds.every( ( id ) => getBlockMode( id ) === 'visual' ), + isAltMode: selectedBlockClientIds.every( + ( id ) => getBlockMode( id ) === 'alt' + ), }; }, [] ); @@ -105,6 +109,17 @@ export default function BlockToolbar( { hideDragHandle } ) { shouldShowMovers && 'is-showing-movers' ); + if ( isAltMode ) { + return ( +
+ +
+ ); + } + return (
{ ! isMultiToolbar && ! displayHeaderToolbar && ( diff --git a/packages/block-editor/src/components/image-editor/index.js b/packages/block-editor/src/components/image-editor/index.js index 87a48f67e41fdc..5cf9affcbec1e6 100644 --- a/packages/block-editor/src/components/image-editor/index.js +++ b/packages/block-editor/src/components/image-editor/index.js @@ -31,7 +31,7 @@ export default function ImageEditor( { naturalHeight={ naturalHeight } naturalWidth={ naturalWidth } /> - + diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 2d0d3cc77ecddb..b5aa946576e6ff 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -896,6 +896,22 @@ export function toggleBlockMode( clientId ) { }; } +/** + * Returns an action object used to set alternate editing modes. + * + * @param {string} clientId Block client ID. + * @param {string} mode Block editing mode. + * + * @return {Object} Action object. + */ +export function setBlockMode( clientId, mode ) { + return { + type: 'SET_BLOCK_MODE', + clientId, + mode, + }; +} + /** * Returns an action object used in signalling that the user has begun to type. * diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index e5c333aacd223d..b433155313d5f5 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1390,15 +1390,22 @@ export function initialPosition( state = null, action ) { } export function blocksMode( state = {}, action ) { - if ( action.type === 'TOGGLE_BLOCK_MODE' ) { - const { clientId } = action; - return { - ...state, - [ clientId ]: - state[ clientId ] && state[ clientId ] === 'html' - ? 'visual' - : 'html', - }; + const { clientId } = action; + + switch ( action.type ) { + case 'TOGGLE_BLOCK_MODE': + return { + ...state, + [ clientId ]: + state[ clientId ] && state[ clientId ] === 'html' + ? 'visual' + : 'html', + }; + case 'SET_BLOCK_MODE': + return { + ...state, + [ clientId ]: action.mode, + }; } return state; diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 8c49687685d87b..b0de5d11859c34 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -50,6 +50,8 @@ import { isExternalImage } from './edit'; */ import { MIN_SIZE, ALLOWED_MEDIA_TYPES } from './constants'; +const IMAGE_EDITING_BLOCK_MODE = 'alt'; + export default function Image( { temporaryURL, attributes: { @@ -110,12 +112,14 @@ export default function Image( { imageSizes, maxWidth, mediaUpload, + isEditingImage, } = useSelect( ( select ) => { const { getBlockRootClientId, getSettings, canInsertBlockType, + getBlockMode, } = select( blockEditorStore ); const rootClientId = getBlockRootClientId( clientId ); @@ -132,11 +136,15 @@ export default function Image( { 'core/cover', rootClientId ), + isEditingImage: + getBlockMode( clientId ) === IMAGE_EDITING_BLOCK_MODE, }; }, [ clientId ] ); - const { replaceBlocks, toggleSelection } = useDispatch( blockEditorStore ); + const { replaceBlocks, toggleSelection, setBlockMode } = useDispatch( + blockEditorStore + ); const { createErrorNotice, createSuccessNotice } = useDispatch( noticesStore ); @@ -146,7 +154,6 @@ export default function Image( { { loadedNaturalWidth, loadedNaturalHeight }, setLoadedNaturalSize, ] = useState( {} ); - const [ isEditingImage, setIsEditingImage ] = useState( false ); const [ externalBlob, setExternalBlob ] = useState(); const clientWidth = useClientWidth( containerRef, [ align ] ); const isResizable = allowResize && ! ( isWideAligned && isLargeViewport ); @@ -156,6 +163,11 @@ export default function Image( { ), ( { name, slug } ) => ( { value: slug, label: name } ) ); + const setIsEditingImage = ( isEditing ) => + setBlockMode( + clientId, + isEditing ? IMAGE_EDITING_BLOCK_MODE : 'visual' + ); // If an image is externally hosted, try to fetch the image data. This may // fail if the image host doesn't allow CORS with the domain. If it works,