From 98c65eaf268b86175d51cbb91c35e4111a7950ef Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:02:49 +1000 Subject: [PATCH 1/5] Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate (#65144) * Drag and Drop: When dragging a mix of video, audio, and image blocks, create individual blocks as appropriate * Consolidate into the fallback transform for the File block Co-authored-by: andrewserong Co-authored-by: ramonjd Co-authored-by: kevin940726 Co-authored-by: swissspidy --- packages/block-library/src/file/transforms.js | 32 +++++++++++++++---- .../block-library/src/image/transforms.js | 23 ------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/packages/block-library/src/file/transforms.js b/packages/block-library/src/file/transforms.js index b925e80e595033..c381a62f783866 100644 --- a/packages/block-library/src/file/transforms.js +++ b/packages/block-library/src/file/transforms.js @@ -24,12 +24,32 @@ const transforms = { const blobURL = createBlobURL( file ); // File will be uploaded in componentDidMount() - blocks.push( - createBlock( 'core/file', { - blob: blobURL, - fileName: file.name, - } ) - ); + if ( file.type.startsWith( 'video/' ) ) { + blocks.push( + createBlock( 'core/video', { + blob: createBlobURL( file ), + } ) + ); + } else if ( file.type.startsWith( 'image/' ) ) { + blocks.push( + createBlock( 'core/image', { + blob: createBlobURL( file ), + } ) + ); + } else if ( file.type.startsWith( 'audio/' ) ) { + blocks.push( + createBlock( 'core/audio', { + blob: createBlobURL( file ), + } ) + ); + } else { + blocks.push( + createBlock( 'core/file', { + blob: blobURL, + fileName: file.name, + } ) + ); + } } ); return blocks; diff --git a/packages/block-library/src/image/transforms.js b/packages/block-library/src/image/transforms.js index 0e1dfb6ee9da44..347d2408280170 100644 --- a/packages/block-library/src/image/transforms.js +++ b/packages/block-library/src/image/transforms.js @@ -3,9 +3,6 @@ */ import { createBlobURL, isBlobURL } from '@wordpress/blob'; import { createBlock, getBlockAttributes } from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; -import { store as noticesStore } from '@wordpress/notices'; -import { __ } from '@wordpress/i18n'; export function stripFirstImage( attributes, { shortcode } ) { const { body } = document.implementation.createHTMLDocument( '' ); @@ -138,26 +135,6 @@ const transforms = { // creating a new gallery. type: 'files', isMatch( files ) { - // The following check is intended to catch non-image files when dropped together with images. - if ( - files.some( - ( file ) => file.type.indexOf( 'image/' ) === 0 - ) && - files.some( - ( file ) => file.type.indexOf( 'image/' ) !== 0 - ) - ) { - const { createErrorNotice } = dispatch( noticesStore ); - createErrorNotice( - __( - 'If uploading to a gallery all files need to be image formats' - ), - { - id: 'gallery-transform-invalid-file', - type: 'snackbar', - } - ); - } return files.every( ( file ) => file.type.indexOf( 'image/' ) === 0 ); From da8f8743c22bd9b188a742886367b0a6a25746ed Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 11 Sep 2024 10:40:44 +0800 Subject: [PATCH 2/5] Disallow setting grid block rows/columns to zero (#65217) * Disallow setting grid block rows/columns to zero * Prevent issues with grid block column/row count by ensuring a proper minimum Co-authored-by: talldan Co-authored-by: andrewserong Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/block-editor/src/layouts/grid.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index 7ab5c7ebbc8c3d..d1f6fdd785089b 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -74,7 +74,8 @@ export default { // In the experiment we want to also show column control in Auto mode, and // the minimum width control in Manual mode. const showColumnsControl = - window.__experimentalEnableGridInteractivity || layout?.columnCount; + window.__experimentalEnableGridInteractivity || + !! layout?.columnCount; const showMinWidthControl = window.__experimentalEnableGridInteractivity || ! layout?.columnCount; @@ -317,7 +318,7 @@ function GridLayoutColumnsAndRowsControl( { const defaultNewColumnCount = isManualPlacement ? 1 : undefined; const newColumnCount = - value === '' + value === '' || value === '0' ? defaultNewColumnCount : parseInt( value, 10 ); onChange( { @@ -327,7 +328,7 @@ function GridLayoutColumnsAndRowsControl( { } else { // Don't allow unsetting the column count. const newColumnCount = - value === '' + value === '' || value === '0' ? 1 : parseInt( value, 10 ); onChange( { @@ -337,7 +338,7 @@ function GridLayoutColumnsAndRowsControl( { } } } value={ columnCount } - min={ 0 } + min={ 1 } label={ __( 'Columns' ) } hideLabelFromVision={ ! window.__experimentalEnableGridInteractivity || @@ -355,7 +356,7 @@ function GridLayoutColumnsAndRowsControl( { onChange={ ( value ) => { // Don't allow unsetting the row count. const newRowCount = - value === '' + value === '' || value === '0' ? 1 : parseInt( value, 10 ); onChange( { @@ -364,21 +365,24 @@ function GridLayoutColumnsAndRowsControl( { } ); } } value={ rowCount } - min={ 0 } + min={ 1 } label={ __( 'Rows' ) } /> ) : ( onChange( { ...layout, - columnCount: value, + columnCount: + value === '' || value === '0' + ? 1 + : value, } ) } - min={ 0 } + min={ 1 } max={ 16 } withInputField={ false } label={ __( 'Columns' ) } From ec58c51108f03e4a03046d763d4c830347da91bf Mon Sep 17 00:00:00 2001 From: Vipul Gupta <55375170+vipul0425@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:18:32 +0530 Subject: [PATCH 3/5] Image: Adds the block controls for uploading image. (#64320) * feat: Adds the block controls for uploading image. * feat: Adds the size based placeholder logic. * fix: The layout design for small images and adds grid support. * refactor: Remove resize observer and add lockURLControls support. * refactor: Make use of the existing MediaReplaceFlow component. * fix: The mediaPlaceholder location after merge. * fix: The initial flash in small size. * feat: Removes the redundant css and redefine the placeholder logic. * fix: Adressed the PR feedbacks. * fix: Removes the effective width logic and moves observer inside of placeholder. * fix: The e2e test failures * Update packages/block-library/src/image/edit.js Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --------- Co-authored-by: vipul0425 Co-authored-by: jasmussen Co-authored-by: t-hamano Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo Co-authored-by: tyxla Co-authored-by: richtabor Co-authored-by: annezazu Co-authored-by: fabiankaegy --- packages/block-library/src/image/edit.js | 31 ++++++++++----- packages/block-library/src/image/editor.scss | 40 +------------------ packages/block-library/src/image/image.js | 42 ++++++++++++-------- 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index f9aed8d93f95a0..660d99bc748ab0 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -12,8 +12,8 @@ import { Placeholder } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { BlockIcon, - MediaPlaceholder, useBlockProps, + MediaPlaceholder, store as blockEditorStore, __experimentalUseBorderProps as useBorderProps, __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles, @@ -109,12 +109,18 @@ export function ImageEdit( { align, metadata, } = attributes; + const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); const figureRef = useRef(); const [ contentResizeListener, { width: containerWidth } ] = useResizeObserver(); + const [ placeholderResizeListener, { width: placeholderWidth } ] = + useResizeObserver(); + + const isSmallContainer = placeholderWidth && placeholderWidth < 160; + const altRef = useRef(); useEffect( () => { altRef.current = alt; @@ -387,11 +393,15 @@ export function ImageEdit( { [ borderProps.className ]: !! borderProps.className && ! isSingleSelected, } ) } - withIllustration - icon={ lockUrlControls ? pluginsIcon : icon } - label={ __( 'Image' ) } + icon={ + ! isSmallContainer && + ( lockUrlControls ? pluginsIcon : icon ) + } + withIllustration={ ! isSingleSelected || isSmallContainer } + label={ ! isSmallContainer && __( 'Image' ) } instructions={ ! lockUrlControls && + ! isSmallContainer && __( 'Upload or drag an image file here, or pick one from your library.' ) @@ -408,13 +418,12 @@ export function ImageEdit( { ...shadowProps.style, } } > - { lockUrlControls ? ( - - { lockUrlControlsMessage } - - ) : ( - content - ) } + { lockUrlControls && + ! isSmallContainer && + lockUrlControlsMessage } + + { ! lockUrlControls && ! isSmallContainer && content } + { placeholderResizeListener } ); }; diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 636741c7d9ddbb..d143e6604d1e73 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -1,44 +1,8 @@ // Provide special styling for the placeholder. // @todo this particular minimal style of placeholder could be componentized further. .wp-block-image.wp-block-image { - - // Show Placeholder style on-select. - &.is-selected .block-editor-media-placeholder { - // Block UI appearance. - color: $gray-900; - background-color: $white; - box-shadow: inset 0 0 0 $border-width $gray-900; - border: none; - - // Disable any duotone filter applied in the selected state. - filter: none !important; - - > svg { - opacity: 0; - } - - .components-placeholder__illustration { - display: none; - } - - &::before { - opacity: 0; - } - } - .block-bindings-media-placeholder-message { - opacity: 0; - } - &.is-selected .block-bindings-media-placeholder-message { - opacity: 1; - } - - // Remove the transition while we still have a legacy placeholder style. - // Otherwise the content jumps between the 1px placeholder border, and any inherited custom - // parent border that may get applied when you deselect. - .components-placeholder__label, - .components-placeholder__instructions, - .components-button { - transition: none; + .block-editor-media-placeholder.is-small { + min-height: 60px; } } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 2de316f78ba5d8..f79f078b1eef82 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -556,6 +556,24 @@ export default function Image( { const showBlockControls = showUrlInput || allowCrop || showCoverControls; + const mediaReplaceFlow = isSingleSelected && + ! isEditingImage && + ! lockUrlControls && ( + + onSelectImage( undefined ) } + /> + + ); + const controls = ( <> { showBlockControls && ( @@ -592,20 +610,6 @@ export default function Image( { ) } ) } - { isSingleSelected && ! isEditingImage && ! lockUrlControls && ( - - onSelectImage( undefined ) } - /> - - ) } { isSingleSelected && externalBlob && ( @@ -1029,12 +1033,18 @@ export default function Image( { } if ( ! url && ! temporaryURL ) { - // Add all controls if the image attributes are connected. - return metadata?.bindings ? controls : sizeControls; + return ( + <> + { mediaReplaceFlow } + { /* Add all controls if the image attributes are connected. */ } + { metadata?.bindings ? controls : sizeControls } + + ); } return ( <> + { mediaReplaceFlow } { controls } { img } From 6a60081909d1dfbbb608e7b069dec3eb6881e37e Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Wed, 11 Sep 2024 10:51:28 +0800 Subject: [PATCH 4/5] Fix resizing to max width in classic themes (#64819) co-authored-by: kevin940726 Co-authored-by: aaronrobertshaw Co-authored-by: andrewserong Co-authored-by: ramonjd * Fix resizing to max width in classic themes * Fix padding and max-width * Reverse the condition * Try ignoring if layout doesn't exist --- packages/block-library/src/image/edit.js | 24 +++++++++----- packages/block-library/src/image/editor.scss | 5 +++ packages/block-library/src/image/image.js | 9 +++--- .../src/image/use-max-width-observer.js | 32 +++++++++++++++++++ 4 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 packages/block-library/src/image/use-max-width-observer.js diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 660d99bc748ab0..16ec296554d743 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,7 +23,6 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; -import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies @@ -32,6 +31,7 @@ import { unlock } from '../lock-unlock'; import { useUploadMediaFromBlobURL } from '../utils/hooks'; import Image from './image'; import { isValidFileType } from './utils'; +import { useMaxWidthObserver } from './use-max-width-observer'; /** * Module constants @@ -111,10 +111,15 @@ export function ImageEdit( { } = attributes; const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); - const figureRef = useRef(); - const [ contentResizeListener, { width: containerWidth } ] = - useResizeObserver(); + const containerRef = useRef(); + // Only observe the max width from the parent container when the parent layout is not flex nor grid. + // This won't work for them because the container width changes with the image. + // TODO: Find a way to observe the container width for flex and grid layouts. + const isMaxWidthContainerWidth = + ! parentLayout || + ( parentLayout.type !== 'flex' && parentLayout.type !== 'grid' ); + const [ maxWidthObserver, maxContentWidth ] = useMaxWidthObserver(); const [ placeholderResizeListener, { width: placeholderWidth } ] = useResizeObserver(); @@ -166,7 +171,7 @@ export function ImageEdit( { } function onSelectImagesList( images ) { - const win = figureRef.current?.ownerDocument.defaultView; + const win = containerRef.current?.ownerDocument.defaultView; if ( images.every( ( file ) => file instanceof win.File ) ) { /** @type {File[]} */ @@ -354,7 +359,10 @@ export function ImageEdit( { Object.keys( borderProps.style ).length > 0 ), } ); - const blockProps = useBlockProps( { ref: figureRef, className: classes } ); + const blockProps = useBlockProps( { + ref: containerRef, + className: classes, + } ); // Much of this description is duplicated from MediaPlaceholder. const { lockUrlControls = false, lockUrlControlsMessage } = useSelect( @@ -445,7 +453,7 @@ export function ImageEdit( { clientId={ clientId } blockEditingMode={ blockEditingMode } parentLayoutType={ parentLayout?.type } - containerWidth={ containerWidth } + maxContentWidth={ maxContentWidth } /> } @@ -464,7 +472,7 @@ export function ImageEdit( { { // The listener cannot be placed as the first element as it will break the in-between inserter. // See https://github.com/WordPress/gutenberg/blob/71134165868298fc15e22896d0c28b41b3755ff7/packages/block-editor/src/components/block-list/use-in-between-inserter.js#L120 - contentResizeListener + isSingleSelected && isMaxWidthContainerWidth && maxWidthObserver } ); diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index d143e6604d1e73..34f65d690d3d74 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -113,6 +113,11 @@ figure.wp-block-image:not(.wp-block) { text-align: center; } +// Relatively position the alignment container to support the content resizer. +.wp-block[data-align]:has(> .wp-block-image) { + position: relative; +} + .wp-block-image__crop-area { position: relative; max-width: 100%; diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index f79f078b1eef82..60d83f89129070 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -108,7 +108,7 @@ export default function Image( { clientId, blockEditingMode, parentLayoutType, - containerWidth, + maxContentWidth, } ) { const { url = '', @@ -938,7 +938,7 @@ export default function Image( { // @todo It would be good to revisit this once a content-width variable // becomes available. const maxWidthBuffer = maxWidth * 2.5; - const maxContentWidth = containerWidth || maxWidthBuffer; + const maxResizeWidth = maxContentWidth || maxWidthBuffer; let showRightHandle = false; let showLeftHandle = false; @@ -984,9 +984,9 @@ export default function Image( { } } showHandle={ isSingleSelected } minWidth={ minWidth } - maxWidth={ maxContentWidth } + maxWidth={ maxResizeWidth } minHeight={ minHeight } - maxHeight={ maxContentWidth / ratio } + maxHeight={ maxResizeWidth / ratio } lockAspectRatio={ ratio } enable={ { top: false, @@ -1000,6 +1000,7 @@ export default function Image( { // Clear hardcoded width if the resized width is close to the max-content width. if ( + maxContentWidth && // Only do this if the image is bigger than the container to prevent it from being squished. // TODO: Remove this check if the image support setting 100% width. naturalWidth >= maxContentWidth && diff --git a/packages/block-library/src/image/use-max-width-observer.js b/packages/block-library/src/image/use-max-width-observer.js new file mode 100644 index 00000000000000..684392537fac7a --- /dev/null +++ b/packages/block-library/src/image/use-max-width-observer.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { useRef } from '@wordpress/element'; +import { useResizeObserver } from '@wordpress/compose'; + +function useMaxWidthObserver() { + const [ contentResizeListener, { width } ] = useResizeObserver(); + const observerRef = useRef(); + + const maxWidthObserver = ( + + ); + + return [ maxWidthObserver, width ]; +} + +export { useMaxWidthObserver }; From 2f939a7f9047ed9b632ac4fb0d593d0cf9588ce9 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:44:22 +0900 Subject: [PATCH 5/5] Fix image block crash (#65222) Co-authored-by: t-hamano Co-authored-by: kevin940726 Co-authored-by: ramonjd --- packages/block-library/src/image/edit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 16ec296554d743..d44dc73abfd855 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,6 +23,7 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; +import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies