From 014d1633b6986f54a0dd597d3d751f566a569570 Mon Sep 17 00:00:00 2001 From: Andrew Hayward Date: Wed, 22 Nov 2023 09:23:25 +0000 Subject: [PATCH 01/51] Migrating `InserterListbox` to use updated Composite implementation (#56246) - Removes `__unstableComposite` imports from `@wordpress/components` - Adds private `Composite*` exports from `@wordpress/components` - Refactors `InserterListbox`, `InserterListboxRow` and `InserterListboxItem` to use updated `Composite` components - Additionally updates `BlockTypesList` to ensure listbox items are appropriately grouped --- .../src/components/block-types-list/index.js | 9 ++++---- .../src/components/inserter-listbox/index.js | 18 +++++++++------ .../src/components/inserter-listbox/item.js | 23 +++++++++---------- .../src/components/inserter-listbox/row.js | 18 +++++---------- 4 files changed, 33 insertions(+), 35 deletions(-) diff --git a/packages/block-editor/src/components/block-types-list/index.js b/packages/block-editor/src/components/block-types-list/index.js index 40e04b040d5a8..0be6f82a653d1 100644 --- a/packages/block-editor/src/components/block-types-list/index.js +++ b/packages/block-editor/src/components/block-types-list/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { getBlockMenuDefaultClassName } from '@wordpress/blocks'; +import { useInstanceId } from '@wordpress/compose'; /** * Internal dependencies @@ -25,11 +26,10 @@ function BlockTypesList( { label, isDraggable = true, } ) { + const className = 'block-editor-block-types-list'; + const listId = useInstanceId( BlockTypesList, className ); return ( - + { chunk( items, 3 ).map( ( row, i ) => ( { row.map( ( item, j ) => ( @@ -43,6 +43,7 @@ function BlockTypesList( { onHover={ onHover } isDraggable={ isDraggable && ! item.isDisabled } isFirst={ i === 0 && j === 0 } + rowId={ `${ listId }-${ i }` } /> ) ) } diff --git a/packages/block-editor/src/components/inserter-listbox/index.js b/packages/block-editor/src/components/inserter-listbox/index.js index 6345cb38c494a..6af26a1d746bf 100644 --- a/packages/block-editor/src/components/inserter-listbox/index.js +++ b/packages/block-editor/src/components/inserter-listbox/index.js @@ -1,26 +1,30 @@ /** * WordPress dependencies */ -import { __unstableUseCompositeState as useCompositeState } from '@wordpress/components'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; /** * Internal dependencies */ -import InserterListboxContext from './context'; +import { unlock } from '../../lock-unlock'; export { default as InserterListboxGroup } from './group'; export { default as InserterListboxRow } from './row'; export { default as InserterListboxItem } from './item'; +const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } = + unlock( componentsPrivateApis ); + function InserterListbox( { children } ) { - const compositeState = useCompositeState( { - shift: true, - wrap: 'horizontal', + const store = useCompositeStore( { + focusShift: true, + focusWrap: 'horizontal', } ); + return ( - + }> { children } - + ); } diff --git a/packages/block-editor/src/components/inserter-listbox/item.js b/packages/block-editor/src/components/inserter-listbox/item.js index 50adb4a788038..951eb86223ce8 100644 --- a/packages/block-editor/src/components/inserter-listbox/item.js +++ b/packages/block-editor/src/components/inserter-listbox/item.js @@ -3,32 +3,31 @@ */ import { Button, - __unstableCompositeItem as CompositeItem, + privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { forwardRef, useContext } from '@wordpress/element'; +import { forwardRef } from '@wordpress/element'; /** * Internal dependencies */ -import InserterListboxContext from './context'; +import { unlock } from '../../lock-unlock'; + +const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis ); function InserterListboxItem( { isFirst, as: Component, children, ...props }, ref ) { - const state = useContext( InserterListboxContext ); return ( - { ( htmlProps ) => { + render={ ( htmlProps ) => { const propsWithTabIndex = { ...htmlProps, tabIndex: isFirst ? 0 : htmlProps.tabIndex, @@ -45,7 +44,7 @@ function InserterListboxItem( } return ; } } - + /> ); } diff --git a/packages/block-editor/src/components/inserter-listbox/row.js b/packages/block-editor/src/components/inserter-listbox/row.js index 710267660199d..f9827f08b3fa3 100644 --- a/packages/block-editor/src/components/inserter-listbox/row.js +++ b/packages/block-editor/src/components/inserter-listbox/row.js @@ -1,24 +1,18 @@ /** * WordPress dependencies */ -import { forwardRef, useContext } from '@wordpress/element'; -import { __unstableCompositeGroup as CompositeGroup } from '@wordpress/components'; +import { forwardRef } from '@wordpress/element'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; /** * Internal dependencies */ -import InserterListboxContext from './context'; +import { unlock } from '../../lock-unlock'; + +const { CompositeGroupV2: CompositeGroup } = unlock( componentsPrivateApis ); function InserterListboxRow( props, ref ) { - const state = useContext( InserterListboxContext ); - return ( - - ); + return ; } export default forwardRef( InserterListboxRow ); From 9c6f6b1738a45f2891b5c7d4fde5c9a5ff80dc7e Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 22 Nov 2023 09:35:13 +0000 Subject: [PATCH 02/51] Update Changelog for 17.1.0 --- changelog.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 2435ab1eceb4a..0f86c2d8f593b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,6 @@ == Changelog == -= 17.1.0-rc.1 = - += 17.1.0 = ## Changelog @@ -27,7 +26,7 @@ #### Global Styles - Global Style Revisions: Ensure consistent back button behaviour. ([55881](https://github.com/WordPress/gutenberg/pull/55881)) - Global Styles Revisions: More descriptive text timeline. ([55868](https://github.com/WordPress/gutenberg/pull/55868)) -- Global styles revisions: Add route for single styles revisions. ([55827](https://github.com/WordPress/gutenberg/pull/55827)) +- Global Styles Revisions: Add route for single styles revisions. ([55827](https://github.com/WordPress/gutenberg/pull/55827)) #### Block Locking - Block Quick Navigation: Truncate text. ([56142](https://github.com/WordPress/gutenberg/pull/56142)) @@ -89,7 +88,7 @@ - DataViews: Make items per page an even number. ([55906](https://github.com/WordPress/gutenberg/pull/55906)) - DataViews: Make used taxonomy private. ([55918](https://github.com/WordPress/gutenberg/pull/55918)) - DataViews: Reset pagination upon filter change. ([55797](https://github.com/WordPress/gutenberg/pull/55797)) -- Dataviews: Add a missing icon for the side by side view. ([55925](https://github.com/WordPress/gutenberg/pull/55925)) +- DataViews: Add a missing icon for the side by side view. ([55925](https://github.com/WordPress/gutenberg/pull/55925)) #### Components - DropdownMenu: Remove extra vertical space around the toggle button. ([56136](https://github.com/WordPress/gutenberg/pull/56136)) @@ -328,6 +327,8 @@ The following contributors merged PRs in this release: @afercia @andrewhayward @andrewserong @anomiex @anton-vlasenko @aristath @artemiomorales @bph @brookewp @c4rl0sbr4v0 @chad1008 @ciampo @DAreRodz @dcalhoun @dsas @ellatrix @flootr @fluiddot @gaambo @glendaviesnz @gziolo @jameskoster @jeryj @jhnstn @joanrodas @jorgefilipecosta @JorgeVilchez95 @jsnajdr @juanmaguitar @kevin940726 @Mamaduka @masteradhoc @matiasbenedetto @ndiego @ntsekouras @oandregal @peterwilsoncc @pooja-muchandikar @priethor @ramonjd @renatho @richtabor @sacerro @scruffian @shimotmk @SiobhyB @Soean @swissspidy @t-hamano @talldan @tellthemachines @torounit @tyxla @WunderBart @youknowriad + + = 17.0.2 = From a7911582cda6f11d1ebddcd27ccbb82fb86022c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:39:45 +0100 Subject: [PATCH 03/51] DataViews: update filter component (#56110) --- .../src/components/dataviews/add-filter.js | 2 +- .../src/components/dataviews/filters.js | 13 +-- .../src/components/dataviews/in-filter.js | 105 ++++++++++-------- .../src/components/dataviews/view-list.js | 35 ++---- 4 files changed, 71 insertions(+), 84 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/add-filter.js b/packages/edit-site/src/components/dataviews/add-filter.js index 147b5a09ca59a..7192a507b2afe 100644 --- a/packages/edit-site/src/components/dataviews/add-filter.js +++ b/packages/edit-site/src/components/dataviews/add-filter.js @@ -54,10 +54,10 @@ export default function AddFilter( { fields, view, onChangeView } ) { } diff --git a/packages/edit-site/src/components/dataviews/filters.js b/packages/edit-site/src/components/dataviews/filters.js index 72ca0eb35bd87..c7681f53fe0ae 100644 --- a/packages/edit-site/src/components/dataviews/filters.js +++ b/packages/edit-site/src/components/dataviews/filters.js @@ -1,8 +1,3 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - /** * Internal dependencies */ @@ -23,13 +18,7 @@ export default function Filters( { fields, view, onChangeView } ) { filters.push( { field: field.id, name: field.header, - elements: [ - { - value: '', - label: __( 'All' ), - }, - ...( field.elements || [] ), - ], + elements: field.elements || [], isVisible: view.filters.some( ( f ) => f.field === field.id && f.operator === OPERATOR_IN diff --git a/packages/edit-site/src/components/dataviews/in-filter.js b/packages/edit-site/src/components/dataviews/in-filter.js index 4f4170fdcbb0b..9dd85eb1eedb2 100644 --- a/packages/edit-site/src/components/dataviews/in-filter.js +++ b/packages/edit-site/src/components/dataviews/in-filter.js @@ -2,65 +2,78 @@ * WordPress dependencies */ import { - __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, - SelectControl, + Button, + privateApis as componentsPrivateApis, + Icon, } from '@wordpress/components'; +import { chevronDown } from '@wordpress/icons'; import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ import { OPERATOR_IN } from './constants'; +import { unlock } from '../../lock-unlock'; + +const { + DropdownMenuV2: DropdownMenu, + DropdownMenuCheckboxItemV2: DropdownMenuCheckboxItem, +} = unlock( componentsPrivateApis ); export default ( { filter, view, onChangeView } ) => { - const valueFound = view.filters.find( - ( f ) => f.field === filter.field && f.operator === OPERATOR_IN + const filterInView = view.filters.find( ( f ) => f.field === filter.field ); + const activeElement = filter.elements.find( + ( element ) => element.value === filterInView?.value ); - const activeValue = - ! valueFound || ! valueFound.hasOwnProperty( 'value' ) - ? '' - : valueFound.value; - - const id = `dataviews__filters-in-${ filter.field }`; - return ( - - { sprintf( - /* translators: filter name. */ - __( '%s:' ), - filter.name - ) } - + + { activeElement !== undefined + ? sprintf( + /* translators: 1: Filter name. 2: filter value. e.g.: "Author is Admin". */ + __( '%1$s is %2$s' ), + filter.name, + activeElement.label + ) + : filter.name } + + } - options={ filter.elements } - onChange={ ( value ) => { - const filters = view.filters.filter( - ( f ) => - f.field !== filter.field || f.operator !== OPERATOR_IN + > + { filter.elements.map( ( element ) => { + return ( + + onChangeView( ( currentView ) => ( { + ...currentView, + page: 1, + filters: [ + ...view.filters.filter( + ( f ) => f.field !== filter.field + ), + { + field: filter.field, + operator: OPERATOR_IN, + value: + activeElement?.value === + element.value + ? undefined + : element.value, + }, + ], + } ) ) + } + > + { element.label } + ); - - filters.push( { - field: filter.field, - operator: OPERATOR_IN, - value, - } ); - - onChangeView( ( currentView ) => ( { - ...currentView, - page: 1, - filters, - } ) ); - } } - /> + } ) } + ); }; diff --git a/packages/edit-site/src/components/dataviews/view-list.js b/packages/edit-site/src/components/dataviews/view-list.js index 0939297e374df..8e131a350ac7d 100644 --- a/packages/edit-site/src/components/dataviews/view-list.js +++ b/packages/edit-site/src/components/dataviews/view-list.js @@ -73,13 +73,7 @@ function HeaderMenu( { dataView, header } ) { if ( header.column.columnDef.type === ENUMERATION_TYPE ) { filter = { field: header.column.columnDef.id, - elements: [ - { - value: '', - label: __( 'All' ), - }, - ...( header.column.columnDef.elements || [] ), - ], + elements: header.column.columnDef.elements || [], }; } const isFilterable = !! filter; @@ -166,11 +160,6 @@ function HeaderMenu( { dataView, header } ) { )[ 0 ] === filter.field ); - // Set the empty item as active if the filter is not set. - if ( ! columnFilter && element.value === '' ) { - isActive = true; - } - if ( columnFilter ) { const value = Object.values( columnFilter )[ 0 ]; @@ -205,19 +194,15 @@ function HeaderMenu( { dataView, header } ) { } ); - if ( element.value === '' ) { - dataView.setColumnFilters( - otherFilters - ); - } else { - dataView.setColumnFilters( [ - ...otherFilters, - { - [ filter.field + - ':in' ]: element.value, - }, - ] ); - } + dataView.setColumnFilters( [ + ...otherFilters, + { + [ filter.field + ':in' ]: + isActive + ? undefined + : element.value, + }, + ] ); } } > { element.label } From 3b380b0917e2b39a1bd30e9228f37669e7c0c7f6 Mon Sep 17 00:00:00 2001 From: Birgit Pauli-Haack Date: Wed, 22 Nov 2023 12:20:06 +0100 Subject: [PATCH 04/51] Update Readme.txt tested up to 6.4 (#56427) * fixes wrong link in #56084 * update 'tested up to' in readme.txt of GB plugin --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 668ccca48a5dc..8ebcfd1406b0d 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === Gutenberg === Contributors: matveb, joen, karmatosed -Tested up to: 6.3 +Tested up to: 6.4 Stable tag: V.V.V License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html From 6e532f444a72d997b09441197caade90c49f19f3 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 22 Nov 2023 13:31:02 +0200 Subject: [PATCH 05/51] Add align support to the image block - alternative (#55954) * only remove the alignment control * use an effect to reset width, height, aspect ratio and cover when align is wide or full * try a filter on block attributes when align control updates attributes * new fixtures for the default align attribute of core/image * updated snapshots * modify the filter to always return the same shape of object, update naming * remove filter, add undo skip * update the react native component * Remove align from custom image attributes This allows the block supports to add the attribute instead keeping things cleaner. * Fix tests * Fix another fixture --------- Co-authored-by: Alex Lende --- docs/reference-guides/core-blocks.md | 4 +- .../test/__snapshots__/align.native.js.snap | 10 ++--- packages/block-library/src/image/block.json | 4 +- packages/block-library/src/image/edit.js | 37 ++++++++----------- .../block-library/src/image/edit.native.js | 35 +++++++++--------- packages/block-library/src/image/image.js | 22 ----------- .../src/mobile/utils/alignments.native.js | 1 + .../blocks-raw-handling.test.js.snap | 6 +-- .../blocks/core__image__center-caption.json | 4 +- ...ed-v2-add-is-resized-class.serialized.html | 2 +- ...cated-v3-add-align-wrapper.serialized.html | 2 +- ...ed-v4-remove-align-wrapper.serialized.html | 2 +- ...-v6-add-style-width-height.serialized.html | 2 +- .../fixtures/documents/wordpress-out.html | 2 +- 14 files changed, 52 insertions(+), 81 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 0ae5979b79704..10f0f76d9eb0d 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -378,8 +378,8 @@ Insert an image to make a visual statement. ([Source](https://github.com/WordPre - **Name:** core/image - **Category:** media -- **Supports:** anchor, color (~~background~~, ~~text~~), filter (duotone) -- **Attributes:** align, alt, aspectRatio, caption, height, href, id, lightbox, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width +- **Supports:** align (center, full, left, right, wide), anchor, color (~~background~~, ~~text~~), filter (duotone) +- **Attributes:** alt, aspectRatio, caption, height, href, id, lightbox, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width ## Latest Comments diff --git a/packages/block-editor/src/hooks/test/__snapshots__/align.native.js.snap b/packages/block-editor/src/hooks/test/__snapshots__/align.native.js.snap index 2782d6ae0b984..045fb0e3bd944 100644 --- a/packages/block-editor/src/hooks/test/__snapshots__/align.native.js.snap +++ b/packages/block-editor/src/hooks/test/__snapshots__/align.native.js.snap @@ -19,25 +19,25 @@ exports[`Align options for group block sets Wide width option 1`] = ` `; exports[`Align options for media block sets Align center option 1`] = ` -" +"
" `; exports[`Align options for media block sets Align left option 1`] = ` -" +"
" `; exports[`Align options for media block sets Align right option 1`] = ` -" +"
" `; exports[`Align options for media block sets Full width option 1`] = ` -" +"
" `; @@ -49,7 +49,7 @@ exports[`Align options for media block sets None option 1`] = ` `; exports[`Align options for media block sets Wide width option 1`] = ` -" +"
" `; diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index d665a8a8f7708..b46829e5059a2 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -9,9 +9,6 @@ "keywords": [ "img", "photo", "picture" ], "textdomain": "default", "attributes": { - "align": { - "type": "string" - }, "url": { "type": "string", "source": "attribute", @@ -95,6 +92,7 @@ } }, "supports": { + "align": [ "left", "center", "right", "wide", "full" ], "anchor": true, "color": { "text": false, diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index c58a96e594911..d189af32efcbe 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -10,8 +10,6 @@ import { getBlobByURL, isBlobURL, revokeBlobURL } from '@wordpress/blob'; import { Placeholder } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { - BlockAlignmentControl, - BlockControls, BlockIcon, MediaPlaceholder, useBlockProps, @@ -106,13 +104,13 @@ export function ImageEdit( { url = '', alt, caption, - align, id, width, height, sizeSlug, aspectRatio, scale, + align, } = attributes; const [ temporaryURL, setTemporaryURL ] = useState(); @@ -126,6 +124,21 @@ export function ImageEdit( { captionRef.current = caption; }, [ caption ] ); + const { __unstableMarkNextChangeAsNotPersistent } = + useDispatch( blockEditorStore ); + + useEffect( () => { + if ( [ 'wide', 'full' ].includes( align ) ) { + __unstableMarkNextChangeAsNotPersistent(); + setAttributes( { + width: undefined, + height: undefined, + aspectRatio: undefined, + scale: undefined, + } ); + } + }, [ align ] ); + const ref = useRef(); const { imageDefaultSize, mediaUpload } = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); @@ -255,16 +268,6 @@ export function ImageEdit( { } } - function updateAlignment( nextAlign ) { - const extraUpdatedAttributes = [ 'wide', 'full' ].includes( nextAlign ) - ? { width: undefined, height: undefined } - : {}; - setAttributes( { - ...extraUpdatedAttributes, - align: nextAlign, - } ); - } - let isTemp = isTemporaryImage( id, url ); // Upload a temporary image on mount. @@ -375,14 +378,6 @@ export function ImageEdit( { clientId={ clientId } blockEditingMode={ blockEditingMode } /> - { ! url && blockEditingMode === 'default' && ( - - - - ) } } onSelect={ onSelectImage } diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 804ae9e1671f6..44ebfda67d875 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -44,7 +44,6 @@ import { MEDIA_TYPE_IMAGE, BlockControls, InspectorControls, - BlockAlignmentToolbar, BlockStyles, store as blockEditorStore, blockSettingsScreens, @@ -212,7 +211,6 @@ export class ImageEdit extends Component { this.onSetFeatured = this.onSetFeatured.bind( this ); this.onFocusCaption = this.onFocusCaption.bind( this ); this.onSelectURL = this.onSelectURL.bind( this ); - this.updateAlignment = this.updateAlignment.bind( this ); this.accessibilityLabelCreator = this.accessibilityLabelCreator.bind( this ); this.setMappedAttributes = this.setMappedAttributes.bind( this ); @@ -305,6 +303,20 @@ export class ImageEdit extends Component { this.replacedFeaturedImage = false; setFeaturedImage( id ); } + + const { align } = attributes; + const { __unstableMarkNextChangeAsNotPersistent } = this.props; + + // Update the attributes if the align is wide or full + if ( [ 'wide', 'full' ].includes( align ) ) { + __unstableMarkNextChangeAsNotPersistent(); + setAttributes( { + width: undefined, + height: undefined, + aspectRatio: undefined, + scale: undefined, + } ); + } } static getDerivedStateFromProps( props, state ) { @@ -391,18 +403,6 @@ export class ImageEdit extends Component { } ); } - updateAlignment( nextAlign ) { - const extraUpdatedAttributes = Object.values( - WIDE_ALIGNMENTS.alignments - ).includes( nextAlign ) - ? { width: undefined, height: undefined } - : {}; - this.props.setAttributes( { - ...extraUpdatedAttributes, - align: nextAlign, - } ); - } - onSetNewTab( value ) { const updatedLinkTarget = getUpdatedLinkTargetSettings( value, @@ -711,10 +711,6 @@ export class ImageEdit extends Component { onClick={ open } /> - ); @@ -941,8 +937,11 @@ export default compose( [ } ), withDispatch( ( dispatch ) => { const { createErrorNotice } = dispatch( noticesStore ); + const { __unstableMarkNextChangeAsNotPersistent } = + dispatch( blockEditorStore ); return { + __unstableMarkNextChangeAsNotPersistent, createErrorNotice, closeSettingsBottomSheet() { dispatch( editPostStore ).closeGeneralSidebar(); diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 64eb03adedb32..11d460efd472c 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -25,7 +25,6 @@ import { MediaReplaceFlow, store as blockEditorStore, useSettings, - BlockAlignmentControl, __experimentalImageEditor as ImageEditor, __experimentalGetElementClassName, __experimentalUseBorderProps as useBorderProps, @@ -353,21 +352,6 @@ export default function Image( { } ); } - function updateAlignment( nextAlign ) { - const extraUpdatedAttributes = [ 'wide', 'full' ].includes( nextAlign ) - ? { - width: undefined, - height: undefined, - aspectRatio: undefined, - scale: undefined, - } - : {}; - setAttributes( { - ...extraUpdatedAttributes, - align: nextAlign, - } ); - } - useEffect( () => { if ( ! isSelected ) { setIsEditingImage( false ); @@ -455,12 +439,6 @@ export default function Image( { const controls = ( <> - { hasNonContentControls && ( - - ) } { hasNonContentControls && ( { diff --git a/packages/components/src/mobile/utils/alignments.native.js b/packages/components/src/mobile/utils/alignments.native.js index 98635ea4681ad..bc42385988a5d 100644 --- a/packages/components/src/mobile/utils/alignments.native.js +++ b/packages/components/src/mobile/utils/alignments.native.js @@ -10,6 +10,7 @@ export const WIDE_ALIGNMENTS = { }, excludeBlocks: [ 'core/heading' ], notInnerContainers: [ + 'core/image', 'core/separator', 'core/media-text', 'core/pullquote', diff --git a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap index 32f2dab713766..071870a420817 100644 --- a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap +++ b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap @@ -158,19 +158,19 @@ exports[`rawHandler should convert HTML post to blocks with minimal content chan `; exports[`rawHandler should convert a caption shortcode 1`] = ` -" +"
test
" `; exports[`rawHandler should convert a caption shortcode with caption 1`] = ` -" +"
test
" `; exports[`rawHandler should convert a caption shortcode with link 1`] = ` -" +"
Bell on Wharf
Bell on wharf in San Francisco
" `; diff --git a/test/integration/fixtures/blocks/core__image__center-caption.json b/test/integration/fixtures/blocks/core__image__center-caption.json index a369e433b4028..034047c07089b 100644 --- a/test/integration/fixtures/blocks/core__image__center-caption.json +++ b/test/integration/fixtures/blocks/core__image__center-caption.json @@ -3,10 +3,10 @@ "name": "core/image", "isValid": true, "attributes": { - "align": "center", "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==", "alt": "", - "caption": "Give it a try. Press the \"really wide\" button on the image toolbar." + "caption": "Give it a try. Press the \"really wide\" button on the image toolbar.", + "align": "center" }, "innerBlocks": [] } diff --git a/test/integration/fixtures/blocks/core__image__deprecated-v2-add-is-resized-class.serialized.html b/test/integration/fixtures/blocks/core__image__deprecated-v2-add-is-resized-class.serialized.html index 9a66da6c01898..c03189e9b456c 100644 --- a/test/integration/fixtures/blocks/core__image__deprecated-v2-add-is-resized-class.serialized.html +++ b/test/integration/fixtures/blocks/core__image__deprecated-v2-add-is-resized-class.serialized.html @@ -1,3 +1,3 @@ - +
diff --git a/test/integration/fixtures/blocks/core__image__deprecated-v3-add-align-wrapper.serialized.html b/test/integration/fixtures/blocks/core__image__deprecated-v3-add-align-wrapper.serialized.html index 9a66da6c01898..c03189e9b456c 100644 --- a/test/integration/fixtures/blocks/core__image__deprecated-v3-add-align-wrapper.serialized.html +++ b/test/integration/fixtures/blocks/core__image__deprecated-v3-add-align-wrapper.serialized.html @@ -1,3 +1,3 @@ - +
diff --git a/test/integration/fixtures/blocks/core__image__deprecated-v4-remove-align-wrapper.serialized.html b/test/integration/fixtures/blocks/core__image__deprecated-v4-remove-align-wrapper.serialized.html index 99da2155bce88..b9e58cc24fddb 100644 --- a/test/integration/fixtures/blocks/core__image__deprecated-v4-remove-align-wrapper.serialized.html +++ b/test/integration/fixtures/blocks/core__image__deprecated-v4-remove-align-wrapper.serialized.html @@ -1,3 +1,3 @@ - +
diff --git a/test/integration/fixtures/blocks/core__image__deprecated-v6-add-style-width-height.serialized.html b/test/integration/fixtures/blocks/core__image__deprecated-v6-add-style-width-height.serialized.html index 807ba3abc9f9c..57545968847e1 100644 --- a/test/integration/fixtures/blocks/core__image__deprecated-v6-add-style-width-height.serialized.html +++ b/test/integration/fixtures/blocks/core__image__deprecated-v6-add-style-width-height.serialized.html @@ -1,3 +1,3 @@ - +
diff --git a/test/integration/fixtures/documents/wordpress-out.html b/test/integration/fixtures/documents/wordpress-out.html index c394fa232081d..a0ac4b89ec552 100644 --- a/test/integration/fixtures/documents/wordpress-out.html +++ b/test/integration/fixtures/documents/wordpress-out.html @@ -28,7 +28,7 @@

Shortcode

- +
From 77d0226badb0769b12e28b19fb439cf6777b672a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20K=C3=A4gy?= Date: Wed, 22 Nov 2023 12:53:32 +0100 Subject: [PATCH 06/51] fix remove removal version from deprecated prop (#56336) --- packages/components/src/angle-picker-control/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/components/src/angle-picker-control/index.tsx b/packages/components/src/angle-picker-control/index.tsx index f90394b12078f..06178e0b40101 100644 --- a/packages/components/src/angle-picker-control/index.tsx +++ b/packages/components/src/angle-picker-control/index.tsx @@ -41,7 +41,6 @@ function UnforwardedAnglePickerControl( 'Bottom margin styles for wp.components.AnglePickerControl', { since: '6.1', - version: '6.4', hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version.', } ); From c3f00773cf989153c7b5f42e0cd3fab0399ca6fd Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:37:36 +0900 Subject: [PATCH 07/51] NavigableContainers: Fix doc typo in onKeyDown prop (#56352) * NavigableContainers: Fix doc typo in onKeyDown prop * Update changelog * Remove changelog --- packages/components/src/navigable-container/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/navigable-container/README.md b/packages/components/src/navigable-container/README.md index a982219248f50..bbc1f16dcb8f6 100644 --- a/packages/components/src/navigable-container/README.md +++ b/packages/components/src/navigable-container/README.md @@ -24,7 +24,7 @@ Gets an offset, given an event. - Required: No -### `onKeydown`: `( event: KeyboardEvent ) => void` +### `onKeyDown`: `( event: KeyboardEvent ) => void` A callback invoked on the keydown event. From 3539a97717b684bb93907f0e8f915842610098d3 Mon Sep 17 00:00:00 2001 From: Maggie Date: Wed, 22 Nov 2023 13:38:19 +0100 Subject: [PATCH 08/51] Improve tooltip for parent blocks on the block toolbar (#56146) * improve tolltip for parent blocks on the block toolbar * fixed tests * missing test * another missing test * fixed another test --- .../src/components/block-parent-selector/index.js | 2 +- packages/block-library/src/cover/test/edit.js | 2 +- .../specs/editor/various/pattern-blocks.test.js | 2 +- test/e2e/specs/editor/blocks/list.spec.js | 12 ++++++------ .../plugins/inner-blocks-allowed-blocks.spec.js | 12 +++++++++--- .../editor/various/toolbar-roving-tabindex.spec.js | 6 +++--- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/block-parent-selector/index.js b/packages/block-editor/src/components/block-parent-selector/index.js index 31e0b1b8fd8cf..80b314eeb42e5 100644 --- a/packages/block-editor/src/components/block-parent-selector/index.js +++ b/packages/block-editor/src/components/block-parent-selector/index.js @@ -74,7 +74,7 @@ export default function BlockParentSelector() { onClick={ () => selectBlock( firstParentClientId ) } label={ sprintf( /* translators: %s: Name of the block's parent. */ - __( 'Select %s' ), + __( 'Select parent block: %s' ), blockInformation?.title ) } showTooltip diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index d1febe3c6fa11..879b77636255a 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -53,7 +53,7 @@ async function createAndSelectBlock() { ); await userEvent.click( screen.getByRole( 'button', { - name: 'Select Cover', + name: 'Select parent block: Cover', } ) ); } diff --git a/packages/e2e-tests/specs/editor/various/pattern-blocks.test.js b/packages/e2e-tests/specs/editor/various/pattern-blocks.test.js index cb5187a390e8b..0d00e3d9a545b 100644 --- a/packages/e2e-tests/specs/editor/various/pattern-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/pattern-blocks.test.js @@ -350,7 +350,7 @@ describe( 'Pattern blocks', () => { expect( reusableBlockWithParagraph ).toBeTruthy(); // Convert back to regular blocks. - await clickBlockToolbarButton( 'Select Edited block' ); + await clickBlockToolbarButton( 'Select parent block: Edited block' ); await clickBlockToolbarButton( 'Options' ); await clickMenuItem( 'Detach' ); await page.waitForXPath( selector, { diff --git a/test/e2e/specs/editor/blocks/list.spec.js b/test/e2e/specs/editor/blocks/list.spec.js index f10a266a41e65..48d50a862a50b 100644 --- a/test/e2e/specs/editor/blocks/list.spec.js +++ b/test/e2e/specs/editor/blocks/list.spec.js @@ -354,7 +354,7 @@ test.describe( 'List (@firefox)', () => { await page.keyboard.type( 'one' ); await page.keyboard.press( 'Enter' ); await page.keyboard.type( 'two' ); - await editor.clickBlockToolbarButton( 'Select List' ); + await editor.clickBlockToolbarButton( 'Select parent block: List' ); await editor.transformBlockTo( 'core/paragraph' ); await expect.poll( editor.getEditedPostContent ).toBe( @@ -397,7 +397,7 @@ test.describe( 'List (@firefox)', () => { await page.keyboard.type( 'one' ); await page.keyboard.press( 'Enter' ); await page.keyboard.type( 'two' ); - await editor.clickBlockToolbarButton( 'Select List' ); + await editor.clickBlockToolbarButton( 'Select parent block: List' ); await editor.transformBlockTo( 'core/quote' ); await expect.poll( editor.getEditedPostContent ).toBe( @@ -674,7 +674,7 @@ test.describe( 'List (@firefox)', () => { test( 'should change the base list type', async ( { editor } ) => { await editor.insertBlock( { name: 'core/list' } ); - await editor.clickBlockToolbarButton( 'Select List' ); + await editor.clickBlockToolbarButton( 'Select parent block: List' ); await editor.clickBlockToolbarButton( 'Ordered' ); await expect.poll( editor.getEditedPostContent ).toBe( ` @@ -694,7 +694,7 @@ test.describe( 'List (@firefox)', () => { await page.keyboard.press( 'Enter' ); await editor.clickBlockToolbarButton( 'Indent' ); await page.keyboard.type( '1' ); - await editor.clickBlockToolbarButton( 'Select List' ); + await editor.clickBlockToolbarButton( 'Select parent block: List' ); await editor.clickBlockToolbarButton( 'Ordered' ); await expect.poll( editor.getEditedPostContent ).toBe( @@ -1232,7 +1232,7 @@ test.describe( 'List (@firefox)', () => { await page.keyboard.type( '2' ); await page.keyboard.press( 'Enter' ); await page.keyboard.type( '3' ); - await editor.clickBlockToolbarButton( 'Select List' ); + await editor.clickBlockToolbarButton( 'Select parent block: List' ); await editor.clickBlockToolbarButton( 'Ordered' ); await expect.poll( editor.getEditedPostContent ).toBe( @@ -1264,7 +1264,7 @@ test.describe( 'List (@firefox)', () => { await page.keyboard.type( 'b' ); await page.keyboard.press( 'Enter' ); await page.keyboard.type( 'c' ); - await editor.clickBlockToolbarButton( 'Select List' ); + await editor.clickBlockToolbarButton( 'Select parent block: List' ); await editor.clickBlockToolbarButton( 'Unordered' ); await expect.poll( editor.getEditedPostContent ).toBe( diff --git a/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js b/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js index c0627121f1649..eaf171adf9313 100644 --- a/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js +++ b/test/e2e/specs/editor/plugins/inner-blocks-allowed-blocks.spec.js @@ -130,13 +130,17 @@ test.describe( 'Allowed Blocks Setting on InnerBlocks', () => { await blockListBox.getByRole( 'option', { name: 'List' } ).click(); // Select the list wrapper and then parent block. await page.keyboard.press( 'ArrowUp' ); - await editor.clickBlockToolbarButton( 'Select Allowed Blocks Dynamic' ); + await editor.clickBlockToolbarButton( + 'Select parent block: Allowed Blocks Dynamic' + ); // Insert the image. await blockAppender.click(); await blockListBox.getByRole( 'option', { name: 'Image' } ).click(); - await editor.clickBlockToolbarButton( 'Select Allowed Blocks Dynamic' ); + await editor.clickBlockToolbarButton( + 'Select parent block: Allowed Blocks Dynamic' + ); await blockAppender.click(); // It should display a different allowed block list. @@ -147,7 +151,9 @@ test.describe( 'Allowed Blocks Setting on InnerBlocks', () => { await blockListBox.getByRole( 'option', { name: 'Gallery' } ).click(); - await editor.clickBlockToolbarButton( 'Select Allowed Blocks Dynamic' ); + await editor.clickBlockToolbarButton( + 'Select parent block: Allowed Blocks Dynamic' + ); await blockAppender.click(); // It should display a different allowed block list. diff --git a/test/e2e/specs/editor/various/toolbar-roving-tabindex.spec.js b/test/e2e/specs/editor/various/toolbar-roving-tabindex.spec.js index e706dfc3607dc..70509348983e6 100644 --- a/test/e2e/specs/editor/various/toolbar-roving-tabindex.spec.js +++ b/test/e2e/specs/editor/various/toolbar-roving-tabindex.spec.js @@ -59,9 +59,9 @@ test.describe( 'Toolbar roving tabindex', () => { await page.keyboard.type( 'List' ); await ToolbarRovingTabindexUtils.testBlockToolbarKeyboardNavigation( 'List text', - 'Select List' + 'Select parent block: List' ); - await page.click( `role=button[name="Select List"i]` ); + await page.click( `role=button[name="Select parent block: List"i]` ); await ToolbarRovingTabindexUtils.wrapCurrentBlockWithGroup( 'List' ); await ToolbarRovingTabindexUtils.testGroupKeyboardNavigation( 'Block: List', @@ -201,7 +201,7 @@ class ToolbarRovingTabindexUtils { await this.page.keyboard.press( 'ArrowRight' ); await this.expectLabelToHaveFocus( currentBlockLabel ); await this.pageUtils.pressKeys( 'shift+Tab' ); - await this.expectLabelToHaveFocus( 'Select Group' ); + await this.expectLabelToHaveFocus( 'Select parent block: Group' ); await this.page.keyboard.press( 'ArrowRight' ); await this.expectLabelToHaveFocus( currentBlockTitle ); } From c5ac49093e11ee641f8599fe47d2276820d429ef Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:08:09 -0300 Subject: [PATCH 09/51] PostCSS style transformation: fail gracefully instead of throwing an error (#56093) * PostCSS style transformation: fail gracefully instead of throwing error * Display better warning messages --- .../src/utils/test/transform-styles.js | 49 +++++++++++++++++++ .../src/utils/transform-styles/index.js | 44 ++++++++++++----- 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/packages/block-editor/src/utils/test/transform-styles.js b/packages/block-editor/src/utils/test/transform-styles.js index f162a0b2f6048..38eaa1947d2a8 100644 --- a/packages/block-editor/src/utils/test/transform-styles.js +++ b/packages/block-editor/src/utils/test/transform-styles.js @@ -4,6 +4,55 @@ import transformStyles from '../transform-styles'; describe( 'transformStyles', () => { + describe( 'error handling', () => { + beforeEach( () => { + // Intentionally suppress the expected console errors and warnings to reduce + // noise in the test output. + jest.spyOn( console, 'warn' ).mockImplementation( jest.fn() ); + } ); + + it( 'should not throw error in case of invalid css', () => { + const run = () => + transformStyles( + [ + { + css: 'h1 { color: red;', // invalid CSS + }, + ], + '.my-namespace' + ); + + expect( run ).not.toThrow(); + expect( console ).toHaveWarned(); + } ); + + it( 'should warn invalid css in the console', () => { + const run = () => + transformStyles( + [ + { + css: 'h1 { color: red; }', // valid CSS + }, + { + css: 'h1 { color: red;', // invalid CSS + }, + ], + '.my-namespace' + ); + + const [ validCSS, invalidCSS ] = run(); + + expect( validCSS ).toBe( '.my-namespace h1 { color: red; }' ); + expect( invalidCSS ).toBe( null ); + + expect( console ).toHaveWarnedWith( + 'wp.blockEditor.transformStyles Failed to transform CSS.', + ':1:1: Unclosed block\n> 1 | h1 { color: red;\n | ^' + // ^^^^ In PostCSS, a tab is equal four spaces + ); + } ); + } ); + describe( 'selector wrap', () => { it( 'should wrap regular selectors', () => { const input = `h1 { color: red; }`; diff --git a/packages/block-editor/src/utils/transform-styles/index.js b/packages/block-editor/src/utils/transform-styles/index.js index 8f5e1702307a4..4da6f6ce23795 100644 --- a/packages/block-editor/src/utils/transform-styles/index.js +++ b/packages/block-editor/src/utils/transform-styles/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import postcss from 'postcss'; +import postcss, { CssSyntaxError } from 'postcss'; import wrap from 'postcss-prefixwrap'; import rebaseUrl from 'postcss-urlrebase'; @@ -19,18 +19,36 @@ import rebaseUrl from 'postcss-urlrebase'; */ const transformStyles = ( styles, wrapperSelector = '' ) => { return styles.map( ( { css, ignoredSelectors = [], baseURL } ) => { - return postcss( - [ - wrapperSelector && - wrap( wrapperSelector, { - ignoredSelectors: [ - ...ignoredSelectors, - wrapperSelector, - ], - } ), - baseURL && rebaseUrl( { rootUrl: baseURL } ), - ].filter( Boolean ) - ).process( css, {} ).css; // use sync PostCSS API + try { + return postcss( + [ + wrapperSelector && + wrap( wrapperSelector, { + ignoredSelectors: [ + ...ignoredSelectors, + wrapperSelector, + ], + } ), + baseURL && rebaseUrl( { rootUrl: baseURL } ), + ].filter( Boolean ) + ).process( css, {} ).css; // use sync PostCSS API + } catch ( error ) { + if ( error instanceof CssSyntaxError ) { + // eslint-disable-next-line no-console + console.warn( + 'wp.blockEditor.transformStyles Failed to transform CSS.', + error.message + '\n' + error.showSourceCode( false ) + ); + } else { + // eslint-disable-next-line no-console + console.warn( + 'wp.blockEditor.transformStyles Failed to transform CSS.', + error + ); + } + + return null; + } } ); }; From f73f8d2ae1e4769ccac645c4f6ae0819729f6926 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 22 Nov 2023 15:03:55 +0100 Subject: [PATCH 10/51] Documentation: Add the attributes definition page to the create block tutorial of the platform docs (#56429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Héctor <27339341+priethor@users.noreply.github.com> --- platform-docs/docs/create-block/attributes.md | 86 ++++++++++++++++++- .../docs/create-block/block-supports.md | 2 +- .../docs/create-block/using-styles.md | 2 +- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/platform-docs/docs/create-block/attributes.md b/platform-docs/docs/create-block/attributes.md index 044b326ae54a5..a2da8ee5c3694 100644 --- a/platform-docs/docs/create-block/attributes.md +++ b/platform-docs/docs/create-block/attributes.md @@ -1,5 +1,87 @@ --- -sidebar_position: 4 +sidebar_position: 2 --- -# Block attributes \ No newline at end of file +# Block Attributes + +Attributes are the way a block stores data, they define the structure of a block. Upon serialization, some attributes are saved into the HTML output while others are kept in a the HTML block comment delimiters. + +For this block tutorial, we want to allow the user to type a message that we will display stylized in the saved content. So, we need to add a **message** attribute that will hold the user message. The following code defines a **message** attribute; the attribute type is a string. When serializing the blocks, the message will be saved within a `div`container. This means that we're going to source the value attribute using `text` source from the selector, which is a `div` tag. + +```js +const attributes = { + message: { + type: 'string', + source: 'text', + selector: 'div', + 'default': '' + } +}; +``` + +Add this to the settings arguments of the `registerBlockType` function call. + +**Note:** The text source is equivalent to `innerText` attribute of a DOM element. + +## Edit and Save + +The **attributes** are passed to both the `edit` and `save` functions. The **setAttributes** function is also passed, but only to the `edit` function. The **setAttributes** function is used to set the values. + +The `attributes` is a JavaScript object containing the values of each attribute, or default values if defined. The `setAttributes` is a function to update an attribute. + +```js +function Edit( { attributes, setAttributes } ) { + // ... +} + +function Save( { attributes } ) { + // ... +} + +registerBlockType( 'gutenpride/gutenpride-block', { + // ... + attributes, + edit: Edit, + save: Save, +} ); +``` + +## TextControl Component + +For our example block, the component we are going to use is the **TextControl** component, which is similar to an HTML text input field. You can see [the documentation for the `TextControl` component](https://developer.wordpress.org/block-editor/reference-guides/components/text-control/). You can browse an [interactive set of components in this Storybook](https://wordpress.github.io/gutenberg/). + +The component is added similar to an HTML tag, setting a label, the `value` is set to the `attributes.message` and the `onChange` function uses the `setAttributes` to update the message attribute value. + +The save function will simply write the `attributes.message` as a `div` tag since that is how we defined it to be parsed. Update the `edit.js` and `save.js` files to the following, replacing the existing functions. + +**edit.js** file: + +```js +import { useBlockProps } from '@wordpress/block-editor'; +import { TextControl } from '@wordpress/components'; + +function Edit( { attributes, setAttributes } ) { + return ( +
+ setAttributes( { message: val } ) } + /> +
+ ); +} +``` + +**save.js** file: + +```jsx +import { useBlockProps } from '@wordpress/block-editor'; + +function Save( { attributes } ) { + const blockProps = useBlockProps.save(); + return
{ attributes.message }
; +} +``` + +Reload the editor and add the block. You can now type a message in the editor and it will be included in the serialized HTML output. diff --git a/platform-docs/docs/create-block/block-supports.md b/platform-docs/docs/create-block/block-supports.md index 20cfccebd4b05..4a245f210d654 100644 --- a/platform-docs/docs/create-block/block-supports.md +++ b/platform-docs/docs/create-block/block-supports.md @@ -1,3 +1,3 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- diff --git a/platform-docs/docs/create-block/using-styles.md b/platform-docs/docs/create-block/using-styles.md index 1d5ac2bcd0721..c8d1bb91d5961 100644 --- a/platform-docs/docs/create-block/using-styles.md +++ b/platform-docs/docs/create-block/using-styles.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 --- # Using styles and stylesheets \ No newline at end of file From fbc962cc618775a8df9d2a6b36b4785010dd0e14 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 22 Nov 2023 23:20:33 +0900 Subject: [PATCH 11/51] Theme JSON schema: add heading/button key to color definition (#55674) * Theme JSON schema: add heading/button key to color definition * Update docs * Add "in a block" --- .../theme-json-reference/theme-json-living.md | 2 ++ schemas/json/theme.json | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 4890386ca8333..492cdaf089cc4 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -95,6 +95,8 @@ Settings related to colors. | link | boolean | false | | | palette | array | | color, name, slug | | text | boolean | true | | +| heading | boolean | true | | +| button | boolean | true | | --- diff --git a/schemas/json/theme.json b/schemas/json/theme.json index 5a24f1b16c1a3..68c649e337d82 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -200,7 +200,7 @@ } }, "link": { - "description": "Allow users to set link colors.", + "description": "Allow users to set link colors in a block.", "type": "boolean", "default": false }, @@ -228,7 +228,17 @@ } }, "text": { - "description": "Allow users to set text colors.", + "description": "Allow users to set text colors in a block.", + "type": "boolean", + "default": true + }, + "heading": { + "description": "Allow users to set heading colors in a block.", + "type": "boolean", + "default": true + }, + "button": { + "description": "Allow users to set button colors in a block.", "type": "boolean", "default": true } From 8b59123df5e19a95142ef0e299d0713e99a129da Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 22 Nov 2023 18:33:58 +0400 Subject: [PATCH 12/51] Playwright Utils: Fix the method of getting post ID in 'publishPost' (#56421) * Playwright Utils: Fix the method of getting post ID in 'publishPost' * Update sidebar permalink e2e test --- .../src/editor/publish-post.ts | 11 +++++------ .../specs/editor/various/sidebar-permalink.spec.js | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/e2e-test-utils-playwright/src/editor/publish-post.ts b/packages/e2e-test-utils-playwright/src/editor/publish-post.ts index 09cca7417c4de..0a2b9e64dc597 100644 --- a/packages/e2e-test-utils-playwright/src/editor/publish-post.ts +++ b/packages/e2e-test-utils-playwright/src/editor/publish-post.ts @@ -28,12 +28,11 @@ export async function publishPost( this: Editor ) { 'role=region[name="Editor publish"i] >> role=button[name="Publish"i]' ); - const urlString = await this.page - .getByRole( 'region', { name: 'Editor publish' } ) - .getByRole( 'textbox', { name: 'address' } ) - .inputValue(); - const url = new URL( urlString ); - const postId = url.searchParams.get( 'p' ); + await this.page + .getByRole( 'button', { name: 'Dismiss this notice' } ) + .filter( { hasText: 'published' } ) + .waitFor(); + const postId = new URL( this.page.url() ).searchParams.get( 'post' ); return typeof postId === 'string' ? parseInt( postId, 10 ) : null; } diff --git a/test/e2e/specs/editor/various/sidebar-permalink.spec.js b/test/e2e/specs/editor/various/sidebar-permalink.spec.js index dcc16844d424a..96283e4b6b15f 100644 --- a/test/e2e/specs/editor/various/sidebar-permalink.spec.js +++ b/test/e2e/specs/editor/various/sidebar-permalink.spec.js @@ -48,7 +48,7 @@ test.describe( 'Sidebar Permalink', () => { await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) .fill( 'aaaaa' ); - await editor.saveDraft(); + await editor.publishPost(); // Start editing again. await editor.canvas .getByRole( 'textbox', { name: 'Add title' } ) From 57f117111c5f043bb89c0790d3759461a539bb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:20:57 +0100 Subject: [PATCH 13/51] Documentation: add new section to release docs about troubleshooting the release (#56436) --- docs/contributors/code/release.md | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/contributors/code/release.md b/docs/contributors/code/release.md index 8c8ed3ff3c334..d19be240f4870 100644 --- a/docs/contributors/code/release.md +++ b/docs/contributors/code/release.md @@ -25,6 +25,7 @@ Similar requirements apply to releasing WordPress's [npm packages](https://devel - [Automated cherry-picking](#automated-cherry-picking) - [Manual cherry-picking](#manual-cherry-picking) - [Publishing the release](#publishing-the-release) + - [Troubleshooting the release](#troubleshooting-the-release) - [Documenting the release](#documenting-the-release) - [Selecting the release highlights](#selecting-the-release-highlights) - [Requesting release assets](#requesting-release-assets) @@ -253,6 +254,41 @@ Once approved, the new Gutenberg version will be available to WordPress users al The final step is to write a release post on [make.wordpress.org/core](https://make.wordpress.org/core/). You can find some tips on that below. +#### Troubleshooting the release + +> The plugin was published to the WordPress.org plugin directory but the workflow failed. + +This has happened ocassionally, see [this one](https://github.com/WordPress/gutenberg/actions/runs/6955409957/job/18924124118) for example. + +It's important to check that: + +- the plugin from the directory works as expected +- the ZIP contents (see [Downloads](https://plugins.trac.wordpress.org/browser/gutenberg/)) looks correct (doesn't have anything obvious missing) +- the [Gutenberg SVN repo](https://plugins.trac.wordpress.org/browser/gutenberg/) has two new commits (see [the log](https://plugins.trac.wordpress.org/browser/gutenberg/)): + - the `trunk` folder should have "Commiting version X.Y.Z" + - there is a new `tags/X.Y.Z` folder with the same contents as `trunk` whose latest commit is "Tagging version X.Y.Z" + +Most likely, the tag folder couldn't be created. This is a [known issue](https://plugins.trac.wordpress.org/browser/gutenberg/) that [can be fixed manually](https://github.com/WordPress/gutenberg/issues/55295#issuecomment-1759292978). + +Either substitute SVN_USERNAME, SVN_PASSWORD, and VERSION for the proper values or set them as global environment variables first: + +```sh +# CHECKOUT THE REPOSITORY +svn checkout https://plugins.svn.wordpress.org/gutenberg/trunk --username "$SVN_USERNAME" --password "$SVN_PASSWORD" gutenberg-svn + +# MOVE TO THE LOCAL FOLDER +cd gutenberg-svn + +# IF YOU HAPPEN TO HAVE ALREADY THE REPO LOCALLY +# AND DIDN'T CHECKOUT, MAKE SURE IT IS UPDATED +# svn up . + +# COPY CURRENT TRUNK INTO THE NEW TAGS FOLDER +svn copy https://plugins.svn.wordpress.org/gutenberg/trunk https://plugins.svn.wordpress.org/gutenberg/tags/$VERSION -m 'Tagging version $VERSION' --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" +``` + +Ask around if you need help with any of this. + ### Documenting the release Documenting the release is led by the release manager with the help of [Gutenberg development team](https://developer.wordpress.org/block-editor/block-editor/contributors/repository-management/#teams) members. This process is comprised of a series of sequential steps that, because of the number of people involved, and the coordination required, need to adhere to a timeline between the RC and stable releases. Stable Gutenberg releases happen on Wednesdays, one week after the initial RC. From 16945143459acfe7085834c6b7358d8a7eeaa03d Mon Sep 17 00:00:00 2001 From: Andrew Hayward Date: Wed, 22 Nov 2023 16:10:49 +0000 Subject: [PATCH 14/51] Migrating block editor `BlockPatternsList` component (#56210) - Removes `__unstableComposite` imports from `@wordpress/components` - Adds private `Composite*` exports from `@wordpress/components` - Refactors `BlockPatternsList` and `BlockPattern` to use updated `Composite` components - Additionally renames list component to be consistent with codebase --- .../components/block-patterns-list/README.md | 8 +-- .../components/block-patterns-list/index.js | 70 ++++++++++++------- .../components/block-patterns-list/style.scss | 7 ++ .../pattern-category-previews.js | 4 +- 4 files changed, 58 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/components/block-patterns-list/README.md b/packages/block-editor/src/components/block-patterns-list/README.md index 7b30dcecc7bbd..8b798f93b7190 100644 --- a/packages/block-editor/src/components/block-patterns-list/README.md +++ b/packages/block-editor/src/components/block-patterns-list/README.md @@ -1,6 +1,6 @@ # Block Patterns List -The `BlockPatternList` component makes a list of the different registered block patterns. It uses the `BlockPreview` component to display a preview for each block pattern. +The `BlockPatternsList` component makes a list of the different registered block patterns. It uses the `BlockPreview` component to display a preview for each block pattern. For more infos about blocks patterns, read [this](https://make.wordpress.org/core/2020/07/16/block-patterns-in-wordpress-5-5/). @@ -18,10 +18,10 @@ For more infos about blocks patterns, read [this](https://make.wordpress.org/cor Renders a block patterns list. ```jsx -import { BlockPatternList } from '@wordpress/block-editor'; +import { BlockPatternsList } from '@wordpress/block-editor'; -const MyBlockPatternList = () => ( - ( + { if ( showTooltip ) { return { children }; @@ -35,11 +40,11 @@ const WithToolTip = ( { showTooltip, title, children } ) => { }; function BlockPattern( { + id, isDraggable, pattern, onClick, onHover, - composite, showTooltip, } ) { const [ isDragging, setIsDragging ] = useState( false ); @@ -78,17 +83,27 @@ function BlockPattern( { title={ pattern.title } > + } + id={ id } onClick={ () => { onClick( pattern, blocks ); onHover?.( null ); @@ -100,10 +115,6 @@ function BlockPattern( { onHover?.( pattern ); } } onMouseLeave={ () => onHover?.( null ) } - aria-label={ pattern.title } - aria-describedby={ - pattern.description ? descriptionId : undefined - } > { + // We reset the active composite item whenever the + // available patterns change, to make sure that + // focus is put back to the start. + setActiveId( undefined ); + }, [ setActiveId, shownPatterns, blockPatterns ] ); + return ( ) : ( @@ -191,4 +211,4 @@ function BlockPatternList( ); } -export default forwardRef( BlockPatternList ); +export default forwardRef( BlockPatternsList ); diff --git a/packages/block-editor/src/components/block-patterns-list/style.scss b/packages/block-editor/src/components/block-patterns-list/style.scss index e3b38deff5ef7..8009dfbcce1f2 100644 --- a/packages/block-editor/src/components/block-patterns-list/style.scss +++ b/packages/block-editor/src/components/block-patterns-list/style.scss @@ -18,6 +18,13 @@ .block-editor-block-patterns-list__item { height: 100%; + // This is derived from the top padding set on + // `.block-editor-block-patterns-explorer__list` + scroll-margin-top: $grid-unit-30; + // This is derived from the bottom padding set on + // `.block-editor-block-patterns-explorer__list` and + // the bottom margin set on `...__list-item` above + scroll-margin-bottom: ($grid-unit-40 + $grid-unit-30); .block-editor-block-preview__container { display: flex; diff --git a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js index 76864a6a00ccc..9e5b6373e54d8 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js +++ b/packages/block-editor/src/components/inserter/block-patterns-tab/pattern-category-previews.js @@ -22,7 +22,7 @@ import { * Internal dependencies */ import usePatternsState from '../hooks/use-patterns-state'; -import BlockPatternList from '../../block-patterns-list'; +import BlockPatternsList from '../../block-patterns-list'; import usePatternsPaging from '../hooks/use-patterns-paging'; import { PatternsFilter } from './patterns-filter'; import { usePatternCategories } from './use-pattern-categories'; @@ -159,7 +159,7 @@ export function PatternCategoryPreviews( { { currentCategoryPatterns.length > 0 && ( - Date: Wed, 22 Nov 2023 17:48:15 +0100 Subject: [PATCH 15/51] Slot: add styles prop to bubblesVirtually version (#56428) * Slot: add `styles` prop to `bubblesVirtually` version * CHANHGELOG * Update CHANGELOG * Enhance clarity of JSDoc comments --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/slot-fill/README.md | 2 +- packages/components/src/slot-fill/types.ts | 24 +++++++++++++++------ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index eb6e595e304ec..cd1705d6cafd7 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,10 @@ - `Tabs`: Memoize and expose the component context ([#56224](https://github.com/WordPress/gutenberg/pull/56224)). +### Internal + +- `Slot`: add `style` prop to `bubblesVirtually` version ([#56428](https://github.com/WordPress/gutenberg/pull/56428)) + ## 25.12.0 (2023-11-16) ### Bug Fix diff --git a/packages/components/src/slot-fill/README.md b/packages/components/src/slot-fill/README.md index a04416bdee50d..9059566deefdf 100644 --- a/packages/components/src/slot-fill/README.md +++ b/packages/components/src/slot-fill/README.md @@ -68,7 +68,7 @@ Both `Slot` and `Fill` accept a `name` string prop, where a `Slot` with a given - By default, events will bubble to their parents on the DOM hierarchy (native event bubbling) - If `bubblesVirtually` is set to true, events will bubble to their virtual parent in the React elements hierarchy instead. -`Slot` with `bubblesVirtually` set to true also accept an optional `className` to add to the slot container. +`Slot` with `bubblesVirtually` set to true also accept optional `className` and `style` props to add to the slot container. `Slot` **without** `bubblesVirtually` accepts an optional `children` function prop, which takes `fills` as a param. It allows you to perform additional processing and wrap `fills` conditionally. diff --git a/packages/components/src/slot-fill/types.ts b/packages/components/src/slot-fill/types.ts index 763fa799c8d86..8abb9b941c527 100644 --- a/packages/components/src/slot-fill/types.ts +++ b/packages/components/src/slot-fill/types.ts @@ -36,15 +36,21 @@ export type SlotComponentProps = /** * A function that returns nodes to be rendered. - * Not supported when `bubblesVirtually` is true. + * Supported only when `bubblesVirtually` is `false`. */ children?: never; /** - * className. - * Not supported when `bubblesVirtually` is true. + * Additional className for the `Slot` component. + * Supported only when `bubblesVirtually` is `true`. */ className?: string; + + /** + * Additional styles for the `Slot` component. + * Supported only when `bubblesVirtually` is `true`. + */ + style?: React.CSSProperties; } ) | ( SlotPropBase & { /** @@ -56,15 +62,21 @@ export type SlotComponentProps = /** * A function that returns nodes to be rendered. - * Not supported when `bubblesVirtually` is true. + * Supported only when `bubblesVirtually` is `false`. */ children?: ( fills: ReactNode ) => ReactNode; /** - * className. - * Not supported when `bubblesVirtually` is false. + * Additional className for the `Slot` component. + * Supported only when `bubblesVirtually` is `true`. */ className?: never; + + /** + * Additional styles for the `Slot` component. + * Supported only when `bubblesVirtually` is `true`. + */ + style?: never; } ); export type FillComponentProps = { From 20975005ead870e5bb96a0544d9d5960ec8be7a4 Mon Sep 17 00:00:00 2001 From: Andrew Hayward Date: Wed, 22 Nov 2023 17:14:09 +0000 Subject: [PATCH 16/51] Add focus rings to focusable disabled buttons (#56383) Fixes the CSS to only remove borders from disabled secondary/tertiary buttons when they don't have focus --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/button/style.scss | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index cd1705d6cafd7..9a3beb0342396 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- `Button`: Add focus rings to focusable disabled buttons ([#56383](https://github.com/WordPress/gutenberg/pull/56383)). + ### Experimental - `Tabs`: Memoize and expose the component context ([#56224](https://github.com/WordPress/gutenberg/pull/56224)). diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index 03273056cfa17..4b11d9169a090 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -129,8 +129,11 @@ background: transparent; transform: none; opacity: 1; - box-shadow: none; - outline: none; + + &:not(:focus) { + box-shadow: none; + outline: none; + } } } From 564f23618997af9beb075f78bb265d28f9e0acc7 Mon Sep 17 00:00:00 2001 From: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com> Date: Wed, 22 Nov 2023 14:24:43 -0300 Subject: [PATCH 17/51] Additional CSS: fix on change validation (#56434) --- .../block-editor/src/components/global-styles/advanced-panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/global-styles/advanced-panel.js b/packages/block-editor/src/components/global-styles/advanced-panel.js index 4460de0351318..af43552c0a3eb 100644 --- a/packages/block-editor/src/components/global-styles/advanced-panel.js +++ b/packages/block-editor/src/components/global-styles/advanced-panel.js @@ -30,7 +30,7 @@ export default function AdvancedPanel( { } ); if ( cssError ) { const [ transformed ] = transformStyles( - [ { css: value } ], + [ { css: newValue } ], '.editor-styles-wrapper' ); if ( transformed ) { From e3a6917ff0353bba5d40660acb1bc273de2b2541 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 22 Nov 2023 22:27:08 +0400 Subject: [PATCH 18/51] Block Settings: Only display parent block selector on small screens (#56431) --- .../block-settings-dropdown.js | 72 ++++++++++--------- 1 file changed, 38 insertions(+), 34 deletions(-) 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 bb8e00d0c11db..4d43865a7f83a 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 @@ -20,7 +20,7 @@ import { store as keyboardShortcutsStore, __unstableUseShortcutEventMatch, } from '@wordpress/keyboard-shortcuts'; -import { pipe, useCopyToClipboard } from '@wordpress/compose'; +import { pipe, useCopyToClipboard, useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -47,6 +47,38 @@ function CopyMenuItem( { blocks, onCopy, label } ) { return { copyMenuItemLabel }; } +function ParentSelectorMenuItem( { parentClientId, parentBlockType } ) { + const isSmallViewport = useViewportMatch( 'medium', '<' ); + const { selectBlock } = useDispatch( blockEditorStore ); + + // Allows highlighting the parent block outline when focusing or hovering + // the parent block selector within the child. + const menuItemRef = useRef(); + const gesturesProps = useShowHoveredOrFocusedGestures( { + ref: menuItemRef, + highlightParent: true, + } ); + + if ( ! isSmallViewport ) { + return null; + } + + return ( + } + onClick={ () => selectBlock( parentClientId ) } + > + { sprintf( + /* translators: %s: Name of the block's parent. */ + __( 'Select parent block (%s)' ), + parentBlockType.title + ) } + + ); +} + export function BlockSettingsDropdown( { block, clientIds, @@ -132,8 +164,6 @@ export function BlockSettingsDropdown( { }; }, [] ); const isMatch = __unstableUseShortcutEventMatch(); - - const { selectBlock } = useDispatch( blockEditorStore ); const hasSelectedBlocks = selectedBlockClientIds.length > 0; const updateSelectionAfterDuplicate = useCallback( @@ -175,14 +205,6 @@ export function BlockSettingsDropdown( { const removeBlockLabel = count === 1 ? __( 'Delete' ) : __( 'Delete blocks' ); - // Allows highlighting the parent block outline when focusing or hovering - // the parent block selector within the child. - const selectParentButtonRef = useRef(); - const showParentOutlineGestures = useShowHoveredOrFocusedGestures( { - ref: selectParentButtonRef, - highlightParent: true, - } ); - // This can occur when the selected block (the parent) // displays child blocks within a List View. const parentBlockIsSelected = @@ -297,30 +319,12 @@ export function BlockSettingsDropdown( { /> { ! parentBlockIsSelected && !! firstParentClientId && ( - - } - onClick={ () => - selectBlock( - firstParentClientId - ) + - { sprintf( - /* translators: %s: Name of the block's parent. */ - __( - 'Select parent block (%s)' - ), - parentBlockType.title - ) } - + parentBlockType={ parentBlockType } + /> ) } { count === 1 && ( Date: Wed, 22 Nov 2023 21:16:56 +0000 Subject: [PATCH 19/51] Add 'View site' action to 'Site updated' snackbar (#52693) * Add 'View site' action to 'Site updated' snackbar * Both Snackbars... --- .../edit-site/src/components/save-hub/index.js | 15 +++++++++++++++ .../components/entities-saved-states/index.js | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/save-hub/index.js b/packages/edit-site/src/components/save-hub/index.js index f43e843ee73c1..6afd52c1f4c2a 100644 --- a/packages/edit-site/src/components/save-hub/index.js +++ b/packages/edit-site/src/components/save-hub/index.js @@ -106,6 +106,15 @@ export default function SaveHub() { label = __( 'Saving' ); } + const { homeUrl } = useSelect( ( select ) => { + const { + getUnstableBase, // Site index. + } = select( coreStore ); + return { + homeUrl: getUnstableBase()?.home, + }; + }, [] ); + const saveCurrentEntity = async () => { if ( ! dirtyCurrentEntity ) return; @@ -135,6 +144,12 @@ export default function SaveHub() { createSuccessNotice( __( 'Site updated.' ), { type: 'snackbar', + actions: [ + { + label: __( 'View site' ), + url: homeUrl, + }, + ], id: saveNoticeId, } ); } catch ( error ) { diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index 07097969fffc8..a47dd29fef036 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -3,7 +3,7 @@ */ import { Button, Flex, FlexItem } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useDispatch } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { useCallback, useRef } from '@wordpress/element'; import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; @@ -85,6 +85,15 @@ export function EntitiesSavedStatesExtensible( { const saveEnabled = saveEnabledProp ?? isDirty; + const { homeUrl } = useSelect( ( select ) => { + const { + getUnstableBase, // Site index. + } = select( coreStore ); + return { + homeUrl: getUnstableBase()?.home, + }; + }, [] ); + const saveCheckedEntities = () => { const saveNoticeId = 'site-editor-save-success'; removeNotice( saveNoticeId ); @@ -149,6 +158,12 @@ export function EntitiesSavedStatesExtensible( { createSuccessNotice( __( 'Site updated.' ), { type: 'snackbar', id: saveNoticeId, + actions: [ + { + label: __( 'View site' ), + url: homeUrl, + }, + ], } ); } } ) From aac7844d5ba4a8768926fff55ad0d819f8f2fb9f Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 22 Nov 2023 21:18:35 +0000 Subject: [PATCH 20/51] Update Changelog for 17.0.3 --- changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/changelog.txt b/changelog.txt index 0f86c2d8f593b..8494a56d7160d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,17 @@ == Changelog == += 17.0.3 = + +## Changelog + +### Bug Fixes + +#### Block Editor + +- PostCSS style transformation: fail gracefully instead of throwing an error (https://github.com/WordPress/gutenberg/pull/56093) + + + = 17.1.0 = From 799c807e6c1b2ad1eeb27e68806498477f4bae0b Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 23 Nov 2023 09:54:45 +1100 Subject: [PATCH 21/51] Post Schedule Panel: Fix Sass deprecation warning for division (#56412) --- packages/editor/src/components/post-schedule/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-schedule/style.scss b/packages/editor/src/components/post-schedule/style.scss index ca5bc19ae7d5c..23cb185167db5 100644 --- a/packages/editor/src/components/post-schedule/style.scss +++ b/packages/editor/src/components/post-schedule/style.scss @@ -18,6 +18,6 @@ height: auto; // The line height + the padding should be the same as the button size. - padding: ( ( $button-size - $grid-unit-20 ) / 2 ) 12px; + padding: math.div($button-size - $grid-unit-20, 2) 12px; line-height: $grid-unit-20; } From 8a2f5bc6b7266b477ced853dce87623bbe53fe64 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:57:23 +0900 Subject: [PATCH 22/51] Post Template: fix incorrect offset query (#56440) * Post Template: fix incorrect offset query * Remove unnecessary code --- packages/block-library/src/post-template/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/post-template/edit.js b/packages/block-library/src/post-template/edit.js index 025a8bf4f6c93..2e668674e8530 100644 --- a/packages/block-library/src/post-template/edit.js +++ b/packages/block-library/src/post-template/edit.js @@ -123,7 +123,7 @@ export default function PostTemplateEdit( { slug: templateSlug.replace( 'category-', '' ), } ); const query = { - offset: perPage ? perPage + offset : 0, + offset: offset || 0, order, orderby: orderBy, }; From 84de158e1631982a325b71f833b1164a1337e8c3 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Thu, 23 Nov 2023 13:19:04 +1100 Subject: [PATCH 23/51] Fix fatal error when calling undefined block library function. (#56459) --- .../class-wp-navigation-block-renderer.php | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/compat/wordpress-6.5/class-wp-navigation-block-renderer.php b/lib/compat/wordpress-6.5/class-wp-navigation-block-renderer.php index 0e9166a7c7d54..e2eb4e10414fe 100644 --- a/lib/compat/wordpress-6.5/class-wp-navigation-block-renderer.php +++ b/lib/compat/wordpress-6.5/class-wp-navigation-block-renderer.php @@ -170,7 +170,7 @@ private static function get_inner_blocks_html( $attributes, $inner_blocks ) { // Add directives to the submenu if needed. if ( $has_submenus && $should_load_view_script ) { $tags = new WP_HTML_Tag_Processor( $inner_blocks_html ); - $inner_blocks_html = block_core_navigation_add_directives_to_submenu( $tags, $attributes ); + $inner_blocks_html = gutenberg_block_core_navigation_add_directives_to_submenu( $tags, $attributes ); } return $inner_blocks_html; @@ -195,7 +195,7 @@ private static function get_inner_blocks_from_navigation_post( $attributes ) { // 'parse_blocks' includes a null block with '\n\n' as the content when // it encounters whitespace. This code strips it. - $compacted_blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks ); + $compacted_blocks = gutenberg_block_core_navigation_filter_out_empty_blocks( $parsed_blocks ); // TODO - this uses the full navigation block attributes for the // context which could be refined. @@ -210,7 +210,7 @@ private static function get_inner_blocks_from_navigation_post( $attributes ) { * @return WP_Block_List Returns the inner blocks for the navigation block. */ private static function get_inner_blocks_from_fallback( $attributes ) { - $fallback_blocks = block_core_navigation_get_fallback_blocks(); + $fallback_blocks = gutenberg_block_core_navigation_get_fallback_blocks(); // Fallback my have been filtered so do basic test for validity. if ( empty( $fallback_blocks ) || ! is_array( $fallback_blocks ) ) { @@ -245,9 +245,9 @@ private static function get_inner_blocks( $attributes, $block ) { defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && array_key_exists( '__unstableLocation', $attributes ) && ! array_key_exists( 'ref', $attributes ) && - ! empty( block_core_navigation_get_menu_items_at_location( $attributes['__unstableLocation'] ) ) + ! empty( gutenberg_block_core_navigation_get_menu_items_at_location( $attributes['__unstableLocation'] ) ) ) { - $inner_blocks = block_core_navigation_get_inner_blocks_from_unstable_location( $attributes ); + $inner_blocks = gutenberg_block_core_navigation_get_inner_blocks_from_unstable_location( $attributes ); } // Load inner blocks from the navigation post. @@ -270,7 +270,7 @@ private static function get_inner_blocks( $attributes, $block ) { */ $inner_blocks = apply_filters( 'block_core_navigation_render_inner_blocks', $inner_blocks ); - $post_ids = block_core_navigation_get_post_ids( $inner_blocks ); + $post_ids = gutenberg_block_core_navigation_get_post_ids( $inner_blocks ); if ( $post_ids ) { _prime_post_caches( $post_ids, false, false ); } @@ -353,8 +353,8 @@ private static function get_layout_class( $attributes ) { private static function get_classes( $attributes ) { // Restore legacy classnames for submenu positioning. $layout_class = static::get_layout_class( $attributes ); - $colors = block_core_navigation_build_css_colors( $attributes ); - $font_sizes = block_core_navigation_build_css_font_sizes( $attributes ); + $colors = gutenberg_block_core_navigation_build_css_colors( $attributes ); + $font_sizes = gutenberg_block_core_navigation_build_css_font_sizes( $attributes ); $is_responsive_menu = static::is_responsive( $attributes ); // Manually add block support text decoration as CSS class. @@ -378,8 +378,8 @@ private static function get_classes( $attributes ) { * @return string Returns the styles for the navigation block. */ private static function get_styles( $attributes ) { - $colors = block_core_navigation_build_css_colors( $attributes ); - $font_sizes = block_core_navigation_build_css_font_sizes( $attributes ); + $colors = gutenberg_block_core_navigation_build_css_colors( $attributes ); + $font_sizes = gutenberg_block_core_navigation_build_css_font_sizes( $attributes ); $block_styles = isset( $attributes['styles'] ) ? $attributes['styles'] : ''; return $block_styles . $colors['inline_styles'] . $font_sizes['inline_styles']; } @@ -394,7 +394,7 @@ private static function get_styles( $attributes ) { */ private static function get_responsive_container_markup( $attributes, $inner_blocks, $inner_blocks_html ) { $should_load_view_script = static::should_load_view_script( $attributes, $inner_blocks ); - $colors = block_core_navigation_build_css_colors( $attributes ); + $colors = gutenberg_block_core_navigation_build_css_colors( $attributes ); $modal_unique_id = wp_unique_id( 'modal-' ); $is_hidden_by_default = isset( $attributes['overlayMenu'] ) && 'always' === $attributes['overlayMenu']; @@ -627,7 +627,7 @@ public static function render( $attributes, $content, $block ) { $inner_blocks = static::get_inner_blocks( $attributes, $block ); // Prevent navigation blocks referencing themselves from rendering. - if ( block_core_navigation_block_contains_core_navigation( $inner_blocks ) ) { + if ( gutenberg_block_core_navigation_block_contains_core_navigation( $inner_blocks ) ) { return ''; } From 084eefebd28ecc79bd0f1d474e8ef215f9651d83 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Thu, 23 Nov 2023 03:21:19 +0000 Subject: [PATCH 24/51] Bump plugin version to 17.1.1 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index 018c269f4f565..a88e153766888 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.2 * Requires PHP: 7.0 - * Version: 17.1.0 + * Version: 17.1.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 601aafc18b268..d82b2404c610e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "17.1.0", + "version": "17.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "17.1.0", + "version": "17.1.1", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 43ca7f0858f60..960ccd074ae60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "17.1.0", + "version": "17.1.1", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 8059f984c2f31b0b95e7eb6a25e4205667ea83cf Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Thu, 23 Nov 2023 03:38:08 +0000 Subject: [PATCH 25/51] Update Changelog for 17.1.1 --- changelog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/changelog.txt b/changelog.txt index 8494a56d7160d..b3750479e99fa 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,16 @@ == Changelog == += 17.1.1 = + +# Changelog + +## Bug Fixes + +### Block Library + +Fix fatal error when calling undefined block library function. #56459 + + = 17.0.3 = ## Changelog From c57fb7b872945bf9f99253e3ccd0818da0406569 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 23 Nov 2023 15:05:22 +1100 Subject: [PATCH 26/51] Cover block: Pass dropZoneElement reference to fix dragging within cover block area (#56312) * Cover block: Pass dropZoneElement reference to fix dragging and dropping within cover block area * Move to using a simple ref --- packages/block-library/src/cover/edit/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index ab49d58b766b0..8c5488584094c 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -335,6 +335,7 @@ function CoverEdit( { templateInsertUpdatesSelection: true, allowedBlocks, templateLock, + dropZoneElement: ref.current, } ); From 6510154314c70d302268690cf80cd121828deb41 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 23 Nov 2023 08:59:30 +0100 Subject: [PATCH 27/51] Move the DisableNonContentBlocks component to the editor package (#56423) --- .../block-editor/site-editor-canvas.js | 4 +-- .../back-to-page-notification.js | 0 .../edit-template-notification.js | 0 .../index.js | 31 +++++++------------ .../src/components/provider/constants.js | 5 +++ .../disable-non-page-content-blocks.js | 6 ++-- .../editor/src/components/provider/index.js | 10 +++--- 7 files changed, 26 insertions(+), 30 deletions(-) rename packages/edit-site/src/components/{page-content-focus-manager => page-content-focus-notifications}/back-to-page-notification.js (100%) rename packages/edit-site/src/components/{page-content-focus-manager => page-content-focus-notifications}/edit-template-notification.js (100%) rename packages/edit-site/src/components/{page-content-focus-manager => page-content-focus-notifications}/index.js (58%) create mode 100644 packages/editor/src/components/provider/constants.js rename packages/{edit-site/src/components/page-content-focus-manager => editor/src/components/provider}/disable-non-page-content-blocks.js (89%) diff --git a/packages/edit-site/src/components/block-editor/site-editor-canvas.js b/packages/edit-site/src/components/block-editor/site-editor-canvas.js index 643fa84559f60..0d2d522c8b3e1 100644 --- a/packages/edit-site/src/components/block-editor/site-editor-canvas.js +++ b/packages/edit-site/src/components/block-editor/site-editor-canvas.js @@ -27,7 +27,7 @@ import { NAVIGATION_POST_TYPE, } from '../../utils/constants'; import { unlock } from '../../lock-unlock'; -import PageContentFocusManager from '../page-content-focus-manager'; +import PageContentFocusNotifications from '../page-content-focus-notifications'; const LAYOUT = { type: 'default', @@ -149,7 +149,7 @@ export default function SiteEditorCanvas() { ) } - + ); } diff --git a/packages/edit-site/src/components/page-content-focus-manager/back-to-page-notification.js b/packages/edit-site/src/components/page-content-focus-notifications/back-to-page-notification.js similarity index 100% rename from packages/edit-site/src/components/page-content-focus-manager/back-to-page-notification.js rename to packages/edit-site/src/components/page-content-focus-notifications/back-to-page-notification.js diff --git a/packages/edit-site/src/components/page-content-focus-manager/edit-template-notification.js b/packages/edit-site/src/components/page-content-focus-notifications/edit-template-notification.js similarity index 100% rename from packages/edit-site/src/components/page-content-focus-manager/edit-template-notification.js rename to packages/edit-site/src/components/page-content-focus-notifications/edit-template-notification.js diff --git a/packages/edit-site/src/components/page-content-focus-manager/index.js b/packages/edit-site/src/components/page-content-focus-notifications/index.js similarity index 58% rename from packages/edit-site/src/components/page-content-focus-manager/index.js rename to packages/edit-site/src/components/page-content-focus-notifications/index.js index 05bcc0da003cf..2b0e636f5231e 100644 --- a/packages/edit-site/src/components/page-content-focus-manager/index.js +++ b/packages/edit-site/src/components/page-content-focus-notifications/index.js @@ -7,27 +7,21 @@ import { useEffect } from '@wordpress/element'; * Internal dependencies */ import { store as editSiteStore } from '../../store'; -import DisableNonPageContentBlocks from './disable-non-page-content-blocks'; import EditTemplateNotification from './edit-template-notification'; import BackToPageNotification from './back-to-page-notification'; import { unlock } from '../../lock-unlock'; -export default function PageContentFocusManager( { contentRef } ) { - const { hasPageContentFocus, pageContentFocusType, canvasMode } = useSelect( - ( select ) => { - const { getPageContentFocusType, getCanvasMode } = unlock( - select( editSiteStore ) - ); - const _canvasMode = getCanvasMode(); - return { - canvasMode: _canvasMode, - pageContentFocusType: getPageContentFocusType(), - hasPageContentFocus: - select( editSiteStore ).hasPageContentFocus(), - }; - }, - [] - ); +export default function PageContentFocusNotifications( { contentRef } ) { + const { pageContentFocusType, canvasMode } = useSelect( ( select ) => { + const { getPageContentFocusType, getCanvasMode } = unlock( + select( editSiteStore ) + ); + const _canvasMode = getCanvasMode(); + return { + canvasMode: _canvasMode, + pageContentFocusType: getPageContentFocusType(), + }; + }, [] ); const { setPageContentFocusType } = unlock( useDispatch( editSiteStore ) ); /* @@ -39,11 +33,10 @@ export default function PageContentFocusManager( { contentRef } ) { if ( canvasMode !== 'edit' && !! pageContentFocusType ) { setPageContentFocusType( null ); } - }, [ canvasMode, pageContentFocusType ] ); + }, [ canvasMode, pageContentFocusType, setPageContentFocusType ] ); return ( <> - { hasPageContentFocus && } diff --git a/packages/editor/src/components/provider/constants.js b/packages/editor/src/components/provider/constants.js new file mode 100644 index 0000000000000..a81b2fd37563a --- /dev/null +++ b/packages/editor/src/components/provider/constants.js @@ -0,0 +1,5 @@ +export const PAGE_CONTENT_BLOCK_TYPES = [ + 'core/post-title', + 'core/post-featured-image', + 'core/post-content', +]; diff --git a/packages/edit-site/src/components/page-content-focus-manager/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/disable-non-page-content-blocks.js similarity index 89% rename from packages/edit-site/src/components/page-content-focus-manager/disable-non-page-content-blocks.js rename to packages/editor/src/components/provider/disable-non-page-content-blocks.js index 2f81f80d0ce63..048b01d026c24 100644 --- a/packages/edit-site/src/components/page-content-focus-manager/disable-non-page-content-blocks.js +++ b/packages/editor/src/components/provider/disable-non-page-content-blocks.js @@ -11,7 +11,7 @@ import { useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import { PAGE_CONTENT_BLOCK_TYPES } from '../../utils/constants'; +import { PAGE_CONTENT_BLOCK_TYPES } from './constants'; function DisableBlock( { clientId } ) { const isDescendentOfQueryLoop = useSelect( @@ -46,9 +46,7 @@ export default function DisableNonPageContentBlocks() { const clientIds = useSelect( ( select ) => { const { __experimentalGetGlobalBlocksByName } = select( blockEditorStore ); - return __experimentalGetGlobalBlocksByName( - Object.keys( PAGE_CONTENT_BLOCK_TYPES ) - ); + return __experimentalGetGlobalBlocksByName( PAGE_CONTENT_BLOCK_TYPES ); }, [] ); return clientIds.map( ( clientId ) => { diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 5fa79eedef987..75f1769927715 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -22,16 +22,13 @@ import withRegistryProvider from './with-registry-provider'; import { store as editorStore } from '../../store'; import useBlockEditorSettings from './use-block-editor-settings'; import { unlock } from '../../lock-unlock'; +import DisableNonPageContentBlocks from './disable-non-page-content-blocks'; +import { PAGE_CONTENT_BLOCK_TYPES } from './constants'; const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { PatternsMenuItems } = unlock( editPatternsPrivateApis ); const noop = () => {}; -export const PAGE_CONTENT_BLOCK_TYPES = [ - 'core/post-title', - 'core/post-featured-image', - 'core/post-content', -]; /** * For the Navigation block editor, we need to force the block editor to contentOnly for that block. @@ -308,6 +305,9 @@ export const ExperimentalEditorProvider = withRegistryProvider( > { children } + { [ 'post-only', 'template-locked' ].includes( + mode + ) && } From c03a097faadb66a2725dc96e8c23772abe6e0559 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 23 Nov 2023 12:19:23 +0400 Subject: [PATCH 28/51] Block Editor: Optimize 'Connections' inspector controls (#56443) --- .../block-editor/src/hooks/custom-fields.js | 133 +++++++++--------- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/packages/block-editor/src/hooks/custom-fields.js b/packages/block-editor/src/hooks/custom-fields.js index 31721569781b6..adb9df15824a7 100644 --- a/packages/block-editor/src/hooks/custom-fields.js +++ b/packages/block-editor/src/hooks/custom-fields.js @@ -34,6 +34,65 @@ function addAttribute( settings ) { return settings; } +function CustomFieldsControl( props ) { + const blockEditingMode = useBlockEditingMode(); + if ( blockEditingMode !== 'default' ) { + return null; + } + + // If the block is a paragraph or image block, we need to know which + // attribute to use for the connection. Only the `content` attribute + // of the paragraph block and the `url` attribute of the image block are supported. + let attributeName; + if ( props.name === 'core/paragraph' ) attributeName = 'content'; + if ( props.name === 'core/image' ) attributeName = 'url'; + + return ( + + + { + if ( nextValue === '' ) { + props.setAttributes( { + connections: undefined, + [ attributeName ]: undefined, + placeholder: undefined, + } ); + } else { + props.setAttributes( { + connections: { + attributes: { + // The attributeName will be either `content` or `url`. + [ attributeName ]: { + // Source will be variable, could be post_meta, user_meta, term_meta, etc. + // Could even be a custom source like a social media attribute. + source: 'meta_fields', + value: nextValue, + }, + }, + }, + [ attributeName ]: undefined, + placeholder: sprintf( + 'This content will be replaced on the frontend by the value of "%s" custom field.', + nextValue + ), + } ); + } + } } + /> + + + ); +} + /** * Override the default edit UI to include a new block inspector control for * assigning a connection to blocks that has support for connections. @@ -46,7 +105,6 @@ function addAttribute( settings ) { */ const withCustomFieldsControls = createHigherOrderComponent( ( BlockEdit ) => { return ( props ) => { - const blockEditingMode = useBlockEditingMode(); const hasCustomFieldsSupport = hasBlockSupport( props.name, '__experimentalConnections', @@ -56,72 +114,17 @@ const withCustomFieldsControls = createHigherOrderComponent( ( BlockEdit ) => { // Check if the current block is a paragraph or image block. // Currently, only these two blocks are supported. if ( ! [ 'core/paragraph', 'core/image' ].includes( props.name ) ) { - return ; + return ; } - // If the block is a paragraph or image block, we need to know which - // attribute to use for the connection. Only the `content` attribute - // of the paragraph block and the `url` attribute of the image block are supported. - let attributeName; - if ( props.name === 'core/paragraph' ) attributeName = 'content'; - if ( props.name === 'core/image' ) attributeName = 'url'; - - if ( hasCustomFieldsSupport && props.isSelected ) { - return ( - <> - - { blockEditingMode === 'default' && ( - - - { - if ( nextValue === '' ) { - props.setAttributes( { - connections: undefined, - [ attributeName ]: undefined, - placeholder: undefined, - } ); - } else { - props.setAttributes( { - connections: { - attributes: { - // The attributeName will be either `content` or `url`. - [ attributeName ]: { - // Source will be variable, could be post_meta, user_meta, term_meta, etc. - // Could even be a custom source like a social media attribute. - source: 'meta_fields', - value: nextValue, - }, - }, - }, - [ attributeName ]: undefined, - placeholder: sprintf( - 'This content will be replaced on the frontend by the value of "%s" custom field.', - nextValue - ), - } ); - } - } } - /> - - - ) } - - ); - } - - return ; + return ( + <> + + { hasCustomFieldsSupport && props.isSelected && ( + + ) } + + ); }; }, 'withCustomFieldsControls' ); From 56d1b71bb8d22e4619d90ca05d8018c2822c0385 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Thu, 23 Nov 2023 09:47:50 +0100 Subject: [PATCH 29/51] [RNMobile] Fix ungroup functionality in `WarningMaxDepthExceeded` component (#56445) --- .../warning-max-depth-exceeded.native.js | 90 ++++++++++++------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js index 57a7b7a60483c..e363db4961c7c 100644 --- a/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js +++ b/packages/block-editor/src/components/inner-blocks/warning-max-depth-exceeded.native.js @@ -8,7 +8,7 @@ import { TouchableWithoutFeedback, View } from 'react-native'; */ import { __, sprintf } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -18,54 +18,71 @@ import UnsupportedBlockDetails from '../unsupported-block-details'; import { store as blockEditorStore } from '../../store'; import { MAX_NESTING_DEPTH } from './constants'; import useUnsupportedBlockEditor from '../use-unsupported-block-editor'; +import { + useConvertToGroupButtons, + useConvertToGroupButtonProps, +} from '../convert-to-group-buttons'; + +const EMPTY_ARRAY = []; const WarningMaxDepthExceeded = ( { clientId } ) => { const [ showDetails, setShowDetails ] = useState( false ); - const { isSelected, innerBlocks } = useSelect( - ( select ) => { - const { getBlock, isBlockSelected } = select( blockEditorStore ); - return { - innerBlocks: getBlock( clientId )?.innerBlocks || [], - isSelected: isBlockSelected( clientId ), - }; - }, + const isSelected = useSelect( + ( select ) => select( blockEditorStore ).isBlockSelected( clientId ), [ clientId ] ); - const { replaceBlocks } = useDispatch( blockEditorStore ); + + // We rely on the logic related to the Group/Ungroup buttons used in the block options to + // determine whether to use the Ungroup action. + const convertToGroupButtonProps = useConvertToGroupButtonProps( [ + clientId, + ] ); + const { isUngroupable } = convertToGroupButtonProps; + const convertToGroupButtons = useConvertToGroupButtons( { + ...convertToGroupButtonProps, + } ); + const onUngroup = convertToGroupButtons.ungroup.onSelect; const { isUnsupportedBlockEditorSupported, canEnableUnsupportedBlockEditor, } = useUnsupportedBlockEditor( clientId ); - const onUngroup = () => { - if ( ! innerBlocks.length ) { - return; - } - - replaceBlocks( clientId, innerBlocks ); - }; - - let description; - // When UBE can't be used, the description mentions using the web browser to edit the block. + /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ + const descriptionFormat = __( + 'Blocks nested deeper than %d levels may not render properly in the mobile editor.' + ); + let description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); if ( ! isUnsupportedBlockEditorSupported && ! canEnableUnsupportedBlockEditor ) { - /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ - const descriptionFormat = __( - 'Blocks nested deeper than %d levels may not render properly in the mobile editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using your web browser.' - ); - description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); + // When UBE can't be used, the description mentions using the web browser to edit the block. + description += + ' ' + + /* translators: Recommendation included in a warning related to having blocks deeply nested. */ + __( + 'For this reason, we recommend editing the block using your web browser.' + ); } // Otherwise, the description mentions using the web editor (i.e. UBE). else { - /* translators: Warning related to having blocks deeply nested. %d: The deepest nesting level. */ - const descriptionFormat = __( - 'Blocks nested deeper than %d levels may not render properly in the mobile editor. For this reason, we recommend flattening the content by ungrouping the block or editing the block using the web editor.' - ); - description = sprintf( descriptionFormat, MAX_NESTING_DEPTH ); + description += + ' ' + + /* translators: Recommendation included in a warning related to having blocks deeply nested. */ + __( + 'For this reason, we recommend editing the block using the web editor.' + ); + } + // If the block can be flattened, we also suggest to ungroup the block. + if ( isUngroupable ) { + description += + ' ' + + /* translators: Alternative option included in a warning related to having blocks deeply nested. */ + __( + 'Alternatively, you can flatten the content by ungrouping the block.' + ); } return ( @@ -88,9 +105,16 @@ const WarningMaxDepthExceeded = ( { clientId } ) => { onCloseSheet={ () => setShowDetails( false ) } title={ __( 'Deeply nested block' ) } description={ description } - customActions={ [ - { label: __( 'Ungroup block' ), onPress: onUngroup }, - ] } + customActions={ + isUngroupable + ? [ + { + label: __( 'Ungroup block' ), + onPress: onUngroup, + }, + ] + : EMPTY_ARRAY + } /> From 726fc065983a202447c8cafe593759e6529bfbf0 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Thu, 23 Nov 2023 11:38:41 +0200 Subject: [PATCH 30/51] Dataviews: Remove link from author (#56467) --- packages/edit-site/src/components/dataviews/dataviews.js | 4 ++-- packages/edit-site/src/components/page-pages/index.js | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 682060203de7c..78d0ea83abb8e 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -56,8 +56,8 @@ export default function DataViews( { return (
- - + + { search && ( item._embedded?.author[ 0 ]?.name, - render: ( { item } ) => { - const author = item._embedded?.author[ 0 ]; - return ( - - { author.name } - - ); - }, type: ENUMERATION_TYPE, elements: authors?.map( ( { id, name } ) => ( { From 2477561b4738b883fe41b2677be6006d3d733c6c Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 23 Nov 2023 13:47:59 +0400 Subject: [PATCH 31/51] useEntityRecord: Improve unit tests (#56415) * useEntityRecord: Improve unit tests Co-authored-by: Kai Hao * Add comment --------- Co-authored-by: Kai Hao --- .../src/hooks/test/use-entity-record.js | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/core-data/src/hooks/test/use-entity-record.js b/packages/core-data/src/hooks/test/use-entity-record.js index 1fe68c84a951b..fa1dea6df8146 100644 --- a/packages/core-data/src/hooks/test/use-entity-record.js +++ b/packages/core-data/src/hooks/test/use-entity-record.js @@ -116,22 +116,29 @@ describe( 'useEntityRecord', () => { } ); it( 'does not resolve entity record when disabled via options', async () => { - // Provide response triggerFetch.mockImplementation( () => TEST_RECORD ); let data; - const TestComponent = () => { - data = useEntityRecord( 'root', 'widget', 2, { - options: { enabled: false }, - } ); + const TestComponent = ( { enabled } ) => { + data = useEntityRecord( 'root', 'widget', 1, { enabled } ); return
; }; - render( + const UI = ( { enabled } ) => ( - + ); + const { rerender } = render( ); + + // A minimum delay for a fetch request. The same delay is used again as a control. + await act( + () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) ) + ); + expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); + + rerender( ); + expect( data ).toEqual( { edit: expect.any( Function ), editedRecord: {}, @@ -141,14 +148,10 @@ describe( 'useEntityRecord', () => { save: expect.any( Function ), } ); - // Fetch request should have been issued. - await waitFor( () => { - expect( triggerFetch ).not.toHaveBeenCalled(); - } ); - await waitFor( () => - expect( triggerFetch ).not.toHaveBeenCalledWith( { - path: '/wp/v2/widgets/2?context=edit', - } ) + // The same delay. + await act( + () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) ) ); + expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); } ); } ); From ea60d43e9545af7ed774c2201bfaba3151a63aa6 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Thu, 23 Nov 2023 11:51:51 +0200 Subject: [PATCH 32/51] DataViews: Make disabled pagination buttons focusable (#56422) --- packages/edit-site/src/components/dataviews/pagination.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/edit-site/src/components/dataviews/pagination.js b/packages/edit-site/src/components/dataviews/pagination.js index 7948cf01ecfc2..25672208d993c 100644 --- a/packages/edit-site/src/components/dataviews/pagination.js +++ b/packages/edit-site/src/components/dataviews/pagination.js @@ -48,6 +48,7 @@ function Pagination( { onChangeView( { ...view, page: 1 } ) } disabled={ view.page === 1 } + __experimentalIsFocusable label={ __( 'First page' ) } icon={ previous } showTooltip @@ -58,6 +59,7 @@ function Pagination( { onChangeView( { ...view, page: view.page - 1 } ) } disabled={ view.page === 1 } + __experimentalIsFocusable label={ __( 'Previous page' ) } icon={ chevronLeft } showTooltip @@ -115,6 +117,7 @@ function Pagination( { onChangeView( { ...view, page: view.page + 1 } ) } disabled={ view.page >= totalPages } + __experimentalIsFocusable label={ __( 'Next page' ) } icon={ chevronRight } showTooltip @@ -125,6 +128,7 @@ function Pagination( { onChangeView( { ...view, page: totalPages } ) } disabled={ view.page >= totalPages } + __experimentalIsFocusable label={ __( 'Last page' ) } icon={ next } showTooltip From 0b6c4a003f90b18509ee6d3d120435444dc15e43 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Thu, 23 Nov 2023 13:42:17 +0100 Subject: [PATCH 33/51] DropdownMenu V2: add support for rendering in legacy popover slot (#56342) * DropdownMenuV2: support rendering in slotfill * Add temporary stories * CHANGELOG --- packages/components/CHANGELOG.md | 1 + .../src/dropdown-menu-v2-ariakit/index.tsx | 14 ++++ .../stories/index.story.tsx | 66 +++++++++++++++++++ .../src/dropdown-menu-v2-ariakit/types.ts | 7 ++ .../src/dropdown-menu/stories/index.story.tsx | 52 +++++++++++++++ packages/components/src/popover/index.tsx | 2 +- 6 files changed, 141 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 9a3beb0342396..cbb12e0146b55 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ ### Internal +- `DropdownMenuV2`: add support for rendering in legacy popover slot ([#56342](https://github.com/WordPress/gutenberg/pull/56342)). - `Slot`: add `style` prop to `bubblesVirtually` version ([#56428](https://github.com/WordPress/gutenberg/pull/56428)) ## 25.12.0 (2023-11-16) diff --git a/packages/components/src/dropdown-menu-v2-ariakit/index.tsx b/packages/components/src/dropdown-menu-v2-ariakit/index.tsx index 10b93d8c552c1..b992c7b4c7b5a 100644 --- a/packages/components/src/dropdown-menu-v2-ariakit/index.tsx +++ b/packages/components/src/dropdown-menu-v2-ariakit/index.tsx @@ -26,6 +26,11 @@ import { SVG, Circle } from '@wordpress/primitives'; import { useContextSystem, contextConnect } from '../context'; import type { WordPressComponentProps } from '../context'; import Icon from '../icon'; +import { useSlot } from '../slot-fill'; +import { + SLOT_NAME as POPOVER_DEFAULT_SLOT_NAME, + slotNameContext, +} from '../popover'; import type { DropdownMenuContext as DropdownMenuContextType, DropdownMenuProps, @@ -182,6 +187,9 @@ const UnconnectedDropdownMenu = ( shift, modal = true, + // Other props + slotName: slotNameProp = POPOVER_DEFAULT_SLOT_NAME, + // From internal components context variant, @@ -270,6 +278,11 @@ const UnconnectedDropdownMenu = ( [ computedDirection ] ); + // Render the portal in the default slot used by the legacy Popover component. + const slotName = useContext( slotNameContext ) || slotNameProp; + const slot = useSlot( slotName ); + const portalContainer = slot.ref?.current; + return ( <> { /* Menu trigger */ } @@ -305,6 +318,7 @@ const UnconnectedDropdownMenu = ( wrapperProps={ wrapperProps } hideOnEscape={ hideOnEscape } unmountOnHide + portalElement={ portalContainer } > { children } diff --git a/packages/components/src/dropdown-menu-v2-ariakit/stories/index.story.tsx b/packages/components/src/dropdown-menu-v2-ariakit/stories/index.story.tsx index a6319c6cfdc93..147de3861b160 100644 --- a/packages/components/src/dropdown-menu-v2-ariakit/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu-v2-ariakit/stories/index.story.tsx @@ -28,6 +28,7 @@ import { import Icon from '../../icon'; import Button from '../../button'; import Modal from '../../modal'; +import Popover from '../../popover'; import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill'; import { ContextSystemProvider } from '../../context'; @@ -501,3 +502,68 @@ InsideModal.parameters = { source: { type: 'code' }, }, }; + +export const WithDefaultSlotFill: StoryFn< typeof DropdownMenu > = ( + props +) => ( + + { /* @ts-expect-error Slot is not currently typed on Popover */ } + + + Top level item + Open submenu } + > + Nested item + + + +); +WithDefaultSlotFill.args = { + ...Default.args, +}; + +export const WithNamedSlotFill: StoryFn< typeof DropdownMenu > = ( props ) => ( + + { /* @ts-expect-error Slot is not currently typed on Popover */ } + + + Top level item + Open submenu } + > + Nested item + + + +); +WithNamedSlotFill.args = { + ...Default.args, + slotName: 'dropdown-menu-slot-with-name', +}; + +// @ts-expect-error __unstableSlotNameProvider is not currently typed on Popover +const SlotNameProvider = Popover.__unstableSlotNameProvider; +export const WithSlotFillViaContext: StoryFn< typeof DropdownMenu > = ( + props +) => ( + + + { /* @ts-expect-error Slot is not currently typed on Popover */ } + + + Top level item + Open submenu + } + > + Nested item + + + + +); +WithSlotFillViaContext.args = { + ...Default.args, +}; diff --git a/packages/components/src/dropdown-menu-v2-ariakit/types.ts b/packages/components/src/dropdown-menu-v2-ariakit/types.ts index 27d3b1e8c4339..64c7134d62bff 100644 --- a/packages/components/src/dropdown-menu-v2-ariakit/types.ts +++ b/packages/components/src/dropdown-menu-v2-ariakit/types.ts @@ -79,6 +79,13 @@ export interface DropdownMenuProps { | ( ( event: KeyboardEvent | React.KeyboardEvent< Element > ) => boolean ); + /** + * The name of the Slot in which the popover should be rendered. It should + * be also passed to the corresponding `PopoverSlot` component. + * + * @default 'Popover' + */ + slotName?: string; } export interface DropdownMenuGroupProps { diff --git a/packages/components/src/dropdown-menu/stories/index.story.tsx b/packages/components/src/dropdown-menu/stories/index.story.tsx index d4b856380db92..e94b5199b2537 100644 --- a/packages/components/src/dropdown-menu/stories/index.story.tsx +++ b/packages/components/src/dropdown-menu/stories/index.story.tsx @@ -9,6 +9,8 @@ import type { Meta, StoryFn } from '@storybook/react'; import { DropdownMenu } from '..'; import MenuItem from '../../menu-item'; import MenuGroup from '../../menu-group'; +import Popover from '../../popover'; +import { Provider as SlotFillProvider } from '../../slot-fill'; /** * WordPress dependencies @@ -116,3 +118,53 @@ WithChildren.args = { ), }; + +export const WithDefaultSlotFill: StoryFn< typeof DropdownMenu > = ( + props +) => ( + +
+ { /* @ts-expect-error Slot is not currently typed on Popover */ } + + +
+
+); +WithDefaultSlotFill.args = { + ...Default.args, +}; + +export const WithNamedSlotFill: StoryFn< typeof DropdownMenu > = ( props ) => ( + +
+ { /* @ts-expect-error Slot is not currently typed on Popover */ } + + +
+
+); +WithNamedSlotFill.args = { + ...Default.args, + popoverProps: { + __unstableSlotName: 'dropdown-menu-slot-with-name', + }, +}; + +// @ts-expect-error __unstableSlotNameProvider is not currently typed on Popover +const SlotNameProvider = Popover.__unstableSlotNameProvider; +export const WithSlotFillViaContext: StoryFn< typeof DropdownMenu > = ( + props +) => ( + + + { /* @ts-expect-error Slot is not currently typed on Popover */ } + +
+ +
+
+
+); +WithSlotFillViaContext.args = { + ...Default.args, +}; diff --git a/packages/components/src/popover/index.tsx b/packages/components/src/popover/index.tsx index 709d4b9884b5e..ff67b65cf5b0d 100644 --- a/packages/components/src/popover/index.tsx +++ b/packages/components/src/popover/index.tsx @@ -97,7 +97,7 @@ const ArrowTriangle = () => ( ); -const slotNameContext = createContext< string | undefined >( undefined ); +export const slotNameContext = createContext< string | undefined >( undefined ); const fallbackContainerClassname = 'components-popover__fallback-container'; const getPopoverFallbackContainer = () => { From cc1870a49f57f89cb4c97b41782420a36f77e4da Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Thu, 23 Nov 2023 14:15:56 +0000 Subject: [PATCH 34/51] DataViews: Code Quality remove some unused props from action. (#56477) --- packages/edit-site/src/components/dataviews/item-actions.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/item-actions.js b/packages/edit-site/src/components/dataviews/item-actions.js index 777244e0396a7..2c3373c14bfdf 100644 --- a/packages/edit-site/src/components/dataviews/item-actions.js +++ b/packages/edit-site/src/components/dataviews/item-actions.js @@ -102,7 +102,6 @@ export default function ItemActions( { item, actions } ) { action.callback( item ) } /> ); @@ -128,7 +127,6 @@ export default function ItemActions( { item, actions } ) { action.callback( item ) } From 130a145c7b41a6629a340ba46c200517e4085bc9 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Thu, 23 Nov 2023 16:48:55 +0200 Subject: [PATCH 35/51] Dataviews: Add preview and grid view in templates list (#56382) * Dataviews: Add preview and grid view in templates list * Update preview design * Preview heights in grid view * fix linting issue * address feedback * minor tweak --------- Co-authored-by: James Koster --- .../src/components/dataviews/view-grid.js | 13 +++- .../src/components/dataviews/view-list.js | 10 ++- .../page-templates/dataviews-templates.js | 73 ++++++++++++++++++- .../src/components/page-templates/style.scss | 18 +++++ packages/edit-site/src/style.scss | 1 + 5 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 packages/edit-site/src/components/page-templates/style.scss diff --git a/packages/edit-site/src/components/dataviews/view-grid.js b/packages/edit-site/src/components/dataviews/view-grid.js index b9d4bd78d96d6..d97a9db04200d 100644 --- a/packages/edit-site/src/components/dataviews/view-grid.js +++ b/packages/edit-site/src/components/dataviews/view-grid.js @@ -8,6 +8,7 @@ import { FlexBlock, Placeholder, } from '@wordpress/components'; +import { useAsyncList } from '@wordpress/compose'; /** * Internal dependencies @@ -23,9 +24,15 @@ export function ViewGrid( { data, fields, view, actions, getItemId } ) { ! view.hiddenFields.includes( field.id ) && field.id !== view.layout.mediaField ); + const shownData = useAsyncList( data, { step: 3 } ); return ( - - { data.map( ( item, index ) => { + + { shownData.map( ( item, index ) => { return (
@@ -50,7 +57,7 @@ export function ViewGrid( { data, fields, view, actions, getItemId } ) { ) ) } - +