From 9f78b226091170ba8bf1b29f25e9bc5a5a3c9f1c Mon Sep 17 00:00:00 2001 From: David Calhoun <438664+dcalhoun@users.noreply.github.com> Date: Tue, 18 May 2021 15:29:18 -0500 Subject: [PATCH] Revert "Image/Gallery block: remove use of unstableOnFocus (#31796)" This reverts commit 9a6e3fcbc927791d7fb70f35ba88da1ef2d83acb. --- .../use-block-props/use-focus-handler.js | 6 +-- packages/block-library/src/gallery/edit.js | 5 ++ .../src/gallery/gallery-image.js | 46 ++++++++++++++++--- packages/block-library/src/gallery/gallery.js | 2 + packages/block-library/src/image/image.js | 22 +++++++++ 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-focus-handler.js b/packages/block-editor/src/components/block-list/use-block-props/use-focus-handler.js index ac9e0f8c6d1bdf..4946cc40a26c9c 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-focus-handler.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-focus-handler.js @@ -17,7 +17,7 @@ import { store as blockEditorStore } from '../../../store'; */ export function useFocusHandler( clientId ) { const { isBlockSelected } = useSelect( blockEditorStore ); - const { selectBlock, selectionChange } = useDispatch( blockEditorStore ); + const { selectBlock } = useDispatch( blockEditorStore ); return useRefEffect( ( node ) => { @@ -33,10 +33,6 @@ export function useFocusHandler( clientId ) { // Check synchronously because a non-selected block might be // getting data through `useSelect` asynchronously. if ( isBlockSelected( clientId ) ) { - // Potentially change selection away from rich text. - if ( ! event.target.isContentEditable ) { - selectionChange( clientId ); - } return; } diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index 92d7125fd9382e..6d921d87c2a041 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -295,6 +295,10 @@ function GalleryEdit( props ) { : __( 'Thumbnails are not cropped.' ); } + function onFocusGalleryCaption() { + setSelectedImage(); + } + function setImageAttributes( index, newAttributes ) { if ( ! images[ index ] ) { return; @@ -462,6 +466,7 @@ function GalleryEdit( props ) { onSelectImage={ onSelectImage } onDeselectImage={ onDeselectImage } onSetImageAttributes={ setImageAttributes } + onFocusGalleryCaption={ onFocusGalleryCaption } blockProps={ blockProps } /> diff --git a/packages/block-library/src/gallery/gallery-image.js b/packages/block-library/src/gallery/gallery-image.js index 2b35ad52830fbd..5b07c133ef9625 100644 --- a/packages/block-library/src/gallery/gallery-image.js +++ b/packages/block-library/src/gallery/gallery-image.js @@ -44,6 +44,7 @@ class GalleryImage extends Component { super( ...arguments ); this.onSelectImage = this.onSelectImage.bind( this ); + this.onSelectCaption = this.onSelectCaption.bind( this ); this.onRemoveImage = this.onRemoveImage.bind( this ); this.bindContainer = this.bindContainer.bind( this ); this.onEdit = this.onEdit.bind( this ); @@ -52,6 +53,7 @@ class GalleryImage extends Component { ); this.onSelectCustomURL = this.onSelectCustomURL.bind( this ); this.state = { + captionSelected: false, isEditing: false, }; } @@ -60,10 +62,28 @@ class GalleryImage extends Component { this.container = ref; } + onSelectCaption() { + if ( ! this.state.captionSelected ) { + this.setState( { + captionSelected: true, + } ); + } + + if ( ! this.props.isSelected ) { + this.props.onSelect(); + } + } + onSelectImage() { if ( ! this.props.isSelected ) { this.props.onSelect(); } + + if ( this.state.captionSelected ) { + this.setState( { + captionSelected: false, + } ); + } } onRemoveImage( event ) { @@ -84,8 +104,9 @@ class GalleryImage extends Component { } ); } - componentDidUpdate() { + componentDidUpdate( prevProps ) { const { + isSelected, image, url, __unstableMarkNextChangeAsNotPersistent, @@ -97,6 +118,18 @@ class GalleryImage extends Component { alt: image.alt_text, } ); } + + // unselect the caption so when the user selects other image and comeback + // the caption is not immediately selected + if ( + this.state.captionSelected && + ! isSelected && + prevProps.isSelected + ) { + this.setState( { + captionSelected: false, + } ); + } } deselectOnBlur() { @@ -183,6 +216,8 @@ class GalleryImage extends Component { src={ url } alt={ alt } data-id={ id } + onClick={ this.onSelectImage } + onFocus={ this.onSelectImage } onKeyDown={ this.onRemoveImage } tabIndex="0" aria-label={ ariaLabel } @@ -199,12 +234,7 @@ class GalleryImage extends Component { } ); return ( - // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions -
+
{ ! isEditing && ( href ? { img } : img ) } { isEditing && ( setAttributes( { caption: newCaption } ) } + unstableOnFocus={ this.onSelectCaption } inlineToolbar /> ) } diff --git a/packages/block-library/src/gallery/gallery.js b/packages/block-library/src/gallery/gallery.js index fc9d0fa39448e4..8e28b50562e6d1 100644 --- a/packages/block-library/src/gallery/gallery.js +++ b/packages/block-library/src/gallery/gallery.js @@ -30,6 +30,7 @@ export const Gallery = ( props ) => { onSelectImage, onDeselectImage, onSetImageAttributes, + onFocusGalleryCaption, insertBlocksAfter, blockProps, } = props; @@ -98,6 +99,7 @@ export const Gallery = ( props ) => { aria-label={ __( 'Gallery caption text' ) } placeholder={ __( 'Write gallery caption…' ) } value={ caption } + unstableOnFocus={ onFocusGalleryCaption } onChange={ ( value ) => setAttributes( { caption: value } ) } inlineToolbar __unstableOnSplitAtEnd={ () => diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index ba59b8f4250ec3..0b52c1aab6b680 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -130,6 +130,7 @@ export default function Image( { noticesStore ); const isLargeViewport = useViewportMatch( 'medium' ); + const [ captionFocused, setCaptionFocused ] = useState( false ); const isWideAligned = includes( [ 'wide', 'full' ], align ); const [ { naturalWidth, naturalHeight }, setNaturalSize ] = useState( {} ); const [ isEditingImage, setIsEditingImage ] = useState( false ); @@ -146,6 +147,12 @@ export default function Image( { // Check if the cover block is registered. const coverBlockExists = !! getBlockType( 'core/cover' ); + useEffect( () => { + if ( ! isSelected ) { + setCaptionFocused( false ); + } + }, [ isSelected ] ); + // 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, // we can enable a button in the toolbar to upload the image. @@ -196,6 +203,18 @@ export default function Image( { setAttributes( { title: value } ); } + function onFocusCaption() { + if ( ! captionFocused ) { + setCaptionFocused( true ); + } + } + + function onImageClick() { + if ( captionFocused ) { + setCaptionFocused( false ); + } + } + function updateAlt( newAlt ) { setAttributes( { alt: newAlt } ); } @@ -398,6 +417,7 @@ export default function Image( { { onImageError() } onLoad={ ( event ) => { setNaturalSize( @@ -544,9 +564,11 @@ export default function Image( { aria-label={ __( 'Image caption text' ) } placeholder={ __( 'Add caption' ) } value={ caption } + unstableOnFocus={ onFocusCaption } onChange={ ( value ) => setAttributes( { caption: value } ) } + isSelected={ captionFocused } inlineToolbar __unstableOnSplitAtEnd={ () => insertBlocksAfter( createBlock( 'core/paragraph' ) )