From 6a04d57b280490ec1a33c168c3f3f47603b08161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:28:20 +0200 Subject: [PATCH 01/32] Set status as no sortable (#55210) --- packages/edit-site/src/components/page-pages/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 6ee6c8bc1bace..56575248453f0 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -116,6 +116,7 @@ export default function PagePages() { id: 'status', accessorFn: ( page ) => postStatuses[ page.status ] ?? page.status, + enableSorting: false, }, { header: { __( 'Actions' ) }, From da3d90b6e5a3c9b3bd7a6b0b37e332638662896e Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Tue, 10 Oct 2023 16:45:34 -0300 Subject: [PATCH 02/32] Use all the settings origins for a block that consumes paths with merge. (#55219) Co-authored-by: Jason Crist <146530+pbking@users.noreply.github.com> --- packages/block-editor/src/components/use-setting/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-setting/index.js b/packages/block-editor/src/components/use-setting/index.js index c1222c9116ae6..1ae672103015c 100644 --- a/packages/block-editor/src/components/use-setting/index.js +++ b/packages/block-editor/src/components/use-setting/index.js @@ -189,7 +189,12 @@ export default function useSetting( path ) { // Return if the setting was found in either the block instance or the store. if ( result !== undefined ) { if ( PATHS_WITH_MERGE[ normalizedPath ] ) { - return result.custom ?? result.theme ?? result.default; + return [ 'default', 'theme', 'custom' ].reduce( + ( acc, key ) => { + return acc.concat( result[ key ] ?? [] ); + }, + [] + ); } return result; } From 8d26e5d60c6f509c5a5944161084dfe618398abd Mon Sep 17 00:00:00 2001 From: Jeff Ong Date: Tue, 10 Oct 2023 17:23:00 -0400 Subject: [PATCH 03/32] Font Library: show error if fetching collection fails (#54919) * Throw and render error if fetching font collections fail. * use the existing notice state to dispay the error --------- Co-authored-by: Matias Benedetto --- .../font-library-modal/context.js | 28 +++++++++++-------- .../font-library-modal/font-collection.js | 28 ++++++++++++------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/context.js b/packages/edit-site/src/components/global-styles/font-library-modal/context.js index 8ab067495fcc0..33a5b0910f052 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/context.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/context.js @@ -323,17 +323,23 @@ function FontLibraryProvider( { children } ) { setFontCollections( response ); }; const getFontCollection = async ( id ) => { - const hasData = !! collections.find( - ( collection ) => collection.id === id - )?.data; - if ( hasData ) return; - const response = await fetchFontCollection( id ); - const updatedCollections = collections.map( ( collection ) => - collection.id === id - ? { ...collection, data: { ...response?.data } } - : collection - ); - setFontCollections( updatedCollections ); + try { + const hasData = !! collections.find( + ( collection ) => collection.id === id + )?.data; + if ( hasData ) return; + const response = await fetchFontCollection( id ); + const updatedCollections = collections.map( ( collection ) => + collection.id === id + ? { ...collection, data: { ...response?.data } } + : collection + ); + setFontCollections( updatedCollections ); + } catch ( e ) { + // eslint-disable-next-line no-console + console.error( e ); + throw e; + } }; useEffect( () => { diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index a3b697efcfb8b..61de80838f637 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -72,20 +72,32 @@ function FontCollection( { id } ) { }, [ id, requiresPermission ] ); useEffect( () => { - getFontCollection( id ); - resetFilters(); + const fetchFontCollection = async () => { + try { + await getFontCollection( id ); + resetFilters(); + } catch ( e ) { + setNotice( { + type: 'error', + message: e?.message, + duration: 0, // Don't auto-hide. + } ); + } + }; + fetchFontCollection(); }, [ id, getFontCollection ] ); useEffect( () => { setSelectedFont( null ); + setNotice( null ); }, [ id ] ); // Reset notice after 5 seconds useEffect( () => { - if ( notice ) { + if ( notice && notice?.duration !== 0 ) { const timeout = setTimeout( () => { setNotice( null ); - }, 5000 ); + }, notice.duration ?? 5000 ); return () => clearTimeout( timeout ); } }, [ notice ] ); @@ -167,10 +179,6 @@ function FontCollection( { id } ) { > ) } - { ! renderConfirmDialog && ! selectedCollection.data && ( - - ) } - { notice && ( <> @@ -227,9 +235,9 @@ function FontCollection( { id } ) { ) } - { ! renderConfirmDialog && - ! selectedCollection?.data?.fontFamilies && } + ! selectedCollection?.data?.fontFamilies && + ! notice && } { ! renderConfirmDialog && !! selectedCollection?.data?.fontFamilies?.length && From cf3b27f199512e08c17f07b093957a656f9b081b Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 10 Oct 2023 13:42:24 -0700 Subject: [PATCH 04/32] HTML API: Backup updates from Core - add `has_class()` and `class_list()` methods [#59209-trac](https://core.trac.wordpress.org/ticket/59209) - add `matches_breadcrumbs()` method [#59400-trac](https://core.trac.wordpress.org/ticket/59400) - rename `createFramgent()` to `create_fragment()` [#59547-trac](https://core.trac.wordpress.org/ticket/59547) --- ...class-gutenberg-html-tag-processor-6-4.php | 147 +++++++++++------- .../html-api/class-wp-html-processor.php | 88 ++++++++--- 2 files changed, 154 insertions(+), 81 deletions(-) diff --git a/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php b/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php index 7a87bddd7f1f7..13f0ec5fad479 100644 --- a/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php +++ b/lib/compat/wordpress-6.4/html-api/class-gutenberg-html-tag-processor-6-4.php @@ -626,6 +626,94 @@ public function next_tag( $query = null ) { } + /** + * Generator for a foreach loop to step through each class name for the matched tag. + * + * This generator function is designed to be used inside a "foreach" loop. + * + * Example: + * + * $p = new WP_HTML_Tag_Processor( "" ); + * $p->next_tag(); + * foreach ( $p->class_list() as $class_name ) { + * echo "{$class_name} "; + * } + * // Outputs: "free lang-en " + * + * @since 6.4.0 + */ + public function class_list() { + /** @var string $class contains the string value of the class attribute, with character references decoded. */ + $class = $this->get_attribute( 'class' ); + + if ( ! is_string( $class ) ) { + return; + } + + $seen = array(); + + $at = 0; + while ( $at < strlen( $class ) ) { + // Skip past any initial boundary characters. + $at += strspn( $class, " \t\f\r\n", $at ); + if ( $at >= strlen( $class ) ) { + return; + } + + // Find the byte length until the next boundary. + $length = strcspn( $class, " \t\f\r\n", $at ); + if ( 0 === $length ) { + return; + } + + /* + * CSS class names are case-insensitive in the ASCII range. + * + * @see https://www.w3.org/TR/CSS2/syndata.html#x1 + */ + $name = strtolower( substr( $class, $at, $length ) ); + $at += $length; + + /* + * It's expected that the number of class names for a given tag is relatively small. + * Given this, it is probably faster overall to scan an array for a value rather + * than to use the class name as a key and check if it's a key of $seen. + */ + if ( in_array( $name, $seen, true ) ) { + continue; + } + + $seen[] = $name; + yield $name; + } + } + + + /** + * Returns if a matched tag contains the given ASCII case-insensitive class name. + * + * @since 6.4.0 + * + * @param string $wanted_class Look for this CSS class name, ASCII case-insensitive. + * @return bool|null Whether the matched tag contains the given class name, or null if not matched. + */ + public function has_class( $wanted_class ) { + if ( ! $this->tag_name_starts_at ) { + return null; + } + + $wanted_class = strtolower( $wanted_class ); + + foreach ( $this->class_list() as $class_name ) { + if ( $class_name === $wanted_class ) { + return true; + } + } + + return false; + } + + /** * Sets a bookmark in the HTML document. * @@ -2347,64 +2435,7 @@ private function matches() { } } - $needs_class_name = null !== $this->sought_class_name; - - if ( $needs_class_name && ! isset( $this->attributes['class'] ) ) { - return false; - } - - /* - * Match byte-for-byte (case-sensitive and encoding-form-sensitive) on the class name. - * - * This will overlook certain classes that exist in other lexical variations - * than was supplied to the search query, but requires more complicated searching. - */ - if ( $needs_class_name ) { - $class_start = $this->attributes['class']->value_starts_at; - $class_end = $class_start + $this->attributes['class']->value_length; - $class_at = $class_start; - - /* - * Ensure that boundaries surround the class name to avoid matching on - * substrings of a longer name. For example, the sequence "not-odd" - * should not match for the class "odd" even though "odd" is found - * within the class attribute text. - * - * See https://html.spec.whatwg.org/#attributes-3 - * See https://html.spec.whatwg.org/#space-separated-tokens - */ - while ( - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition - false !== ( $class_at = strpos( $this->html, $this->sought_class_name, $class_at ) ) && - $class_at < $class_end - ) { - /* - * Verify this class starts at a boundary. - */ - if ( $class_at > $class_start ) { - $character = $this->html[ $class_at - 1 ]; - - if ( ' ' !== $character && "\t" !== $character && "\f" !== $character && "\r" !== $character && "\n" !== $character ) { - $class_at += strlen( $this->sought_class_name ); - continue; - } - } - - /* - * Verify this class ends at a boundary as well. - */ - if ( $class_at + strlen( $this->sought_class_name ) < $class_end ) { - $character = $this->html[ $class_at + strlen( $this->sought_class_name ) ]; - - if ( ' ' !== $character && "\t" !== $character && "\f" !== $character && "\r" !== $character && "\n" !== $character ) { - $class_at += strlen( $this->sought_class_name ); - continue; - } - } - - return true; - } - + if ( null !== $this->sought_class_name && ! $this->has_class( $this->sought_class_name ) ) { return false; } diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php index 2e4b5a47589e8..e53e64c80e2e0 100644 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php +++ b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php @@ -43,7 +43,7 @@ * * Example: * - * $processor = WP_HTML_Processor::createFragment( $html ); + * $processor = WP_HTML_Processor::create_fragment( $html ); * if ( $processor->next_tag( array( 'breadcrumbs' => array( 'DIV', 'FIGURE', 'IMG' ) ) ) ) { * $processor->add_class( 'responsive-image' ); * } @@ -62,7 +62,7 @@ * Since all elements find themselves inside a full HTML document * when parsed, the return value from `get_breadcrumbs()` will always * contain any implicit outermost elements. For example, when parsing - * with `createFragment()` in the `BODY` context (the default), any + * with `create_fragment()` in the `BODY` context (the default), any * tag in the given HTML document will contain `array( 'HTML', 'BODY', … )` * in its breadcrumbs. * @@ -243,7 +243,7 @@ class WP_HTML_Processor extends Gutenberg_HTML_Tag_Processor_6_4 { * @param string $encoding Text encoding of the document; must be default of 'UTF-8'. * @return WP_HTML_Processor|null The created processor if successful, otherwise null. */ - public static function createFragment( $html, $context = '', $encoding = 'UTF-8' ) { + public static function create_fragment( $html, $context = '', $encoding = 'UTF-8' ) { if ( '' !== $context || 'UTF-8' !== $encoding ) { return null; } @@ -284,7 +284,7 @@ public static function createFragment( $html, $context = '', $encoding = ' * * @since 6.4.0 * - * @see WP_HTML_Processor::createFragment() + * @see WP_HTML_Processor::create_fragment() * * @param string $html HTML to process. * @param string|null $use_the_static_create_methods_instead This constructor should not be called manually. @@ -296,9 +296,9 @@ public function __construct( $html, $use_the_static_create_methods_instead = nul _doing_it_wrong( __METHOD__, sprintf( - /* translators: %s: WP_HTML_Processor::createFragment. */ + /* translators: %s: WP_HTML_Processor::create_fragment(). */ __( 'Call %s to create an HTML Processor instead of calling the constructor directly.' ), - 'WP_HTML_Processor::createFragment' + 'WP_HTML_Processor::create_fragment()' ), '6.4.0' ); @@ -328,7 +328,7 @@ public function __construct( $html, $use_the_static_create_methods_instead = nul * * Example * - * $processor = WP_HTML_Processor::createFragment( '' ); + * $processor = WP_HTML_Processor::create_fragment( '' ); * false === $processor->next_tag(); * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); * @@ -361,6 +361,7 @@ public function get_last_error() { * Defaults to first tag. * @type string|null $class_name Tag must contain this whole class name to match. * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. * } * @return bool Whether a tag was matched. */ @@ -410,26 +411,67 @@ public function next_tag( $query = null ) { $breadcrumbs = $query['breadcrumbs']; $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; - $crumb = end( $breadcrumbs ); - $target = strtoupper( $crumb ); while ( $match_offset > 0 && $this->step() ) { - if ( $target !== $this->get_tag() ) { - continue; + if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { + return true; } + } - // Look up the stack to see if the breadcrumbs match. - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - if ( strtoupper( $crumb ) !== $node->node_name ) { - break; - } + return false; + } - $crumb = prev( $breadcrumbs ); - if ( false === $crumb && 0 === --$match_offset && ! $this->is_tag_closer() ) { - return true; - } + /** + * Indicates if the currently-matched tag matches the given breadcrumbs. + * + * A "*" represents a single tag wildcard, where any tag matches, but not no tags. + * + * At some point this function _may_ support a `**` syntax for matching any number + * of unspecified tags in the breadcrumb stack. This has been intentionally left + * out, however, to keep this function simple and to avoid introducing backtracking, + * which could open up surprising performance breakdowns. + * + * Example: + * + * $processor = WP_HTML_Processor::create_fragment( '' ); + * $processor->next_tag( 'img' ); + * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); + * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); + * + * @since 6.4.0 + * + * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. + * @return bool Whether the currently-matched tag is found at the given nested structure. + */ + public function matches_breadcrumbs( $breadcrumbs ) { + if ( ! $this->get_tag() ) { + return false; + } + + // Everything matches when there are zero constraints. + if ( 0 === count( $breadcrumbs ) ) { + return true; + } + + // Start at the last crumb. + $crumb = end( $breadcrumbs ); + + if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { + return false; + } + + foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { + $crumb = strtoupper( current( $breadcrumbs ) ); + + if ( '*' !== $crumb && $node->node_name !== $crumb ) { + return false; } - $crumb = end( $breadcrumbs ); + if ( false === prev( $breadcrumbs ) ) { + return true; + } } return false; @@ -519,7 +561,7 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { * * Example * - * $processor = WP_HTML_Processor::createFragment( '' ); + * $processor = WP_HTML_Processor::create_fragment( '' ); * $processor->next_tag( 'IMG' ); * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); * @@ -1401,5 +1443,5 @@ public static function is_void( $tag_name ) { * * @access private */ - const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::createFragment instead of calling the class constructor directly.'; + const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; } From 887cf3dfc4b3426ce5696a383216186233c468e1 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:42:00 +1100 Subject: [PATCH 05/32] Private APIs: Update consent string for unlocking access. (#55182) Replace the consent string with `I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress`. --- docs/contributors/code/coding-guidelines.md | 2 +- packages/block-editor/src/lock-unlock.js | 2 +- packages/block-library/src/lock-unlock.js | 2 +- packages/blocks/src/lock-unlock.js | 2 +- packages/commands/src/lock-unlock.js | 2 +- packages/components/src/private-apis.ts | 2 +- packages/core-commands/src/lock-unlock.js | 2 +- packages/core-data/src/private-apis.js | 2 +- packages/customize-widgets/src/lock-unlock.js | 2 +- packages/data/src/lock-unlock.js | 2 +- packages/edit-post/src/lock-unlock.js | 2 +- packages/edit-site/src/lock-unlock.js | 2 +- packages/edit-widgets/src/lock-unlock.js | 2 +- packages/editor/src/lock-unlock.js | 2 +- packages/patterns/src/lock-unlock.js | 2 +- packages/private-apis/README.md | 4 ++-- packages/private-apis/src/implementation.js | 2 +- packages/private-apis/src/test/index.js | 2 +- packages/reusable-blocks/src/lock-unlock.js | 2 +- packages/router/src/lock-unlock.js | 2 +- 20 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/contributors/code/coding-guidelines.md b/docs/contributors/code/coding-guidelines.md index 90fb5c7adf81f..53f0a0f8d1000 100644 --- a/docs/contributors/code/coding-guidelines.md +++ b/docs/contributors/code/coding-guidelines.md @@ -162,7 +162,7 @@ do so by opting-in to `@wordpress/private-apis`: import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' // Name of the package calling __dangerousOptInToUnstableAPIsOnlyForCoreModules, // (not the name of the package whose APIs you want to access) ); diff --git a/packages/block-editor/src/lock-unlock.js b/packages/block-editor/src/lock-unlock.js index 019821d284b36..433a61a12aec0 100644 --- a/packages/block-editor/src/lock-unlock.js +++ b/packages/block-editor/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' ); diff --git a/packages/block-library/src/lock-unlock.js b/packages/block-library/src/lock-unlock.js index 3fef0820721be..3c18e76b798cd 100644 --- a/packages/block-library/src/lock-unlock.js +++ b/packages/block-library/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-library' ); diff --git a/packages/blocks/src/lock-unlock.js b/packages/blocks/src/lock-unlock.js index 363b51af7d233..0a98fcfb19d29 100644 --- a/packages/blocks/src/lock-unlock.js +++ b/packages/blocks/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/blocks' ); diff --git a/packages/commands/src/lock-unlock.js b/packages/commands/src/lock-unlock.js index 0665114d842c3..e11bd687d8742 100644 --- a/packages/commands/src/lock-unlock.js +++ b/packages/commands/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/commands' ); diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index fd61c2564e6b0..fa086f783b4b2 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -34,7 +34,7 @@ import Theme from './theme'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/components' ); diff --git a/packages/core-commands/src/lock-unlock.js b/packages/core-commands/src/lock-unlock.js index 24973274f1897..6f0712a8069fd 100644 --- a/packages/core-commands/src/lock-unlock.js +++ b/packages/core-commands/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/core-commands' ); diff --git a/packages/core-data/src/private-apis.js b/packages/core-data/src/private-apis.js index a5b93a25dbf77..53f0dc2dfa133 100644 --- a/packages/core-data/src/private-apis.js +++ b/packages/core-data/src/private-apis.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/core-data' ); diff --git a/packages/customize-widgets/src/lock-unlock.js b/packages/customize-widgets/src/lock-unlock.js index f428bbaac936a..01d57a2835d5d 100644 --- a/packages/customize-widgets/src/lock-unlock.js +++ b/packages/customize-widgets/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/customize-widgets' ); diff --git a/packages/data/src/lock-unlock.js b/packages/data/src/lock-unlock.js index 5fdca775a27b8..b5b1f9cbed5a5 100644 --- a/packages/data/src/lock-unlock.js +++ b/packages/data/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/data' ); diff --git a/packages/edit-post/src/lock-unlock.js b/packages/edit-post/src/lock-unlock.js index 172d18df7d1ba..bf65b262d9f48 100644 --- a/packages/edit-post/src/lock-unlock.js +++ b/packages/edit-post/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-post' ); diff --git a/packages/edit-site/src/lock-unlock.js b/packages/edit-site/src/lock-unlock.js index 9934484ea2347..5c335db46b9d4 100644 --- a/packages/edit-site/src/lock-unlock.js +++ b/packages/edit-site/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-site' ); diff --git a/packages/edit-widgets/src/lock-unlock.js b/packages/edit-widgets/src/lock-unlock.js index a13068520e077..003e53788068c 100644 --- a/packages/edit-widgets/src/lock-unlock.js +++ b/packages/edit-widgets/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-widgets' ); diff --git a/packages/editor/src/lock-unlock.js b/packages/editor/src/lock-unlock.js index 5a36d0cd752f4..12df6f4711b23 100644 --- a/packages/editor/src/lock-unlock.js +++ b/packages/editor/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/editor' ); diff --git a/packages/patterns/src/lock-unlock.js b/packages/patterns/src/lock-unlock.js index 51adc98f32cac..d727871d71439 100644 --- a/packages/patterns/src/lock-unlock.js +++ b/packages/patterns/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/patterns' ); diff --git a/packages/private-apis/README.md b/packages/private-apis/README.md index 9faaada853200..cdc1db2180e2c 100644 --- a/packages/private-apis/README.md +++ b/packages/private-apis/README.md @@ -12,7 +12,7 @@ Every `@wordpress` package wanting to privately access or expose experimental AP import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' // Name of the package calling __dangerousOptInToUnstableAPIsOnlyForCoreModules, // (not the name of the package whose APIs you want to access) ); @@ -22,7 +22,7 @@ Each package may only opt in once. The function name communicates that plugins a The function will throw an error if the following conditions are not met: -1. The first argument must exactly match the required consent string: `'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'`. +1. The first argument must exactly match the required consent string: `'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'`. 2. The second argument must be a known `@wordpress` package that hasn't yet opted into `@wordpress/private-apis` Once the opt-in is complete, the obtained `lock()` and `unlock()` utilities enable hiding `__experimental` APIs from the naked eye: diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index 4f1877bff569e..14d3048eff68b 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -51,7 +51,7 @@ const registeredPrivateApis = []; * CHANGE MAY OCCUR IN EITHER A MAJOR OR MINOR RELEASE. */ const requiredConsent = - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'; /** @type {boolean} */ let allowReRegistration; diff --git a/packages/private-apis/src/test/index.js b/packages/private-apis/src/test/index.js index 2e73a1a58eaa1..d91f7d3bcdafe 100644 --- a/packages/private-apis/src/test/index.js +++ b/packages/private-apis/src/test/index.js @@ -16,7 +16,7 @@ beforeEach( () => { } ); const requiredConsent = - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'; describe( '__dangerousOptInToUnstableAPIsOnlyForCoreModules', () => { it( 'Should require a consent string', () => { diff --git a/packages/reusable-blocks/src/lock-unlock.js b/packages/reusable-blocks/src/lock-unlock.js index c33f209c9d76a..c0bc2d1529f7d 100644 --- a/packages/reusable-blocks/src/lock-unlock.js +++ b/packages/reusable-blocks/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/reusable-blocks' ); diff --git a/packages/router/src/lock-unlock.js b/packages/router/src/lock-unlock.js index d148f785fe944..d7f4e92b4a542 100644 --- a/packages/router/src/lock-unlock.js +++ b/packages/router/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/router' ); From 84ed4a69e9715e71bcc4f3593154c3b82dd16531 Mon Sep 17 00:00:00 2001 From: Cullen Whitmore Date: Tue, 10 Oct 2023 19:41:22 -0500 Subject: [PATCH 06/32] docs: Update broken anchor link (#55233) --- packages/create-block/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index edcdd020caf38..88ac97c34c2cf 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -28,7 +28,7 @@ $ cd todo-list $ npm start ``` -The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation). +The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation-1). _(requires `node` version `14.0.0` or above, and `npm` version `6.14.4` or above)_ From 7602b560eca577d58ccbdf41d42ed5186caccc80 Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 10 Oct 2023 13:58:37 -0700 Subject: [PATCH 07/32] Block Supports: Backport optimization from Core for Elements Support Brings over optimization surfaced during the WordPress 6.4 beta release for block supports elements, which entails skipping needless iteration when it's known that the iteration need not continue. See WordPress/wordpress-develop#5411 See [#59544-trac](https://core.trac.wordpress.org/ticket/59544) --- lib/block-supports/elements.php | 88 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 2106360c4bd04..85dbd7d39797c 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -13,7 +13,7 @@ * @return string Filtered block content. */ function gutenberg_render_elements_support( $block_content, $block ) { - if ( ! $block_content || empty( $block['attrs'] ) ) { + if ( ! $block_content || ! isset( $block['attrs']['style']['elements'] ) ) { return $block_content; } @@ -23,42 +23,42 @@ function gutenberg_render_elements_support( $block_content, $block ) { 'button' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ), 'paths' => array( - 'style.elements.button.color.text', - 'style.elements.button.color.background', - 'style.elements.button.color.gradient', + array( 'button', 'color', 'text' ), + array( 'button', 'color', 'background' ), + array( 'button', 'color', 'gradient' ), ), ), 'link' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ), 'paths' => array( - 'style.elements.link.color.text', - 'style.elements.link.:hover.color.text', + array( 'link', 'color', 'text' ), + array( 'link', ':hover', 'color', 'text' ), ), ), 'heading' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ), 'paths' => array( - 'style.elements.heading.color.text', - 'style.elements.heading.color.background', - 'style.elements.heading.color.gradient', - 'style.elements.h1.color.text', - 'style.elements.h1.color.background', - 'style.elements.h1.color.gradient', - 'style.elements.h2.color.text', - 'style.elements.h2.color.background', - 'style.elements.h2.color.gradient', - 'style.elements.h3.color.text', - 'style.elements.h3.color.background', - 'style.elements.h3.color.gradient', - 'style.elements.h4.color.text', - 'style.elements.h4.color.background', - 'style.elements.h4.color.gradient', - 'style.elements.h5.color.text', - 'style.elements.h5.color.background', - 'style.elements.h5.color.gradient', - 'style.elements.h6.color.text', - 'style.elements.h6.color.background', - 'style.elements.h6.color.gradient', + array( 'heading', 'color', 'text' ), + array( 'heading', 'color', 'background' ), + array( 'heading', 'color', 'gradient' ), + array( 'h1', 'color', 'text' ), + array( 'h1', 'color', 'background' ), + array( 'h1', 'color', 'gradient' ), + array( 'h2', 'color', 'text' ), + array( 'h2', 'color', 'background' ), + array( 'h2', 'color', 'gradient' ), + array( 'h3', 'color', 'text' ), + array( 'h3', 'color', 'background' ), + array( 'h3', 'color', 'gradient' ), + array( 'h4', 'color', 'text' ), + array( 'h4', 'color', 'background' ), + array( 'h4', 'color', 'gradient' ), + array( 'h5', 'color', 'text' ), + array( 'h5', 'color', 'background' ), + array( 'h5', 'color', 'gradient' ), + array( 'h6', 'color', 'text' ), + array( 'h6', 'color', 'background' ), + array( 'h6', 'color', 'gradient' ), ), ), ); @@ -71,7 +71,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { return $block_content; } - $element_colors_set = 0; + $elements_style_attributes = $block['attrs']['style']['elements']; foreach ( $element_color_properties as $element_config ) { if ( $element_config['skip'] ) { @@ -79,24 +79,28 @@ function gutenberg_render_elements_support( $block_content, $block ) { } foreach ( $element_config['paths'] as $path ) { - if ( null !== _wp_array_get( $block['attrs'], explode( '.', $path ), null ) ) { - ++$element_colors_set; + if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) { + /* + * It only takes a single custom attribute to require that the custom + * class name be added to the block, so once one is found there's no + * need to continue looking for others. + * + * As is done with the layout hook, this code assumes that the block + * contains a single wrapper and that it's the first element in the + * rendered output. That first element, if it exists, gets the class. + */ + $tags = new WP_HTML_Tag_Processor( $block_content ); + if ( $tags->next_tag() ) { + $tags->add_class( wp_get_elements_class_name( $block ) ); + } + + return $tags->get_updated_html(); } } } - if ( ! $element_colors_set ) { - return $block_content; - } - - // Like the layout hook this assumes the hook only applies to blocks with a single wrapper. - // Add the class name to the first element, presuming it's the wrapper, if it exists. - $tags = new WP_HTML_Tag_Processor( $block_content ); - if ( $tags->next_tag() ) { - $tags->add_class( wp_get_elements_class_name( $block ) ); - } - - return $tags->get_updated_html(); + // If no custom attributes were found then there's nothing to modify. + return $block_content; } /** From 4d04850d1a03c55689844bccc20916129b962519 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 11 Oct 2023 14:04:04 +1100 Subject: [PATCH 08/32] Remove `@return void` from PHP function docs. (#55237) --- packages/block-library/src/form/index.php | 4 ---- packages/block-library/src/image/index.php | 4 ---- packages/block-library/src/pattern/index.php | 2 -- packages/block-library/src/search/index.php | 4 ---- 4 files changed, 14 deletions(-) diff --git a/packages/block-library/src/form/index.php b/packages/block-library/src/form/index.php index 0dbbaf6838740..b9e3a9c25c628 100644 --- a/packages/block-library/src/form/index.php +++ b/packages/block-library/src/form/index.php @@ -83,8 +83,6 @@ function block_core_form_extra_fields_comment_form( $extra_fields, $attributes ) /** * Sends an email if the form is a contact form. - * - * @return void */ function block_core_form_send_email() { check_ajax_referer( 'wp-block-form' ); @@ -126,8 +124,6 @@ function block_core_form_send_email() { /** * Send the data export/remove request if the form is a privacy-request form. - * - * @return void */ function block_core_form_privacy_form() { // Get the POST data. diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index e1f71964622c0..9cce87d9e8bd7 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -310,8 +310,6 @@ function block_core_image_render_lightbox( $block_content, $block ) { * @since 6.4.0 * * @global WP_Scripts $wp_scripts - * - * @return void */ function block_core_image_ensure_interactivity_dependency() { global $wp_scripts; @@ -327,8 +325,6 @@ function block_core_image_ensure_interactivity_dependency() { /** * Registers the `core/image` block on server. - * - * @return void */ function register_block_core_image() { register_block_type_from_metadata( diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index fc4652a7c22e8..1f5477968b92d 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -7,8 +7,6 @@ /** * Registers the `core/pattern` block on the server. - * - * @return void */ function register_block_core_pattern() { register_block_type_from_metadata( diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index ed3d1cf4b847a..f00ecfe6abe1c 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -281,8 +281,6 @@ function classnames_for_block_core_search( $attributes ) { * @param array $wrapper_styles Current collection of wrapper styles. * @param array $button_styles Current collection of button styles. * @param array $input_styles Current collection of input styles. - * - * @return void */ function apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) { $is_button_inside = isset( $attributes['buttonPosition'] ) && 'button-inside' === $attributes['buttonPosition']; @@ -327,8 +325,6 @@ function apply_block_core_search_border_style( $attributes, $property, $side, &$ * @param array $wrapper_styles Current collection of wrapper styles. * @param array $button_styles Current collection of button styles. * @param array $input_styles Current collection of input styles. - * - * @return void */ function apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) { apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles ); From f29a96b3fa63eabbd1d97f0f7e66b070986752b1 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr Date: Wed, 11 Oct 2023 08:49:34 +0200 Subject: [PATCH 09/32] useBlockSettings: add missing useMemo dependencies (#55204) --- packages/block-editor/src/hooks/utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index f81fc118ea84b..8e0d422c5fbec 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -279,6 +279,8 @@ export function useBlockSettings( name, parentLayout ) { isBackgroundEnabled, isLinkEnabled, isTextEnabled, + isHeadingEnabled, + isButtonEnabled, ] ); return useSettingsForBlockElement( rawSettings, name ); From 8a9cb70272edcfdfd34f3557848949eb0fd29921 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Oct 2023 07:56:23 +0100 Subject: [PATCH 10/32] DataViews: Allow actions to be provided declaratively as a prop (#55192) * DataViews: Allow actions to be provided declaratively as a prop * Restore PageActions component * Rename variable * Fix typo --- .../src/components/actions/trash-post.js | 55 +++++++++++++++++++ .../src/components/dataviews/dataviews.js | 51 ++++++++++++++++- .../src/components/page-actions/index.js | 8 +-- .../src/components/page-pages/index.js | 18 ++---- 4 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 packages/edit-site/src/components/actions/trash-post.js diff --git a/packages/edit-site/src/components/actions/trash-post.js b/packages/edit-site/src/components/actions/trash-post.js new file mode 100644 index 0000000000000..7977ed3d11e00 --- /dev/null +++ b/packages/edit-site/src/components/actions/trash-post.js @@ -0,0 +1,55 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { decodeEntities } from '@wordpress/html-entities'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useMemo } from '@wordpress/element'; + +export default function useMoveToTrashAction() { + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + const { deleteEntityRecord } = useDispatch( coreStore ); + + return useMemo( + () => ( { + id: 'move-to-trash', + label: __( 'Move to Trash' ), + async perform( post ) { + try { + await deleteEntityRecord( + 'postType', + post.type, + post.id, + {}, + { throwOnError: true } + ); + createSuccessNotice( + sprintf( + /* translators: The page's title. */ + __( '"%s" moved to the Trash.' ), + decodeEntities( post.title.rendered ) + ), + { + type: 'snackbar', + id: 'edit-site-page-trashed', + } + ); + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( + 'An error occurred while moving the page to the trash.' + ); + + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + }, + isDesctructive: true, + } ), + [ createSuccessNotice, createErrorNotice, deleteEntityRecord ] + ); +} diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 4628d850a023c..13e27ddfacae5 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -15,7 +15,13 @@ import { import { __experimentalVStack as VStack, __experimentalHStack as HStack, + VisuallyHidden, + DropdownMenu, + MenuGroup, + MenuItem, } from '@wordpress/components'; +import { useMemo } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -24,8 +30,10 @@ import ListView from './list-view'; import { Pagination } from './pagination'; import ViewActions from './view-actions'; import TextFilter from './text-filter'; +import { moreVertical } from '@wordpress/icons'; export default function DataViews( { + actions, data, fields, view, @@ -34,9 +42,50 @@ export default function DataViews( { paginationInfo, options: { pageCount }, } ) { + const columns = useMemo( () => { + const _columns = [ ...fields ]; + if ( actions && actions.length ) { + _columns.push( { + header: { __( 'Actions' ) }, + id: 'actions', + cell: ( props ) => { + return ( + + { () => ( + + { actions.map( ( action ) => ( + + action.perform( + props.row.original + ) + } + isDestructive={ + action.isDesctructive + } + > + { action.label } + + ) ) } + + ) } + + ); + }, + enableHiding: false, + } ); + } + + return _columns; + }, [ fields, actions ] ); + const dataView = useReactTable( { data, - columns: fields, + columns, manualSorting: true, manualFiltering: true, manualPagination: true, diff --git a/packages/edit-site/src/components/page-actions/index.js b/packages/edit-site/src/components/page-actions/index.js index f6f0119a16454..d42a706c36796 100644 --- a/packages/edit-site/src/components/page-actions/index.js +++ b/packages/edit-site/src/components/page-actions/index.js @@ -10,17 +10,11 @@ import { moreVertical } from '@wordpress/icons'; */ import TrashPageMenuItem from './trash-page-menu-item'; -export default function PageActions( { - postId, - className, - toggleProps, - onRemove, -} ) { +export default function PageActions( { postId, toggleProps, onRemove } ) { return ( { () => ( diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 56575248453f0..2c7b07044dbdd 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { - VisuallyHidden, __experimentalHeading as Heading, __experimentalVStack as VStack, } from '@wordpress/components'; @@ -16,8 +15,8 @@ import { useState, useMemo } from '@wordpress/element'; */ import Page from '../page'; import Link from '../routes/link'; -import PageActions from '../page-actions'; import { DataViews } from '../dataviews'; +import useTrashPostAction from '../actions/trash-post'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -118,27 +117,22 @@ export default function PagePages() { postStatuses[ page.status ] ?? page.status, enableSorting: false, }, - { - header: { __( 'Actions' ) }, - id: 'actions', - cell: ( props ) => { - const page = props.row.original; - return ; - }, - enableHiding: false, - }, ], [ postStatuses ] ); + const trashPostAction = useTrashPostAction(); + const actions = useMemo( () => [ trashPostAction ], [ trashPostAction ] ); + // TODO: we need to handle properly `data={ data || EMPTY_ARRAY }` for when `isLoading`. return ( Date: Wed, 11 Oct 2023 10:02:46 +0200 Subject: [PATCH 11/32] Remove the lightbox filter and view file when the lightbox setting is disabled. (#55120) * Remove the filter and view file of the lightbox when the lightbox setting is disabled. * Make sure to add filter and view file when needed. * Fix block comment indentation. --- packages/block-library/src/image/index.php | 62 +++++++++++----------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 9cce87d9e8bd7..4213350ab05c8 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -32,45 +32,47 @@ function render_block_core_image( $attributes, $content, $block ) { $processor->set_attribute( 'data-id', $attributes['data-id'] ); } - $lightbox_enabled = false; $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block ); - // If the lightbox is enabled and the image is not linked, flag the lightbox to be rendered. - if ( isset( $lightbox_settings ) && 'none' === $link_destination ) { + $view_js_file_handle = 'wp-block-image-view'; + $script_handles = $block->block_type->view_script_handles; - if ( isset( $lightbox_settings['enabled'] ) && true === $lightbox_settings['enabled'] ) { - $lightbox_enabled = true; - } - } - - // If at least one block in the page has the lightbox, mark the block type as interactive. - if ( $lightbox_enabled ) { + /* + * If the lightbox is enabled and the image is not linked, add the filter + * and the JavaScript view file. + */ + if ( + isset( $lightbox_settings ) && + 'none' === $link_destination && + isset( $lightbox_settings['enabled'] ) && + true === $lightbox_settings['enabled'] + ) { $block->block_type->supports['interactivity'] = true; - } - - // Determine whether the view script should be enqueued or not. - $view_js_file = 'wp-block-image-view'; - if ( ! wp_script_is( $view_js_file ) ) { - $script_handles = $block->block_type->view_script_handles; - // If the script is not needed, and it is still in the `view_script_handles`, remove it. - if ( ! $lightbox_enabled && in_array( $view_js_file, $script_handles, true ) ) { - $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) ); - } - // If the script is needed, but it was previously removed, add it again. - if ( $lightbox_enabled && ! in_array( $view_js_file, $script_handles, true ) ) { - $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) ); + if ( ! in_array( $view_js_file_handle, $script_handles, true ) ) { + $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file_handle ) ); } - } - if ( $lightbox_enabled ) { - // This render needs to happen in a filter with priority 15 to ensure that it - // runs after the duotone filter and that duotone styles are applied to the image - // in the lightbox. We also need to ensure that the lightbox works with any plugins - // that might use filters as well. We can consider removing this in the future if the - // way the blocks are rendered changes, or if a new kind of filter is introduced. + /* + * This render needs to happen in a filter with priority 15 to ensure + * that it runs after the duotone filter and that duotone styles are + * applied to the image in the lightbox. We also need to ensure that the + * lightbox works with any plugins that might use filters as well. We + * can consider removing this in the future if the way the blocks are + * rendered changes, or if a new kind of filter is introduced. + */ add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 ); + } else { + /* + * Remove the filter and the JavaScript view file if previously added by + * other Image blocks. + */ + remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 ); + // If the script is not needed, and it is still in the `view_script_handles`, remove it. + if ( in_array( $view_js_file_handle, $script_handles, true ) ) { + $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file_handle ) ); + } } return $processor->get_updated_html(); From e1258031c11cd23d8d30bcf2521a81d04e512491 Mon Sep 17 00:00:00 2001 From: Andrew Hayward Date: Wed, 11 Oct 2023 09:48:07 +0100 Subject: [PATCH 12/32] Add `type="button"` to vanilla `` elements (#55125) * Adding `type="button` to buttons as needed * Updating test snapshots * Updating `CHANGELOG.md` --- .../color-palette/test/__snapshots__/control.js.snap | 1 + packages/block-library/src/page-list-item/edit.js | 2 ++ packages/components/CHANGELOG.md | 3 ++- packages/components/src/color-palette/index.tsx | 1 + .../test/__snapshots__/index.tsx.snap | 8 ++++++++ .../toggle-group-control-option-base/component.tsx | 1 + .../src/components/block-editor/resize-handle.js | 1 + .../edit-site/src/components/page-patterns/grid-item.js | 1 + 8 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index 242218705b3cf..3942c05ce96f1 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -175,6 +175,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` aria-label="Custom color picker. The currently selected color is called "red" and has a value of "#f00"." class="components-color-palette__custom-color-button" style="background: rgb(255, 0, 0);" + type="button" /> @@ -90,6 +91,7 @@ export default function PageListItemEdit( { context, attributes } ) { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3dfc268ad2163..0605bda1a47e5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). ### Bug Fix @@ -52,7 +53,7 @@ ### Experimental -- Introduce `Tabs`, an experimental v2 of `TabPanel`: ([#53960](https://github.com/WordPress/gutenberg/pull/53960)). +- Introduce `Tabs`, an experimental v2 of `TabPanel`: ([#53960](https://github.com/WordPress/gutenberg/pull/53960)). ## 25.8.0 (2023-09-20) diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index f87d46e64bc09..297e03f389e3e 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -299,6 +299,7 @@ function UnforwardedColorPalette( style={ { background: value, } } + type="button" /> { onFocusProp?.( event ); diff --git a/packages/edit-site/src/components/block-editor/resize-handle.js b/packages/edit-site/src/components/block-editor/resize-handle.js index 199ca09869cf9..0e9fae084ec89 100644 --- a/packages/edit-site/src/components/block-editor/resize-handle.js +++ b/packages/edit-site/src/components/block-editor/resize-handle.js @@ -35,6 +35,7 @@ export default function ResizeHandle( { aria-label={ __( 'Drag to resize' ) } aria-describedby={ `resizable-editor__resize-help-${ direction }` } onKeyDown={ handleKeyDown } + type="button" /> Date: Wed, 11 Oct 2023 11:37:25 +0200 Subject: [PATCH 13/32] Patterns: Remove the version enforcement for npm in `engines` field (#55245) * Patterns: Remove the version enforcement for npm in `engines` * Regenerate the lock file --- package-lock.json | 3 +-- packages/patterns/package.json | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 341db8407614b..c457a01b4b74b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57445,8 +57445,7 @@ "@wordpress/url": "file:../url" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8 <9" + "node": ">=16.0.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 0cb8857df9a4b..d8cabf9fae235 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -19,8 +19,7 @@ "url": "https://github.com/WordPress/gutenberg/issues" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8 <9" + "node": ">=16.0.0" }, "main": "build/index.js", "module": "build-module/index.js", From 3c75843af3002ff943dc8802d4f8b7e83cbf209a Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Wed, 11 Oct 2023 11:41:10 +0100 Subject: [PATCH 14/32] fix: Fix border visibility in block-based themes (#54964) --- packages/primitives/src/block-quotation/index.native.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/primitives/src/block-quotation/index.native.js b/packages/primitives/src/block-quotation/index.native.js index 01e8b7cdb4c50..3d0d29c297245 100644 --- a/packages/primitives/src/block-quotation/index.native.js +++ b/packages/primitives/src/block-quotation/index.native.js @@ -20,6 +20,9 @@ export const BlockQuotation = forwardRef( ( { ...props }, ref ) => { styles.wpBlockQuoteLight, styles.wpBlockQuoteDark ), + style?.baseColors?.color?.text && { + borderLeftColor: style.baseColors.color.text, + }, style?.color && { borderLeftColor: style.color, }, From 0c216e400b3cc7764cc27713bf44c31e3712dc57 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 11 Oct 2023 14:45:32 +0300 Subject: [PATCH 15/32] [DataViews]: Update the view config to include fields visibility (#55247) * [DataViews]: Update the view config to include fields visibility * fix typo * use array instead of Set for `hidden` * use `hiddenFields` top level prop --- .../src/components/dataviews/dataviews.js | 39 ++++++++++++++++++- .../src/components/dataviews/view-actions.js | 6 +-- .../src/components/page-pages/index.js | 16 ++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 13e27ddfacae5..0131040bf83af 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -32,6 +32,8 @@ import ViewActions from './view-actions'; import TextFilter from './text-filter'; import { moreVertical } from '@wordpress/icons'; +const EMPTY_OBJECT = {}; + export default function DataViews( { actions, data, @@ -44,7 +46,7 @@ export default function DataViews( { } ) { const columns = useMemo( () => { const _columns = [ ...fields ]; - if ( actions && actions.length ) { + if ( actions?.length ) { _columns.push( { header: { __( 'Actions' ) }, id: 'actions', @@ -83,6 +85,19 @@ export default function DataViews( { return _columns; }, [ fields, actions ] ); + const columnVisibility = useMemo( () => { + if ( ! view.hiddenFields?.length ) { + return; + } + return view.hiddenFields.reduce( + ( accumulator, fieldId ) => ( { + ...accumulator, + [ fieldId ]: false, + } ), + {} + ); + }, [ view.hiddenFields ] ); + const dataView = useReactTable( { data, columns, @@ -104,6 +119,7 @@ export default function DataViews( { pageIndex: view.page, pageSize: view.perPage, }, + columnVisibility: columnVisibility ?? EMPTY_OBJECT, }, onSortingChange: ( sortingUpdater ) => { onChangeView( ( currentView ) => { @@ -135,6 +151,27 @@ export default function DataViews( { }; } ); }, + onColumnVisibilityChange: ( columnVisibilityUpdater ) => { + onChangeView( ( currentView ) => { + const hiddenFields = Object.entries( + columnVisibilityUpdater() + ).reduce( + ( accumulator, [ fieldId, value ] ) => { + if ( value ) { + return accumulator.filter( + ( id ) => id !== fieldId + ); + } + return [ ...accumulator, fieldId ]; + }, + [ ...( currentView.hiddenFields || [] ) ] + ); + return { + ...currentView, + hiddenFields, + }; + } ); + }, onGlobalFilterChange: ( value ) => { onChangeView( { ...view, search: value, page: 0 } ); }, diff --git a/packages/edit-site/src/components/dataviews/view-actions.js b/packages/edit-site/src/components/dataviews/view-actions.js index 1ede6ebcd8b75..ab9f3be88c200 100644 --- a/packages/edit-site/src/components/dataviews/view-actions.js +++ b/packages/edit-site/src/components/dataviews/view-actions.js @@ -102,10 +102,10 @@ function PageSizeMenu( { dataView } ) { } function FieldsVisibilityMenu( { dataView } ) { - const hideableFields = dataView + const hidableFields = dataView .getAllColumns() .filter( ( columnn ) => columnn.getCanHide() ); - if ( ! hideableFields?.length ) { + if ( ! hidableFields?.length ) { return null; } return ( @@ -118,7 +118,7 @@ function FieldsVisibilityMenu( { dataView } ) { } > - { hideableFields?.map( ( field ) => { + { hidableFields?.map( ( field ) => { return ( { + const formattedDate = dateI18n( + getSettings().formats.datetimeAbbreviated, + getDate( props.row.original.date ) + ); + return { formattedDate }; + }, + enableSorting: false, + }, ], [ postStatuses ] ); From 75ea690cae00f70366357b2976e2aaa0e72c576e Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:04:27 +0300 Subject: [PATCH 16/32] Data views: add linked title fallback (#55248) --- packages/edit-site/src/components/page-pages/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 62276f314f746..ec27265302748 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -91,7 +91,8 @@ export default function PagePages() { canvas: 'edit', } } > - { decodeEntities( props.getValue() ) } + { decodeEntities( props.getValue() ) || + __( '(no title)' ) } From 9e11bfc6f4066a9a288f1e4ddba1e3037d6a53d0 Mon Sep 17 00:00:00 2001 From: Artemio Morales Date: Wed, 11 Oct 2023 07:12:43 -0500 Subject: [PATCH 17/32] Image: Disable lightbox editor UI for linked images (#55141) * Disable lightbox UI and add help text for linked images * Update help text --- packages/block-library/src/image/image.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index d49a8f7cd0578..1f602c4380e88 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -377,6 +377,8 @@ export default function Image( { const lightboxChecked = !! lightbox?.enabled || ( ! lightbox && !! lightboxSetting?.enabled ); + const lightboxToggleDisabled = linkDestination !== 'none'; + const dimensionsControl = ( ) } From bd3ea8771a09e6e86f6d662fe0242089d81c7873 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 11 Oct 2023 14:42:59 +0100 Subject: [PATCH 18/32] Only handle rename UI if selected (#55250) --- packages/block-editor/src/hooks/block-rename-ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-rename-ui.js b/packages/block-editor/src/hooks/block-rename-ui.js index 6a98dcf2e2fad..aec11a9b2c657 100644 --- a/packages/block-editor/src/hooks/block-rename-ui.js +++ b/packages/block-editor/src/hooks/block-rename-ui.js @@ -189,13 +189,13 @@ function BlockRenameControl( props ) { export const withBlockRenameControl = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { - const { clientId, name, attributes, setAttributes } = props; + const { clientId, name, attributes, setAttributes, isSelected } = props; const supportsBlockNaming = hasBlockSupport( name, 'renaming', true ); return ( <> - { supportsBlockNaming && ( + { isSelected && supportsBlockNaming && ( <> Date: Wed, 11 Oct 2023 15:53:52 +0200 Subject: [PATCH 19/32] Colors: Fix color button border radii (#55207) * Apply the classname prop to `ToolsPanelItem` only when it s not a placeholder * Color Gradient panel: use new selctors to select first and last items * Add fallback for browsers not yet supporting the `:has()` selector * Use nth-child notation instead of :has and sibling selector * CHANGELOG --- .../src/components/colors-gradients/style.scss | 6 ++++-- packages/components/CHANGELOG.md | 1 + .../src/tools-panel/tools-panel-item/hook.ts | 10 ++++------ .../components/src/tools-panel/tools-panel/README.md | 3 +++ packages/components/src/tools-panel/types.ts | 2 ++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/colors-gradients/style.scss b/packages/block-editor/src/components/colors-gradients/style.scss index 8b36f04b83552..6cade124b7fe4 100644 --- a/packages/block-editor/src/components/colors-gradients/style.scss +++ b/packages/block-editor/src/components/colors-gradients/style.scss @@ -77,14 +77,16 @@ $swatch-gap: 12px; border-right: 1px solid $gray-300; border-bottom: 1px solid $gray-300; - &.first { + // Identify the first visible instance as placeholder items will not have this class. + &:nth-child(1 of &) { margin-top: $grid-unit-30; border-top-left-radius: $radius-block-ui; border-top-right-radius: $radius-block-ui; border-top: 1px solid $gray-300; } - &.last { + // Identify the last visible instance as placeholder items will not have this class. + &:nth-last-child(1 of &) { border-bottom-left-radius: $radius-block-ui; border-bottom-right-radius: $radius-block-ui; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0605bda1a47e5..b3c01c4db2c70 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- `ToolsPanel`: do not apply the `className` to prop to `ToolsPanelItem` components when rendered as placeholders ([#55207](https://github.com/WordPress/gutenberg/pull/55207)). - `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). ### Bug Fix diff --git a/packages/components/src/tools-panel/tools-panel-item/hook.ts b/packages/components/src/tools-panel/tools-panel-item/hook.ts index 95958ae9f4860..23701afdfcfd0 100644 --- a/packages/components/src/tools-panel/tools-panel-item/hook.ts +++ b/packages/components/src/tools-panel/tools-panel-item/hook.ts @@ -176,18 +176,16 @@ export function useToolsPanelItem( const cx = useCx(); const classes = useMemo( () => { - const placeholderStyle = - shouldRenderPlaceholder && - ! isShown && - styles.ToolsPanelItemPlaceholder; + const shouldApplyPlaceholderStyles = + shouldRenderPlaceholder && ! isShown; const firstItemStyle = firstDisplayedItem === label && __experimentalFirstVisibleItemClass; const lastItemStyle = lastDisplayedItem === label && __experimentalLastVisibleItemClass; return cx( styles.ToolsPanelItem, - placeholderStyle, - className, + shouldApplyPlaceholderStyles && styles.ToolsPanelItemPlaceholder, + ! shouldApplyPlaceholderStyles && className, firstItemStyle, lastItemStyle ); diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md index 6802a6436875a..0ee251592d67b 100644 --- a/packages/components/src/tools-panel/tools-panel/README.md +++ b/packages/components/src/tools-panel/tools-panel/README.md @@ -191,5 +191,8 @@ A function to call when the `Reset all` menu option is selected. As an argument, Advises the `ToolsPanel` that all of its `ToolsPanelItem` children should render placeholder content (instead of `null`) when they are toggled off and hidden. +Note that placeholder items won't apply the `className` that would be +normally applied to a visible `ToolsPanelItem` via the `className` prop. + - Required: No - Default: `false` diff --git a/packages/components/src/tools-panel/types.ts b/packages/components/src/tools-panel/types.ts index 183ed3254fe80..3156137e58044 100644 --- a/packages/components/src/tools-panel/types.ts +++ b/packages/components/src/tools-panel/types.ts @@ -50,6 +50,8 @@ export type ToolsPanelProps = { /** * Advises the `ToolsPanel` that its child `ToolsPanelItem`s should render * placeholder content instead of null when they are toggled off and hidden. + * Note that placeholder items won't apply the `className` that would be + * normally applied to a visible `ToolsPanelItem` via the `className` prop. * * @default false */ From bc47191907929ea89236df76063d434d48bff822 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Oct 2023 14:58:10 +0100 Subject: [PATCH 20/32] DataViews: Add featured image field to the page list (#55246) Co-authored-by: ntsekouras --- .../edit-site/src/components/media/index.js | 27 +++++++++++++++++++ .../src/components/page-pages/index.js | 19 +++++++++++-- .../src/components/page-pages/style.scss | 4 +++ packages/edit-site/src/style.scss | 1 + 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 packages/edit-site/src/components/media/index.js create mode 100644 packages/edit-site/src/components/page-pages/style.scss diff --git a/packages/edit-site/src/components/media/index.js b/packages/edit-site/src/components/media/index.js new file mode 100644 index 0000000000000..7120d7c7f56ce --- /dev/null +++ b/packages/edit-site/src/components/media/index.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { useEntityRecord } from '@wordpress/core-data'; + +function Media( { id, size, ...props } ) { + const { record: media } = useEntityRecord( 'root', 'media', id ); + const sizesPerPriority = [ 'large', 'thumbnail' ]; + const currentSize = + size ?? + sizesPerPriority.find( ( s ) => !! media?.media_details?.sizes[ s ] ); + const mediaDetails = media?.media_details?.sizes[ currentSize ]; + + if ( ! mediaDetails ) { + return null; + } + + return ( + + ); +} + +export default Media; diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index ec27265302748..e34e4cbac5be3 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -18,6 +18,7 @@ import Page from '../page'; import Link from '../routes/link'; import { DataViews } from '../dataviews'; import useTrashPostAction from '../actions/trash-post'; +import Media from '../media'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -34,7 +35,7 @@ export default function PagePages() { }, // All fields are visible by default, so it's // better to keep track of the hidden ones. - hiddenFields: [ 'date' ], + hiddenFields: [ 'date', 'featured-image' ], } ); // Request post statuses to get the proper labels. const { records: statuses } = useEntityRecords( 'root', 'status' ); @@ -75,6 +76,20 @@ export default function PagePages() { const fields = useMemo( () => [ + { + id: 'featured-image', + header: __( 'Featured Image' ), + accessorFn: ( page ) => page.featured_media, + cell: ( props ) => + !! props.row.original.featured_media ? ( + + ) : null, + enableSorting: false, + }, { header: __( 'Title' ), id: 'title', @@ -116,7 +131,7 @@ export default function PagePages() { }, }, { - header: 'Status', + header: __( 'Status' ), id: 'status', accessorFn: ( page ) => postStatuses[ page.status ] ?? page.status, diff --git a/packages/edit-site/src/components/page-pages/style.scss b/packages/edit-site/src/components/page-pages/style.scss new file mode 100644 index 0000000000000..82e124b3ac4fe --- /dev/null +++ b/packages/edit-site/src/components/page-pages/style.scss @@ -0,0 +1,4 @@ +.edit-site-page-pages__featured-image { + border-radius: $radius-block-ui; + max-height: 60px; +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index e95cd3571c419..dadbf48d06e64 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -11,6 +11,7 @@ @import "./components/header-edit-mode/document-actions/style.scss"; @import "./components/list/style.scss"; @import "./components/page/style.scss"; +@import "./components/page-pages/style.scss"; @import "./components/page-patterns/style.scss"; @import "./components/table/style.scss"; @import "./components/sidebar-edit-mode/style.scss"; From bab057e96f30f8e2284feec137de88e300a8e0aa Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 15:55:53 +0100 Subject: [PATCH 21/32] Update: Unset variable set by reference after a foreach loop. (#55261) --- lib/class-wp-theme-json-gutenberg.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 3aa07158df853..8c2857fa89d0c 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1065,6 +1065,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' foreach ( $style_nodes as &$node ) { $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] ); } + unset( $node ); } if ( ! empty( $options['root_selector'] ) ) { From 31d16369947199fd806e37ca0667b9ec8c38dc9c Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 15:56:19 +0100 Subject: [PATCH 22/32] Fix: Use y-webrtc room name terminology instead of docName. (#55260) --- packages/sync/src/connect-indexdb.js | 4 ++-- packages/sync/src/connect-webrtc.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sync/src/connect-indexdb.js b/packages/sync/src/connect-indexdb.js index ee56a463fd995..5523640408f57 100644 --- a/packages/sync/src/connect-indexdb.js +++ b/packages/sync/src/connect-indexdb.js @@ -20,8 +20,8 @@ import { IndexeddbPersistence } from 'y-indexeddb'; * @return {Promise<() => void>} Promise that resolves when the connection is established. */ export function connectIndexDb( objectId, objectType, doc ) { - const docName = `${ objectType }-${ objectId }`; - const provider = new IndexeddbPersistence( docName, doc ); + const roomName = `${ objectType }-${ objectId }`; + const provider = new IndexeddbPersistence( roomName, doc ); return new Promise( ( resolve ) => { provider.on( 'synced', () => { diff --git a/packages/sync/src/connect-webrtc.js b/packages/sync/src/connect-webrtc.js index 867bba39d6892..fefe3fddbb8a5 100644 --- a/packages/sync/src/connect-webrtc.js +++ b/packages/sync/src/connect-webrtc.js @@ -18,8 +18,8 @@ import { WebrtcProvider } from 'y-webrtc'; * @return {Promise<() => void>} Promise that resolves when the connection is established. */ export function connectWebRTC( objectId, objectType, doc ) { - const docName = `${ objectType }-${ objectId }`; - new WebrtcProvider( docName, doc, { + const roomName = `${ objectType }-${ objectId }`; + new WebrtcProvider( roomName, doc, { // @ts-ignore password: window.__experimentalCollaborativeEditingSecret, } ); From bdfb93e6db4334f0022acc512fc2c52bfe6d27ff Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 11 Oct 2023 18:02:46 +0300 Subject: [PATCH 23/32] Add changelog entry for #54415 (#55201) * Add changelog entry for #54415 * Move changelog to components --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b3c01c4db2c70..addb5a4d9ec32 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- Allow using CSS level 4 viewport-relative units ([54415](https://github.com/WordPress/gutenberg/pull/54415)) - `ToolsPanel`: do not apply the `className` to prop to `ToolsPanelItem` components when rendered as placeholders ([#55207](https://github.com/WordPress/gutenberg/pull/55207)). - `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). From c04dadbeb7c6d5f6a6d34536cac0c7cf39b403fe Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 16:33:51 +0100 Subject: [PATCH 24/32] Chore: Fix: Remove third parameter passed to shouldDismissPastedFiles which only receives 2. (#55262) --- packages/block-editor/src/utils/pasting.js | 5 +-- .../block-editor/src/utils/test/pasting.js | 31 +++++++------------ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/utils/pasting.js b/packages/block-editor/src/utils/pasting.js index f9612aad20f14..3ce7c20083269 100644 --- a/packages/block-editor/src/utils/pasting.js +++ b/packages/block-editor/src/utils/pasting.js @@ -77,10 +77,7 @@ export function getPasteEventData( { clipboardData } ) { const files = getFilesFromDataTransfer( clipboardData ); - if ( - files.length && - ! shouldDismissPastedFiles( files, html, plainText ) - ) { + if ( files.length && ! shouldDismissPastedFiles( files, html ) ) { return { files }; } diff --git a/packages/block-editor/src/utils/test/pasting.js b/packages/block-editor/src/utils/test/pasting.js index 7cebac9be6692..2c9dc8654a895 100644 --- a/packages/block-editor/src/utils/test/pasting.js +++ b/packages/block-editor/src/utils/test/pasting.js @@ -11,20 +11,19 @@ const mocks = { describe( 'shouldDismissPastedFiles', () => { it( 'should return false when no HTML is present', () => { - expect( - shouldDismissPastedFiles( [ mocks.pngImageFile ], '', '' ) - ).toBe( false ); + expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], '' ) ).toBe( + false + ); } ); it( 'should return false when file is not an image', () => { - expect( - shouldDismissPastedFiles( [ mocks.documentFile ], '', '' ) - ).toBe( false ); + expect( shouldDismissPastedFiles( [ mocks.documentFile ], '' ) ).toBe( + false + ); } ); it( 'should return false when multiple images are present', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile, mocks.jpgImageFile ], - '', '' ) ).toBe( false ); @@ -33,8 +32,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( false ); } ); @@ -42,8 +40,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( true ); } ); @@ -56,8 +53,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - 'https://lh3.googleusercontent.com/ab/SOMESTRING?authuser=0' + '' ) ).toBe( false ); } ); @@ -66,8 +62,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( false ); } ); @@ -76,8 +71,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - 'Some table text', - 'Some table text' + 'Some table text' ) ).toBe( true ); } ); @@ -86,8 +80,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - 'AB', - 'A\nB' + 'AB' ) ).toBe( true ); } ); From c42302313185c983a4550a7723e3d90f05bc7a30 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:53:48 +0300 Subject: [PATCH 25/32] Writing flow: fix selecting synced pattern (#55221) --- .../components/writing-flow/use-arrow-nav.js | 4 ++++ .../specs/editor/various/writing-flow.spec.js | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js index 02bff32eaefa3..44051b324ff64 100644 --- a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js @@ -114,6 +114,10 @@ export function getClosestTabbable( } function isTabCandidate( node ) { + if ( node.closest( '[inert]' ) ) { + return; + } + // Skip if there's only one child that is content editable (and thus a // better candidate). if ( diff --git a/test/e2e/specs/editor/various/writing-flow.spec.js b/test/e2e/specs/editor/various/writing-flow.spec.js index 98bb00a596f03..a772bd91276c2 100644 --- a/test/e2e/specs/editor/various/writing-flow.spec.js +++ b/test/e2e/specs/editor/various/writing-flow.spec.js @@ -1116,6 +1116,29 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { ) ).toHaveText( /^.a+$/ ); } ); + + test( 'should select synced pattern', async ( { page, editor } ) => { + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'synced' ); + + await editor.clickBlockOptionsMenuItem( 'Create pattern' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.type( 'test' ); + await page.keyboard.press( 'Enter' ); + + await expect( + editor.canvas.locator( '[data-type="core/block"]' ) + ).toBeFocused(); + + await editor.insertBlock( { name: 'core/paragraph' } ); + + await page.keyboard.press( 'ArrowUp' ); + + await expect( + editor.canvas.locator( '[data-type="core/block"]' ) + ).toBeFocused(); + } ); } ); class WritingFlowUtils { From 9087e3dc8381fcb83e666d54595fc3a3e2ac1f85 Mon Sep 17 00:00:00 2001 From: Artemio Morales Date: Wed, 11 Oct 2023 13:36:10 -0500 Subject: [PATCH 26/32] Image: Stop crashing with Lightbox on image blocks without an image (#55269) * Stop crashing with Lightbox on image blocks without an image * Fix PHPCS error --- packages/block-library/src/image/index.php | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 4213350ab05c8..87e17a4c136b4 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -16,11 +16,13 @@ * @return string The block content with the data-id attribute added. */ function render_block_core_image( $attributes, $content, $block ) { + if ( false === stripos( $content, 'next_tag( 'img' ); - if ( $processor->get_attribute( 'src' ) === null ) { + if ( ! $processor->next_tag( 'img' ) || null === $processor->get_attribute( 'src' ) ) { return ''; } @@ -125,11 +127,28 @@ function block_core_image_get_lightbox_settings( $block ) { * @return string Filtered block content. */ function block_core_image_render_lightbox( $block_content, $block ) { + /* + * If it's not possible that an IMG element exists then return the given + * block content as-is. It may be that there's no actual image in the block + * or it could be that another plugin already modified this HTML. + */ + if ( false === stripos( $block_content, 'next_tag( 'img' ); + /* + * If there's definitely no IMG element in the block then return the given + * block content as-is. There's nothing that this code can knowingly modify + * to add the lightbox behavior. + */ + if ( ! $processor->next_tag( 'img' ) ) { + return $block_content; + } + $alt_attribute = $processor->get_attribute( 'alt' ); // An empty alt attribute `alt=""` is valid for decorative images. From a3bde627aa4219c0b6a4ae67644bd9f79079115c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 11 Oct 2023 18:55:41 +0000 Subject: [PATCH 27/32] Bump plugin version to 16.8.0 --- 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 1bfcb11db361b..f2ae747fd9e20 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: 16.8.0-rc.2 + * Version: 16.8.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index c457a01b4b74b..557adb678c325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index cf6ce78f22e7f..9f014a3cfbae0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 5cf349583aa62424fedf213f1e3b5c3e12a90960 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 11 Oct 2023 19:15:21 +0000 Subject: [PATCH 28/32] Update Changelog for 16.8.0 --- changelog.txt | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) diff --git a/changelog.txt b/changelog.txt index 1b7d1150efdaf..801ea6d95cd5e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ == Changelog == += 16.8.0 = + = 16.8.0-rc.2 = ## Changelog @@ -21,6 +23,294 @@ The following contributors merged PRs in this release: @fullofcaffeine @torounit += 16.8.0-rc.1 = + +## Changelog + +### Features + +#### Block Editor +- Adds 'nofollow' setting to Button block. ([54110](https://github.com/WordPress/gutenberg/pull/54110)) + +#### Site Editor +- Add 'Show template' toggle when editing pages. ([52674](https://github.com/WordPress/gutenberg/pull/52674)) + + +### Enhancements + +- Update pattern import menu item. ([54782](https://github.com/WordPress/gutenberg/pull/54782)) + +#### Components +- Adding label/description to `BlockEditor/DuotoneControl`. ([54473](https://github.com/WordPress/gutenberg/pull/54473)) +- Deprecating `isPressed` in `Button` component. ([54740](https://github.com/WordPress/gutenberg/pull/54740)) +- Follow ariakit best practices. ([54696](https://github.com/WordPress/gutenberg/pull/54696)) +- InputControl-based components: Add opt-in prop for next 40px default size. ([53819](https://github.com/WordPress/gutenberg/pull/53819)) +- Modal: Add `contentWidth` prop to support a selection of preset modal sizes. ([54471](https://github.com/WordPress/gutenberg/pull/54471)) +- Remove unused components from `ui/`. ([54573](https://github.com/WordPress/gutenberg/pull/54573)) +- Update ariakit to 0.3.3. ([54818](https://github.com/WordPress/gutenberg/pull/54818)) +- Update compact search control metrics. ([54663](https://github.com/WordPress/gutenberg/pull/54663)) +- Wrapped `TextareaControl` in a `forwardRef` call. ([54975](https://github.com/WordPress/gutenberg/pull/54975)) + +#### Block Library +- Add a brief description to the Footnotes block. ([54613](https://github.com/WordPress/gutenberg/pull/54613)) +- Footnotes: Use core’s meta revisioning if available. ([52988](https://github.com/WordPress/gutenberg/pull/52988)) +- Login/out: Add spacing support. ([45147](https://github.com/WordPress/gutenberg/pull/45147)) +- Query view.js: Code quality. ([54982](https://github.com/WordPress/gutenberg/pull/54982)) +- Set custom color when applying initial background image. ([54054](https://github.com/WordPress/gutenberg/pull/54054)) +- Use `wp_get_inline_script_tag()` in `build_dropdown_script_block_core_categories()`. ([54637](https://github.com/WordPress/gutenberg/pull/54637)) + +#### Block Editor +- Default suggested links to pages. ([54622](https://github.com/WordPress/gutenberg/pull/54622)) +- Remove base URL from link control search results. ([54553](https://github.com/WordPress/gutenberg/pull/54553)) +- Simplify `BlockHTMLConvertButton`. ([54972](https://github.com/WordPress/gutenberg/pull/54972)) +- Update strings in blocks 'RenameModal' component. ([54887](https://github.com/WordPress/gutenberg/pull/54887)) + +#### Post Editor +- Edit Post: Use hooks instead of HoCs in 'PostStatus' components. ([54951](https://github.com/WordPress/gutenberg/pull/54951)) +- Editor: Use hooks instead of HoCs in 'PostSticky' components. ([54949](https://github.com/WordPress/gutenberg/pull/54949)) +- Editor: Use hooks instead of HoCs in 'PostSwitchToDraftButton'. ([54695](https://github.com/WordPress/gutenberg/pull/54695)) +- Show confirmation dialog when moving a post to the trash. ([50219](https://github.com/WordPress/gutenberg/pull/50219)) + +#### Site Editor +- Add template replace flow to template inspector. ([54609](https://github.com/WordPress/gutenberg/pull/54609)) +- [Site Editor]: Update copy of using the default template in a page. ([54728](https://github.com/WordPress/gutenberg/pull/54728)) + +#### Patterns +- Remove category description in inserter panel. ([54894](https://github.com/WordPress/gutenberg/pull/54894)) + +#### Typography +- Font Library: Refactor endpoint permissions. ([54829](https://github.com/WordPress/gutenberg/pull/54829)) + + +### Bug Fixes + +- Fix the ShortcutProvider usage. ([54851](https://github.com/WordPress/gutenberg/pull/54851)) +- Fix warning when a template calls a template area twice. ([54861](https://github.com/WordPress/gutenberg/pull/54861)) +- Revert "Fix warning when a template calls a template area twice". ([54926](https://github.com/WordPress/gutenberg/pull/54926)) + +#### Block Library +- All Nav block items to break long titles. ([54866](https://github.com/WordPress/gutenberg/pull/54866)) +- Fallback to Twitter provider when embedding X URLs. ([54876](https://github.com/WordPress/gutenberg/pull/54876)) +- Fix Deleted Navigation Menu warning string. ([55033](https://github.com/WordPress/gutenberg/pull/55033)) +- Fix Search Block not updating in Nav block. ([54823](https://github.com/WordPress/gutenberg/pull/54823)) +- Fix left and right aligmnent in children of Post Template. ([54997](https://github.com/WordPress/gutenberg/pull/54997)) +- Fix output of Navigation block classnames in the editor. ([54992](https://github.com/WordPress/gutenberg/pull/54992)) +- Fix overwriting of published post meta when previewing footnote changes. ([54339](https://github.com/WordPress/gutenberg/pull/54339)) +- Image: Ensure Expand on Click toggle is shown if block-level lightbox setting exists. ([54878](https://github.com/WordPress/gutenberg/pull/54878)) +- Image: Fix layout shift when lightbox is opened and closed. ([53026](https://github.com/WordPress/gutenberg/pull/53026)) +- Media & Text: Fix React warning. ([55038](https://github.com/WordPress/gutenberg/pull/55038)) +- Search block: Allow space for input field only when form expanded. ([54846](https://github.com/WordPress/gutenberg/pull/54846)) +- Search block: Update alignment and icon button width. ([54773](https://github.com/WordPress/gutenberg/pull/54773)) + +#### Site Editor +- Avoid same key warnings in template parts area listings. ([54863](https://github.com/WordPress/gutenberg/pull/54863)) +- Avoid stale navigation block values when parsing entity record. ([54996](https://github.com/WordPress/gutenberg/pull/54996)) +- Don't display the navigation section in template parts details when a menu is missing. ([54993](https://github.com/WordPress/gutenberg/pull/54993)) +- Fix ToolSelector popover variant. ([54840](https://github.com/WordPress/gutenberg/pull/54840)) +- Reset 'Show template' toggle when leaving edit mode. ([54679](https://github.com/WordPress/gutenberg/pull/54679)) +- remove `overflow: Hidden` from the entity title in the site editor sidebar. ([54769](https://github.com/WordPress/gutenberg/pull/54769)) + +#### Components +- FormTokenField: Add `box-sizing` reset style and reset default padding. ([54734](https://github.com/WordPress/gutenberg/pull/54734)) +- Popover: Fix the styles for components that use emotion within popovers. ([54912](https://github.com/WordPress/gutenberg/pull/54912)) +- Remove hover style for secondary Button when aria-disabled is set. ([54978](https://github.com/WordPress/gutenberg/pull/54978)) +- Reverting addition of `aria-selected` style hook in `Button`. ([54931](https://github.com/WordPress/gutenberg/pull/54931)) +- `SlotFill`: Pass `Component` instance to unregisterSlot. ([54765](https://github.com/WordPress/gutenberg/pull/54765)) + +#### Block Editor +- Avoid double-wrapping selectors when transforming the styles. ([54981](https://github.com/WordPress/gutenberg/pull/54981)) +- [Inserter]: Fix reset of registered media categories. ([55012](https://github.com/WordPress/gutenberg/pull/55012)) + +#### Typography +- Font Library: Changed the OTF mime type expected value to be what PHP returns. ([54886](https://github.com/WordPress/gutenberg/pull/54886)) +- Font Library: Move font uploads to a new tab. ([54655](https://github.com/WordPress/gutenberg/pull/54655)) + +#### Global Styles +- Block custom CSS: Fix incorrect CSS when multiple root selectors. ([53602](https://github.com/WordPress/gutenberg/pull/53602)) +- Image: Ensure `false` values are preserved in memory when defined in `theme.json`. ([54639](https://github.com/WordPress/gutenberg/pull/54639)) + +#### List View +- Fix performance issue when selecting all blocks. ([54900](https://github.com/WordPress/gutenberg/pull/54900)) + +#### Colors +- Format Library: Try to fix highlight popover jumping. ([54736](https://github.com/WordPress/gutenberg/pull/54736)) + +#### Interactivity API +- Image: Fix duotone not being applied to lightbox image. ([54670](https://github.com/WordPress/gutenberg/pull/54670)) + + +### Accessibility + +#### Block Library +- Footnotes: Add aria-label to return links. ([54843](https://github.com/WordPress/gutenberg/pull/54843)) +- Table of contents block accessibility improvements. ([54322](https://github.com/WordPress/gutenberg/pull/54322)) + +#### Components +- HTML block: Fix accessibility issues on back-end. ([54408](https://github.com/WordPress/gutenberg/pull/54408)) +- `Modal`: Accessibly hide/show outer modal when nested. ([54743](https://github.com/WordPress/gutenberg/pull/54743)) + +#### Patterns +- Use list role instead of listbox in patterns list. ([54884](https://github.com/WordPress/gutenberg/pull/54884)) + +#### Post Editor +- Editor: Always render the 'Switch to Draft' button to avoid focus loss. ([54722](https://github.com/WordPress/gutenberg/pull/54722)) + +#### Block Editor +- Block Switcher: Use a different label for multi-selection. ([54692](https://github.com/WordPress/gutenberg/pull/54692)) + + +### Performance + +- Tests: Support the Site Editor's legacy spinner. ([54784](https://github.com/WordPress/gutenberg/pull/54784)) +- Use instanceOf over property_exists. ([54835](https://github.com/WordPress/gutenberg/pull/54835)) + +#### Block Editor +- Subscribe only to block editor store in `useBlockSync`. ([55041](https://github.com/WordPress/gutenberg/pull/55041)) + + +### Experiments + +#### Site Editor +- al]: First version of pages list in site editor. ([54966](https://github.com/WordPress/gutenberg/pull/54966)) + +#### Block Editor +- Expose `getDuotoneFilter()` as private API. ([54905](https://github.com/WordPress/gutenberg/pull/54905)) + + +### Documentation + +- Add a documentation page about the block editor settings. ([54870](https://github.com/WordPress/gutenberg/pull/54870)) +- Add a page about the format library to the platform documentation site. ([55037](https://github.com/WordPress/gutenberg/pull/55037)) +- Docs: Add a callout to the `wp-now` documentation to mention it's still experimental. ([55044](https://github.com/WordPress/gutenberg/pull/55044)) +- Docs: Remove outdated info. ([54707](https://github.com/WordPress/gutenberg/pull/54707)) +- Docs: Remove the Full Site Editing doc. ([54516](https://github.com/WordPress/gutenberg/pull/54516)) +- Docs: Rename Block Hooks handbook page to Block Filters. ([54862](https://github.com/WordPress/gutenberg/pull/54862)) +- Document the current state of the Real-Time collaboration experiment. ([54932](https://github.com/WordPress/gutenberg/pull/54932)) +- Fix a broken MD link in callout. ([54772](https://github.com/WordPress/gutenberg/pull/54772)) +- Platform Docs: Add a documentation page explaining how to use the block library. ([54967](https://github.com/WordPress/gutenberg/pull/54967)) +- Update the documentation of the block editor and replace @wordpress/element with react. ([54908](https://github.com/WordPress/gutenberg/pull/54908)) +- Update versions in WP for 6.4. ([54890](https://github.com/WordPress/gutenberg/pull/54890)) + + +### Code Quality + +- Add a unit test for the "ValidBlockLibraryFunctionNameSniff" sniff. ([53928](https://github.com/WordPress/gutenberg/pull/53928)) +- Move dependencies to the right place. ([54597](https://github.com/WordPress/gutenberg/pull/54597)) +- Move mime-type collection generation to a function that can be tested…. ([54844](https://github.com/WordPress/gutenberg/pull/54844)) +- Post Title block should use esc_url(). ([53981](https://github.com/WordPress/gutenberg/pull/53981)) +- Rich text: Use getPasteEventData. ([55048](https://github.com/WordPress/gutenberg/pull/55048)) +- Writing flow: Absorb clipboard handler. ([55006](https://github.com/WordPress/gutenberg/pull/55006)) + +#### Block Library +- Footnotes: Avoid regexes in entity provider. ([54505](https://github.com/WordPress/gutenberg/pull/54505)) +- Image Block: Fix browser console error when clicking "Expand on Click". ([54938](https://github.com/WordPress/gutenberg/pull/54938)) +- Removed unwanted space from the string. ([54654](https://github.com/WordPress/gutenberg/pull/54654)) +- Update CODEOWNERS for `core/image` block. ([54793](https://github.com/WordPress/gutenberg/pull/54793)) + +#### Patterns +- Add a new spec for for adding an unsynced pattern. ([54892](https://github.com/WordPress/gutenberg/pull/54892)) +- Add end-to-end tests for filtering and searching patterns. ([54906](https://github.com/WordPress/gutenberg/pull/54906)) +- Add new end-to-end test for creating a pattern. ([54855](https://github.com/WordPress/gutenberg/pull/54855)) +- Include pattern category in main end-to-end critical path test. ([54923](https://github.com/WordPress/gutenberg/pull/54923)) + +#### Components +- Consolidate utils to remove `ui/`. ([54922](https://github.com/WordPress/gutenberg/pull/54922)) +- Move `ContextSystemProvider` out of `/ui`. ([54847](https://github.com/WordPress/gutenberg/pull/54847)) +- SlotFill: Migrate to Typescript. ([51350](https://github.com/WordPress/gutenberg/pull/51350)) +- Tidying `CircularOptionPicker.Option`. ([54903](https://github.com/WordPress/gutenberg/pull/54903)) + +#### Typography +- Font Library: Syntax refactor repace strpos with str_contains. ([54832](https://github.com/WordPress/gutenberg/pull/54832)) +- Font Library: Use snake_case instead of camelCase on fontFamilies endpoint param. ([54977](https://github.com/WordPress/gutenberg/pull/54977)) + +#### Block Editor +- Rich text: Avoid shortcode logic, adjust paste handler instead. ([55052](https://github.com/WordPress/gutenberg/pull/55052)) + +#### Plugin +- Remove legacy logic for '__unstableResolvedAssets' setting. ([54812](https://github.com/WordPress/gutenberg/pull/54812)) + +#### Data Layer +- createResolversCacheMiddleware: Remove dependency on core/data store. ([54733](https://github.com/WordPress/gutenberg/pull/54733)) + +#### Site Editor +- Use constants rather than hard coded template strings (round 3). ([54705](https://github.com/WordPress/gutenberg/pull/54705)) + + +### Tools + +- Label enforcer workflow: Make accessibility a focus instead of a type. ([54941](https://github.com/WordPress/gutenberg/pull/54941)) +- Scripts: Update webpack and related dependencies to the latest version. ([54657](https://github.com/WordPress/gutenberg/pull/54657)) +- Update changelog automation and test fixtures to match the last a11y label renaming. ([54974](https://github.com/WordPress/gutenberg/pull/54974)) + +#### Testing +- Don’t use TypeScript files in scripts package. ([54856](https://github.com/WordPress/gutenberg/pull/54856)) +- ESLint: Update eslint-plugin-testing-library to v6. ([54910](https://github.com/WordPress/gutenberg/pull/54910)) +- Fix end-to-end test: ”WP Editor Meta Boxes > Should save the changes”. ([51884](https://github.com/WordPress/gutenberg/pull/51884)) +- Font Library: Avoid deprected error in test. ([54802](https://github.com/WordPress/gutenberg/pull/54802)) +- Make `editor.getBlocks` to return only testing-related properties. ([54901](https://github.com/WordPress/gutenberg/pull/54901)) +- Migrate 'Global styles sidebar' test to Playwright. ([55045](https://github.com/WordPress/gutenberg/pull/55045)) +- Migrate 'iframed block editor settings styles' tests to Playwright. ([55014](https://github.com/WordPress/gutenberg/pull/55014)) +- Migrate 'iframed inline styles' tests to Playwright. ([55009](https://github.com/WordPress/gutenberg/pull/55009)) +- Migrate 'iframed masonry block' tests to Playwright. ([55016](https://github.com/WordPress/gutenberg/pull/55016)) +- Migrate 'iframed multiple block stylesheets' tests to Playwright. ([55003](https://github.com/WordPress/gutenberg/pull/55003)) +- Migrate keyboard-navigable-blocks end-to-end tests from puppeteer to playwright. ([54944](https://github.com/WordPress/gutenberg/pull/54944)) +- Scripts: Properly use CommonJS for default Playwright configuration. ([54988](https://github.com/WordPress/gutenberg/pull/54988)) +- Try fixing the flaky 'Toolbar roving tabindex' end-to-end test. ([54785](https://github.com/WordPress/gutenberg/pull/54785)) +- end-to-end Tests: Revert temporary fixes. ([54865](https://github.com/WordPress/gutenberg/pull/54865)) +- end-to-end Utils: Allow overriding username/password. ([53267](https://github.com/WordPress/gutenberg/pull/53267)) + +#### Build Tooling +- Add some @types packages as proper dependencies. ([50231](https://github.com/WordPress/gutenberg/pull/50231)) +- Update the default JSX pragma to React instead of @wordpress/element. ([54494](https://github.com/WordPress/gutenberg/pull/54494)) +- Upgrade wp-prettier to v3.0.3 (final). ([54775](https://github.com/WordPress/gutenberg/pull/54775)) + + +### Security + +#### Data Layer +- Replace turbo-combine-reducers with combineReducers from Redux. ([54606](https://github.com/WordPress/gutenberg/pull/54606)) + + +### Various + +- (chore) Revert the 16.7 RC2 release in order to release it again due to wrong changelog. ([54744](https://github.com/WordPress/gutenberg/pull/54744)) + +#### Design Tools +- Background image block support: Add tests, adjust injection logic slightly. ([54489](https://github.com/WordPress/gutenberg/pull/54489)) +- Background support: Backport fix for undefined array key. ([54850](https://github.com/WordPress/gutenberg/pull/54850)) + +#### Typography +- Revert "Font Library: Avoid rendering font library ui outisde gutenberg plugin". ([54947](https://github.com/WordPress/gutenberg/pull/54947)) + +#### Commands +- Make the reset styles command consistent. ([54841](https://github.com/WordPress/gutenberg/pull/54841)) + +#### Patterns +- Use "Not synced" in place of "Standard" nomenclature for patterns. ([54839](https://github.com/WordPress/gutenberg/pull/54839)) + +#### Block Editor +- Simplify BlockPatternsSyncFilter with clearer labels and additional context. ([54838](https://github.com/WordPress/gutenberg/pull/54838)) + +#### Site Editor +- Use consistent capitalization for template parts in Site Editor constants. ([54709](https://github.com/WordPress/gutenberg/pull/54709)) + + +## First time contributors + +The following PRs were merged by first time contributors: + +- @leemyongpakvn: Fix a broken MD link in callout. ([54772](https://github.com/WordPress/gutenberg/pull/54772)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @alexstine @andrewhayward @andrewserong @annezazu @anton-vlasenko @artemiomorales @aurooba @bangank36 @brookewp @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @dcalhoun @derekblank @draganescu @ellatrix @fluiddot @fullofcaffeine @geriux @getdave @glendaviesnz @gziolo @jameskoster @jeryj @jsnajdr @juhi123 @kevin940726 @leemyongpakvn @madhusudhand @MaggieCabrera @Mamaduka @matiasbenedetto @michalczaplinski @mirka @mtias @mujuonly @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ockham @pbking @priethor @ramonjd @richtabor @scruffian @SiobhyB @spacedmonkey @stokesman @swissspidy @t-hamano @tellthemachines @tellyworth @them-es @torounit @tyxla @westonruter @WunderBart @youknowriad + + + + = 16.7.1 = ## Changelog From 9f38ee31ca51887352c540d02b65cd5de69601c2 Mon Sep 17 00:00:00 2001 From: Brooke <35543432+brookewp@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:01:20 -0700 Subject: [PATCH 29/32] url: update `filterURLForDisplay` to include all image, video, and audio file types (#54920) * url: update display filter to include all file types * Restore regex with defined media files with extended list * Add tooltip to LinkPreview and remove from MediaReplaceFlow * Restore regex to display all file urls * Add test to LinkPreview to check for tooltip * Add test for filter to verify newly included formats * Update link control test based on feedback * Combine new test with existing filename test * Update const naming and add comment * Clean up test by replacing with it.each * Simplify regex to a string Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --------- Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --- .../components/link-control/link-preview.js | 16 +++++++--- .../src/components/link-control/test/index.js | 19 ++++++++++++ .../components/media-replace-flow/index.js | 23 ++++++-------- packages/url/src/filter-url-for-display.js | 5 +-- packages/url/src/test/index.js | 31 +++++++++---------- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/components/link-control/link-preview.js b/packages/block-editor/src/components/link-control/link-preview.js index 8272602cde908..04a67d4478994 100644 --- a/packages/block-editor/src/components/link-control/link-preview.js +++ b/packages/block-editor/src/components/link-control/link-preview.js @@ -11,6 +11,7 @@ import { Button, ExternalLink, __experimentalText as Text, + Tooltip, } from '@wordpress/components'; import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url'; import { Icon, globe, info, linkOff, edit } from '@wordpress/icons'; @@ -87,12 +88,17 @@ export default function LinkPreview( { { ! isEmptyURL ? ( <> - - { displayTitle } - + + { displayTitle } + + { value?.url && displayTitle !== displayURL && ( diff --git a/packages/block-editor/src/components/link-control/test/index.js b/packages/block-editor/src/components/link-control/test/index.js index 5c44f0295249c..e0366a3f27ef5 100644 --- a/packages/block-editor/src/components/link-control/test/index.js +++ b/packages/block-editor/src/components/link-control/test/index.js @@ -2056,6 +2056,25 @@ describe( 'Addition Settings UI', () => { } ) ); } ); + + it( 'should show tooltip with full URL alongside filtered display', async () => { + const user = userEvent.setup(); + const url = + 'http://www.wordpress.org/wp-content/uploads/a-document.pdf'; + render( ); + + const link = screen.getByRole( 'link' ); + + expect( link ).toHaveTextContent( 'a-document.pdf' ); + + await user.hover( link ); + + expect( await screen.findByRole( 'tooltip' ) ).toHaveTextContent( url ); + + await user.unhover( link ); + + expect( screen.queryByRole( 'tooltip' ) ).not.toBeInTheDocument(); + } ); } ); describe( 'Post types', () => { diff --git a/packages/block-editor/src/components/media-replace-flow/index.js b/packages/block-editor/src/components/media-replace-flow/index.js index c331761af5852..33419676eaab8 100644 --- a/packages/block-editor/src/components/media-replace-flow/index.js +++ b/packages/block-editor/src/components/media-replace-flow/index.js @@ -16,7 +16,6 @@ import { ToolbarButton, Dropdown, withFilters, - Tooltip, } from '@wordpress/components'; import { useSelect, withDispatch } from '@wordpress/data'; import { DOWN } from '@wordpress/keycodes'; @@ -220,19 +219,15 @@ const MediaReplaceFlow = ( { { __( 'Current media URL:' ) } - - - { - onSelectURL( url ); - editMediaButtonRef.current.focus(); - } } - /> - - + { + onSelectURL( url ); + editMediaButtonRef.current.focus(); + } } + /> ) } > diff --git a/packages/url/src/filter-url-for-display.js b/packages/url/src/filter-url-for-display.js index 2d3247e6d1da9..eede264e8e801 100644 --- a/packages/url/src/filter-url-for-display.js +++ b/packages/url/src/filter-url-for-display.js @@ -21,12 +21,13 @@ export function filterURLForDisplay( url, maxLength = null ) { filteredURL = filteredURL.replace( '/', '' ); } - const mediaRegexp = /([\w|:])*\.(?:jpg|jpeg|gif|png|svg)/; + // capture file name from URL + const fileRegexp = /\/([^\/?]+)\.(?:[\w]+)(?=\?|$)/; if ( ! maxLength || filteredURL.length <= maxLength || - ! filteredURL.match( mediaRegexp ) + ! filteredURL.match( fileRegexp ) ) { return filteredURL; } diff --git a/packages/url/src/test/index.js b/packages/url/src/test/index.js index 9aa53dca512df..e258e112b2987 100644 --- a/packages/url/src/test/index.js +++ b/packages/url/src/test/index.js @@ -254,23 +254,20 @@ describe( 'isValidPath', () => { } ); describe( 'getFilename', () => { - it( 'returns the filename part of the URL', () => { - expect( getFilename( 'https://wordpress.org/image.jpg' ) ).toBe( - 'image.jpg' - ); - expect( - getFilename( 'https://wordpress.org/image.jpg?query=test' ) - ).toBe( 'image.jpg' ); - expect( getFilename( 'https://wordpress.org/image.jpg#anchor' ) ).toBe( - 'image.jpg' - ); - expect( - getFilename( 'http://localhost:8080/a/path/to/an/image.jpg' ) - ).toBe( 'image.jpg' ); - expect( getFilename( '/path/to/an/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( 'path/to/an/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( '/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( 'image.jpg' ) ).toBe( 'image.jpg' ); + it.each( [ + [ 'https://wordpress.org/image.jpg', 'image.jpg' ], + [ 'https://wordpress.org/image.jpg?query=test', 'image.jpg' ], + [ 'https://wordpress.org/image.jpg#anchor', 'image.jpg' ], + [ 'http://localhost:8080/a/path/to/an/image.jpg', 'image.jpg' ], + [ '/path/to/an/image.jpg', 'image.jpg' ], + [ 'path/to/an/image.jpg', 'image.jpg' ], + [ '/image.jpg', 'image.jpg' ], + [ 'https://wordpress.org/file.pdf', 'file.pdf' ], + [ 'https://wordpress.org/image.webp?query=test', 'image.webp' ], + [ 'https://wordpress.org/video.mov#anchor', 'video.mov' ], + [ 'http://localhost:8080/a/path/to/audio.mp3', 'audio.mp3' ], + ] )( 'returns the filename part of the URL: %s', ( url, filename ) => { + expect( getFilename( url ) ).toBe( filename ); } ); it( 'returns undefined when the provided value does not contain a filename', () => { From c39b35245eb3fe187eb0aed5672d3e4d91906a9a Mon Sep 17 00:00:00 2001 From: Rich Tabor Date: Wed, 11 Oct 2023 17:23:46 -0400 Subject: [PATCH 30/32] Update fullscreen icon (#55021) --- packages/icons/src/library/fullscreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/icons/src/library/fullscreen.js b/packages/icons/src/library/fullscreen.js index 8b11ddcac7217..11bef7aebd612 100644 --- a/packages/icons/src/library/fullscreen.js +++ b/packages/icons/src/library/fullscreen.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const fullscreen = ( - + ); From d84da61d9b35da1329ac70d9ac7d158862813160 Mon Sep 17 00:00:00 2001 From: Brooke <35543432+brookewp@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:01:22 -0700 Subject: [PATCH 31/32] Toolbar: Add unstyled variant (#55139) * Toolbar: Add unstyled variant * Add variants to block editor and remove workarounds * Update stories * Add test for new variant * Update changelog * Memoize toolbar context * Clean up and improve CSS * Add to README and update phrasing * Implement feedback to simplify and optimize * Rename and simplify story by reusing default args --- .../block-tools/block-contextual-toolbar.js | 1 + .../src/components/block-tools/style.scss | 1 - .../src/components/tool-selector/index.js | 2 +- packages/components/CHANGELOG.md | 4 +++ .../src/toolbar/stories/index.story.tsx | 15 +++++++++ .../components/src/toolbar/test/index.tsx | 8 +++++ .../components/src/toolbar/toolbar/README.md | 9 +++++ .../components/src/toolbar/toolbar/index.tsx | 33 ++++++++++++------- .../components/src/toolbar/toolbar/style.scss | 9 +++++ .../components/src/toolbar/toolbar/types.ts | 10 ++++++ .../components/header/header-toolbar/index.js | 1 + .../header/header-toolbar/style.scss | 1 - 12 files changed, 79 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js index 439c3d33a3036..fcec9d56b24a8 100644 --- a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js @@ -188,6 +188,7 @@ function BlockContextualToolbar( { focusOnMount, isFixed, ...props } ) { className={ classes } /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } + variant={ isFixed ? 'unstyled' : undefined } { ...props } > { ! isCollapsed && } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 796c513d6d7c2..2cb2edaf1a9c7 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -109,7 +109,6 @@ overflow-y: hidden; } - border: none; border-bottom: $border-width solid $gray-200; border-radius: 0; diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index a0df14f1a19d9..1e93a18cf6bb9 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -51,7 +51,7 @@ function ToolSelector( props, ref ) { label={ __( 'Tools' ) } /> ) } - popoverProps={ { placement: 'bottom-start', variant: undefined } } + popoverProps={ { placement: 'bottom-start' } } renderContent={ () => ( <> diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index addb5a4d9ec32..d1d87acebaa37 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,10 @@ - `ConfirmDialog`: Migrate to TypeScript. ([#54954](https://github.com/WordPress/gutenberg/pull/54954)). +### New Features + +- `Toolbar`: add new `variant` prop for 'unstyled' option ([#55139](https://github.com/WordPress/gutenberg/pull/55139)). + ## 25.9.0 (2023-10-05) ### Enhancements diff --git a/packages/components/src/toolbar/stories/index.story.tsx b/packages/components/src/toolbar/stories/index.story.tsx index 2eecf54a4a493..e4fb3b07e1c90 100644 --- a/packages/components/src/toolbar/stories/index.story.tsx +++ b/packages/components/src/toolbar/stories/index.story.tsx @@ -52,6 +52,10 @@ const meta: Meta< typeof Toolbar > = { }, argTypes: { children: { control: { type: null } }, + variant: { + options: [ undefined, 'unstyled' ], + control: { type: 'radio' }, + }, }, parameters: { controls: { expanded: true }, @@ -181,3 +185,14 @@ WithoutGroup.args = { > ), }; + +/** + * Set the variant to `unstyled` to remove default border styles. + * Otherwise, leave it as `undefined` for default styles. + */ + +export const Unstyled = Template.bind( {} ); +Unstyled.args = { + ...Default.args, + variant: 'unstyled', +}; diff --git a/packages/components/src/toolbar/test/index.tsx b/packages/components/src/toolbar/test/index.tsx index c9e58edc8a80e..74c58804fc099 100644 --- a/packages/components/src/toolbar/test/index.tsx +++ b/packages/components/src/toolbar/test/index.tsx @@ -25,5 +25,13 @@ describe( 'Toolbar', () => { screen.getByLabelText( 'control2', { selector: 'button' } ) ).toBeInTheDocument(); } ); + + it( 'should apply the unstyled variant correctly via the `variant` prop', () => { + render( ); + + expect( screen.getByRole( 'toolbar' ) ).toHaveClass( + 'is-unstyled' + ); + } ); } ); } ); diff --git a/packages/components/src/toolbar/toolbar/README.md b/packages/components/src/toolbar/toolbar/README.md index 6692d3f63f34e..ee89127ded74f 100644 --- a/packages/components/src/toolbar/toolbar/README.md +++ b/packages/components/src/toolbar/toolbar/README.md @@ -71,6 +71,15 @@ An accessible label for the toolbar. - Required: Yes +#### `variant`: `'unstyled' | undefined` + +Specifies the toolbar's style. + +Leave undefined for the default style. Or `'unstyled'` which removes the border from the toolbar, but keeps the default popover style. + +- Required: No +- Default: `undefined` + ## Related components - Toolbar may contain [ToolbarGroup](/packages/components/src/toolbar-group/README.md), [ToolbarButton](/packages/components/src/toolbar-button/README.md) and [ToolbarItem](/packages/components/src/toolbar-Item/README.md) as children. diff --git a/packages/components/src/toolbar/toolbar/index.tsx b/packages/components/src/toolbar/toolbar/index.tsx index b6e83dcf6da2a..47c49b270afef 100644 --- a/packages/components/src/toolbar/toolbar/index.tsx +++ b/packages/components/src/toolbar/toolbar/index.tsx @@ -7,7 +7,7 @@ import type { ForwardedRef } from 'react'; /** * WordPress dependencies */ -import { forwardRef } from '@wordpress/element'; +import { forwardRef, useMemo } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; /** @@ -19,23 +19,30 @@ import type { ToolbarProps } from './types'; import type { WordPressComponentProps } from '../../context'; import { ContextSystemProvider } from '../../context'; -const CONTEXT_SYSTEM_VALUE = { - DropdownMenu: { - variant: 'toolbar', - }, - Dropdown: { - variant: 'toolbar', - }, -}; - function UnforwardedToolbar( { className, label, + variant, ...props }: WordPressComponentProps< ToolbarProps, 'div', false >, ref: ForwardedRef< any > ) { + const isVariantDefined = variant !== undefined; + const contextSystemValue = useMemo( () => { + if ( isVariantDefined ) { + return {}; + } + return { + DropdownMenu: { + variant: 'toolbar', + }, + Dropdown: { + variant: 'toolbar', + }, + }; + }, [ isVariantDefined ] ); + if ( ! label ) { deprecated( 'Using Toolbar without label prop', { since: '5.6', @@ -55,10 +62,12 @@ function UnforwardedToolbar( // `ToolbarGroup` already uses components-toolbar for compatibility reasons. const finalClassName = classnames( 'components-accessible-toolbar', - className + className, + variant && `is-${ variant }` ); + return ( - + .components-toolbar-group:last-child { border-right: none; } + + &.is-unstyled { + border: none; + + & > .components-toolbar-group { + border-right: none; + } + + } } .components-accessible-toolbar, diff --git a/packages/components/src/toolbar/toolbar/types.ts b/packages/components/src/toolbar/toolbar/types.ts index f6a6b9667ab4b..681f1ab2d1af2 100644 --- a/packages/components/src/toolbar/toolbar/types.ts +++ b/packages/components/src/toolbar/toolbar/types.ts @@ -12,4 +12,14 @@ export type ToolbarProps = { * An accessible label for the toolbar. */ label: string; + /** + * Specifies the toolbar's style. + * + * Leave undefined for the default style. Or `'unstyled'` which + * removes the border from the toolbar, but keeps the default + * popover style. + * + * @default undefined + */ + variant?: 'unstyled' | undefined; }; diff --git a/packages/edit-post/src/components/header/header-toolbar/index.js b/packages/edit-post/src/components/header/header-toolbar/index.js index e814f7a49072f..b86e66af7a849 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.js @@ -136,6 +136,7 @@ function HeaderToolbar( { setListViewToggleElement } ) { className="edit-post-header-toolbar" aria-label={ toolbarAriaLabel } shouldUseKeyboardFocusShortcut={ ! blockToolbarCanBeFocused } + variant="unstyled" > .components-button { From d2bf1366d55f8fad5edeebd521eda29b610d19bc Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:44:33 +1000 Subject: [PATCH 32/32] Patterns: Use modal for pattern duplication flow as workaround for changing sync status (#54764) --- .../create-template-part-modal/index.js | 14 +- .../page-patterns/duplicate-menu-item.js | 278 +++++++----------- .../components/page-patterns/use-patterns.js | 5 + .../src/components/create-pattern-modal.js | 22 +- 4 files changed, 130 insertions(+), 189 deletions(-) diff --git a/packages/edit-site/src/components/create-template-part-modal/index.js b/packages/edit-site/src/components/create-template-part-modal/index.js index 0b3a57e0c0744..31f12b6cab56d 100644 --- a/packages/edit-site/src/components/create-template-part-modal/index.js +++ b/packages/edit-site/src/components/create-template-part-modal/index.js @@ -39,17 +39,21 @@ import { } from '../../utils/template-part-create'; export default function CreateTemplatePartModal( { - closeModal, + defaultArea = TEMPLATE_PART_AREA_DEFAULT_CATEGORY, blocks = [], + confirmLabel = __( 'Create' ), + closeModal, + modalTitle = __( 'Create template part' ), onCreate, onError, + defaultTitle = '', } ) { const { createErrorNotice } = useDispatch( noticesStore ); const { saveEntityRecord } = useDispatch( coreStore ); const existingTemplateParts = useExistingTemplateParts(); - const [ title, setTitle ] = useState( '' ); - const [ area, setArea ] = useState( TEMPLATE_PART_AREA_DEFAULT_CATEGORY ); + const [ title, setTitle ] = useState( defaultTitle ); + const [ area, setArea ] = useState( defaultArea ); const [ isSubmitting, setIsSubmitting ] = useState( false ); const instanceId = useInstanceId( CreateTemplatePartModal ); @@ -104,7 +108,7 @@ export default function CreateTemplatePartModal( { return ( @@ -181,7 +185,7 @@ export default function CreateTemplatePartModal( { aria-disabled={ ! title || isSubmitting } isBusy={ isSubmitting } > - { __( 'Create' ) } + { confirmLabel } diff --git a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js index a882de95bdaeb..a0842cf9002a0 100644 --- a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js @@ -2,10 +2,11 @@ * WordPress dependencies */ import { MenuItem } from '@wordpress/components'; -import { store as coreStore } from '@wordpress/core-data'; import { useDispatch } from '@wordpress/data'; +import { useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -13,206 +14,131 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; */ import { TEMPLATE_PART_POST_TYPE, - PATTERN_TYPES, PATTERN_SYNC_TYPES, + PATTERN_TYPES, } from '../../utils/constants'; -import { - useExistingTemplateParts, - getUniqueTemplatePartTitle, - getCleanTemplatePartSlug, -} from '../../utils/template-part-create'; import { unlock } from '../../lock-unlock'; -import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories'; +import CreateTemplatePartModal from '../create-template-part-modal'; +const { CreatePatternModal } = unlock( patternsPrivateApis ); const { useHistory } = unlock( routerPrivateApis ); -function getPatternMeta( item ) { - if ( item.type === PATTERN_TYPES.theme ) { - return { wp_pattern_sync_status: PATTERN_SYNC_TYPES.unsynced }; - } - - const syncStatus = item.patternBlock.wp_pattern_sync_status; - const isUnsynced = syncStatus === PATTERN_SYNC_TYPES.unsynced; - - return { - ...item.patternBlock.meta, - wp_pattern_sync_status: isUnsynced ? syncStatus : undefined, - }; -} - export default function DuplicateMenuItem( { categoryId, item, label = __( 'Duplicate' ), onClose, } ) { - const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore ); - const { createErrorNotice, createSuccessNotice } = - useDispatch( noticesStore ); - + const { createSuccessNotice } = useDispatch( noticesStore ); + const [ isModalOpen, setIsModalOpen ] = useState( false ); const history = useHistory(); - const existingTemplateParts = useExistingTemplateParts(); - const { patternCategories } = usePatternCategories(); - async function createTemplatePart() { - try { - const copiedTitle = sprintf( - /* translators: %s: Existing template part title */ - __( '%s (Copy)' ), - item.title - ); - const title = getUniqueTemplatePartTitle( - copiedTitle, - existingTemplateParts - ); - const slug = getCleanTemplatePartSlug( title ); - const { area, content } = item.templatePart; - - const result = await saveEntityRecord( - 'postType', - TEMPLATE_PART_POST_TYPE, - { slug, title, content, area }, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: The new template part's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), - item.title - ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - - history.push( { - postType: TEMPLATE_PART_POST_TYPE, - postId: result?.id, - categoryType: TEMPLATE_PART_POST_TYPE, - categoryId, - } ); + const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - onClose(); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( - 'An error occurred while creating the template part.' - ); - - createErrorNotice( errorMessage, { + async function onTemplatePartSuccess( templatePart ) { + createSuccessNotice( + sprintf( + // translators: %s: The new template part's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + item.title + ), + { type: 'snackbar', - id: 'edit-site-patterns-error', - } ); - onClose(); - } - } - - async function findOrCreateTerm( term ) { - try { - const newTerm = await saveEntityRecord( - 'taxonomy', - 'wp_pattern_category', - { - name: term.label, - slug: term.name, - description: term.description, - }, - { - throwOnError: true, - } - ); - invalidateResolution( 'getUserPatternCategories' ); - return newTerm.id; - } catch ( error ) { - if ( error.code !== 'term_exists' ) { - throw error; + id: 'edit-site-patterns-success', } + ); - return error.data.term_id; - } + history.push( { + postType: TEMPLATE_PART_POST_TYPE, + postId: templatePart?.id, + categoryType: TEMPLATE_PART_POST_TYPE, + categoryId, + } ); + + onClose(); } - async function getCategories( categories ) { - const terms = categories.map( ( category ) => { - const fullCategory = patternCategories.find( - ( cat ) => cat.name === category - ); - if ( fullCategory.id ) { - return fullCategory.id; + function onPatternSuccess( { pattern } ) { + createSuccessNotice( + sprintf( + // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + pattern.title.raw + ), + { + type: 'snackbar', + id: 'edit-site-patterns-success', } - return findOrCreateTerm( fullCategory ); + ); + + history.push( { + categoryType: PATTERN_TYPES.theme, + categoryId, + postType: PATTERN_TYPES.user, + postId: pattern.id, } ); - return Promise.all( terms ); + onClose(); } - async function createPattern() { - try { - const isThemePattern = item.type === PATTERN_TYPES.theme; - const title = sprintf( - /* translators: %s: Existing pattern title */ - __( '%s (Copy)' ), - item.title || item.name - ); - const categories = await getCategories( item.categories || [] ); - - const result = await saveEntityRecord( - 'postType', - PATTERN_TYPES.user, - { - content: isThemePattern - ? item.content - : item.patternBlock.content, - meta: getPatternMeta( item ), - status: 'publish', - title, - wp_pattern_category: categories, - }, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), + const isThemePattern = item.type === PATTERN_TYPES.theme; + const closeModal = () => setIsModalOpen( false ); + const duplicatedProps = isTemplatePart + ? { + blocks: item.blocks, + defaultArea: item.templatePart.area, + defaultTitle: sprintf( + /* translators: %s: Existing template part title */ + __( '%s (Copy)' ), + item.title + ), + } + : { + defaultCategories: isThemePattern + ? item.categories + : item.termLabels, + content: isThemePattern + ? item.content + : item.patternBlock.content, + defaultSyncType: isThemePattern + ? PATTERN_SYNC_TYPES.unsynced + : item.syncStatus, + defaultTitle: sprintf( + /* translators: %s: Existing pattern title */ + __( '%s (Copy)' ), item.title || item.name ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - - history.push( { - categoryType: PATTERN_TYPES.theme, - categoryId, - postType: PATTERN_TYPES.user, - postId: result?.id, - } ); - - onClose(); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while creating the pattern.' ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - id: 'edit-site-patterns-error', - } ); - onClose(); - } - } - - const createItem = - item.type === TEMPLATE_PART_POST_TYPE - ? createTemplatePart - : createPattern; - - return { label }; + }; + + return ( + <> + setIsModalOpen( true ) } + aria-expanded={ isModalOpen } + aria-haspopup="dialog" + > + { label } + + { isModalOpen && ! isTemplatePart && ( + + ) } + { isModalOpen && isTemplatePart && ( + + ) } + > + ); } diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index 6504b6f59684c..fde4eaadb5dc0 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -195,6 +195,11 @@ const patternBlockToPattern = ( patternBlock, categories ) => ( { : patternCategoryId ), } ), + termLabels: patternBlock.wp_pattern_category.map( ( patternCategoryId ) => + categories?.get( patternCategoryId ) + ? categories.get( patternCategoryId ).label + : patternCategoryId + ), id: patternBlock.id, name: patternBlock.slug, syncStatus: patternBlock.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full, diff --git a/packages/patterns/src/components/create-pattern-modal.js b/packages/patterns/src/components/create-pattern-modal.js index 37dd725ef9226..6dd162605506e 100644 --- a/packages/patterns/src/components/create-pattern-modal.js +++ b/packages/patterns/src/components/create-pattern-modal.js @@ -28,15 +28,21 @@ import CategorySelector, { CATEGORY_SLUG } from './category-selector'; import { unlock } from '../lock-unlock'; export default function CreatePatternModal( { - onSuccess, - onError, + confirmLabel = __( 'Create' ), + defaultCategories = [], + className = 'patterns-menu-items__convert-modal', content, + modalTitle = __( 'Create pattern' ), onClose, - className = 'patterns-menu-items__convert-modal', + onError, + onSuccess, + defaultSyncType = PATTERN_SYNC_TYPES.full, + defaultTitle = '', } ) { - const [ syncType, setSyncType ] = useState( PATTERN_SYNC_TYPES.full ); - const [ categoryTerms, setCategoryTerms ] = useState( [] ); - const [ title, setTitle ] = useState( '' ); + const [ syncType, setSyncType ] = useState( defaultSyncType ); + const [ categoryTerms, setCategoryTerms ] = useState( defaultCategories ); + const [ title, setTitle ] = useState( defaultTitle ); + const [ isSaving, setIsSaving ] = useState( false ); const { createPattern } = unlock( useDispatch( patternsStore ) ); const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore ); @@ -145,7 +151,7 @@ export default function CreatePatternModal( { return ( { onClose(); setTitle( '' ); @@ -203,7 +209,7 @@ export default function CreatePatternModal( { aria-disabled={ ! title || isSaving } isBusy={ isSaving } > - { __( 'Create' ) } + { confirmLabel }
WP_HTML_Processor::createFragment
WP_HTML_Processor::create_fragment()
' ); + * $processor = WP_HTML_Processor::create_fragment( '' ); * false === $processor->next_tag(); * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); * @@ -361,6 +361,7 @@ public function get_last_error() { * Defaults to first tag. * @type string|null $class_name Tag must contain this whole class name to match. * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. * } * @return bool Whether a tag was matched. */ @@ -410,26 +411,67 @@ public function next_tag( $query = null ) { $breadcrumbs = $query['breadcrumbs']; $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; - $crumb = end( $breadcrumbs ); - $target = strtoupper( $crumb ); while ( $match_offset > 0 && $this->step() ) { - if ( $target !== $this->get_tag() ) { - continue; + if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { + return true; } + } - // Look up the stack to see if the breadcrumbs match. - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - if ( strtoupper( $crumb ) !== $node->node_name ) { - break; - } + return false; + } - $crumb = prev( $breadcrumbs ); - if ( false === $crumb && 0 === --$match_offset && ! $this->is_tag_closer() ) { - return true; - } + /** + * Indicates if the currently-matched tag matches the given breadcrumbs. + * + * A "*" represents a single tag wildcard, where any tag matches, but not no tags. + * + * At some point this function _may_ support a `**` syntax for matching any number + * of unspecified tags in the breadcrumb stack. This has been intentionally left + * out, however, to keep this function simple and to avoid introducing backtracking, + * which could open up surprising performance breakdowns. + * + * Example: + * + * $processor = WP_HTML_Processor::create_fragment( '' ); + * $processor->next_tag( 'img' ); + * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); + * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); + * + * @since 6.4.0 + * + * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. + * @return bool Whether the currently-matched tag is found at the given nested structure. + */ + public function matches_breadcrumbs( $breadcrumbs ) { + if ( ! $this->get_tag() ) { + return false; + } + + // Everything matches when there are zero constraints. + if ( 0 === count( $breadcrumbs ) ) { + return true; + } + + // Start at the last crumb. + $crumb = end( $breadcrumbs ); + + if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { + return false; + } + + foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { + $crumb = strtoupper( current( $breadcrumbs ) ); + + if ( '*' !== $crumb && $node->node_name !== $crumb ) { + return false; } - $crumb = end( $breadcrumbs ); + if ( false === prev( $breadcrumbs ) ) { + return true; + } } return false; @@ -519,7 +561,7 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { * * Example * - * $processor = WP_HTML_Processor::createFragment( '' ); + * $processor = WP_HTML_Processor::create_fragment( '' ); * $processor->next_tag( 'IMG' ); * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); * @@ -1401,5 +1443,5 @@ public static function is_void( $tag_name ) { * * @access private */ - const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::createFragment instead of calling the class constructor directly.'; + const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; } From 887cf3dfc4b3426ce5696a383216186233c468e1 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:42:00 +1100 Subject: [PATCH 05/32] Private APIs: Update consent string for unlocking access. (#55182) Replace the consent string with `I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress`. --- docs/contributors/code/coding-guidelines.md | 2 +- packages/block-editor/src/lock-unlock.js | 2 +- packages/block-library/src/lock-unlock.js | 2 +- packages/blocks/src/lock-unlock.js | 2 +- packages/commands/src/lock-unlock.js | 2 +- packages/components/src/private-apis.ts | 2 +- packages/core-commands/src/lock-unlock.js | 2 +- packages/core-data/src/private-apis.js | 2 +- packages/customize-widgets/src/lock-unlock.js | 2 +- packages/data/src/lock-unlock.js | 2 +- packages/edit-post/src/lock-unlock.js | 2 +- packages/edit-site/src/lock-unlock.js | 2 +- packages/edit-widgets/src/lock-unlock.js | 2 +- packages/editor/src/lock-unlock.js | 2 +- packages/patterns/src/lock-unlock.js | 2 +- packages/private-apis/README.md | 4 ++-- packages/private-apis/src/implementation.js | 2 +- packages/private-apis/src/test/index.js | 2 +- packages/reusable-blocks/src/lock-unlock.js | 2 +- packages/router/src/lock-unlock.js | 2 +- 20 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/contributors/code/coding-guidelines.md b/docs/contributors/code/coding-guidelines.md index 90fb5c7adf81f..53f0a0f8d1000 100644 --- a/docs/contributors/code/coding-guidelines.md +++ b/docs/contributors/code/coding-guidelines.md @@ -162,7 +162,7 @@ do so by opting-in to `@wordpress/private-apis`: import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' // Name of the package calling __dangerousOptInToUnstableAPIsOnlyForCoreModules, // (not the name of the package whose APIs you want to access) ); diff --git a/packages/block-editor/src/lock-unlock.js b/packages/block-editor/src/lock-unlock.js index 019821d284b36..433a61a12aec0 100644 --- a/packages/block-editor/src/lock-unlock.js +++ b/packages/block-editor/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' ); diff --git a/packages/block-library/src/lock-unlock.js b/packages/block-library/src/lock-unlock.js index 3fef0820721be..3c18e76b798cd 100644 --- a/packages/block-library/src/lock-unlock.js +++ b/packages/block-library/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-library' ); diff --git a/packages/blocks/src/lock-unlock.js b/packages/blocks/src/lock-unlock.js index 363b51af7d233..0a98fcfb19d29 100644 --- a/packages/blocks/src/lock-unlock.js +++ b/packages/blocks/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/blocks' ); diff --git a/packages/commands/src/lock-unlock.js b/packages/commands/src/lock-unlock.js index 0665114d842c3..e11bd687d8742 100644 --- a/packages/commands/src/lock-unlock.js +++ b/packages/commands/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/commands' ); diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index fd61c2564e6b0..fa086f783b4b2 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -34,7 +34,7 @@ import Theme from './theme'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/components' ); diff --git a/packages/core-commands/src/lock-unlock.js b/packages/core-commands/src/lock-unlock.js index 24973274f1897..6f0712a8069fd 100644 --- a/packages/core-commands/src/lock-unlock.js +++ b/packages/core-commands/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/core-commands' ); diff --git a/packages/core-data/src/private-apis.js b/packages/core-data/src/private-apis.js index a5b93a25dbf77..53f0dc2dfa133 100644 --- a/packages/core-data/src/private-apis.js +++ b/packages/core-data/src/private-apis.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/core-data' ); diff --git a/packages/customize-widgets/src/lock-unlock.js b/packages/customize-widgets/src/lock-unlock.js index f428bbaac936a..01d57a2835d5d 100644 --- a/packages/customize-widgets/src/lock-unlock.js +++ b/packages/customize-widgets/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/customize-widgets' ); diff --git a/packages/data/src/lock-unlock.js b/packages/data/src/lock-unlock.js index 5fdca775a27b8..b5b1f9cbed5a5 100644 --- a/packages/data/src/lock-unlock.js +++ b/packages/data/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/data' ); diff --git a/packages/edit-post/src/lock-unlock.js b/packages/edit-post/src/lock-unlock.js index 172d18df7d1ba..bf65b262d9f48 100644 --- a/packages/edit-post/src/lock-unlock.js +++ b/packages/edit-post/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-post' ); diff --git a/packages/edit-site/src/lock-unlock.js b/packages/edit-site/src/lock-unlock.js index 9934484ea2347..5c335db46b9d4 100644 --- a/packages/edit-site/src/lock-unlock.js +++ b/packages/edit-site/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-site' ); diff --git a/packages/edit-widgets/src/lock-unlock.js b/packages/edit-widgets/src/lock-unlock.js index a13068520e077..003e53788068c 100644 --- a/packages/edit-widgets/src/lock-unlock.js +++ b/packages/edit-widgets/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-widgets' ); diff --git a/packages/editor/src/lock-unlock.js b/packages/editor/src/lock-unlock.js index 5a36d0cd752f4..12df6f4711b23 100644 --- a/packages/editor/src/lock-unlock.js +++ b/packages/editor/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/editor' ); diff --git a/packages/patterns/src/lock-unlock.js b/packages/patterns/src/lock-unlock.js index 51adc98f32cac..d727871d71439 100644 --- a/packages/patterns/src/lock-unlock.js +++ b/packages/patterns/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/patterns' ); diff --git a/packages/private-apis/README.md b/packages/private-apis/README.md index 9faaada853200..cdc1db2180e2c 100644 --- a/packages/private-apis/README.md +++ b/packages/private-apis/README.md @@ -12,7 +12,7 @@ Every `@wordpress` package wanting to privately access or expose experimental AP import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' // Name of the package calling __dangerousOptInToUnstableAPIsOnlyForCoreModules, // (not the name of the package whose APIs you want to access) ); @@ -22,7 +22,7 @@ Each package may only opt in once. The function name communicates that plugins a The function will throw an error if the following conditions are not met: -1. The first argument must exactly match the required consent string: `'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'`. +1. The first argument must exactly match the required consent string: `'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'`. 2. The second argument must be a known `@wordpress` package that hasn't yet opted into `@wordpress/private-apis` Once the opt-in is complete, the obtained `lock()` and `unlock()` utilities enable hiding `__experimental` APIs from the naked eye: diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index 4f1877bff569e..14d3048eff68b 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -51,7 +51,7 @@ const registeredPrivateApis = []; * CHANGE MAY OCCUR IN EITHER A MAJOR OR MINOR RELEASE. */ const requiredConsent = - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'; /** @type {boolean} */ let allowReRegistration; diff --git a/packages/private-apis/src/test/index.js b/packages/private-apis/src/test/index.js index 2e73a1a58eaa1..d91f7d3bcdafe 100644 --- a/packages/private-apis/src/test/index.js +++ b/packages/private-apis/src/test/index.js @@ -16,7 +16,7 @@ beforeEach( () => { } ); const requiredConsent = - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'; describe( '__dangerousOptInToUnstableAPIsOnlyForCoreModules', () => { it( 'Should require a consent string', () => { diff --git a/packages/reusable-blocks/src/lock-unlock.js b/packages/reusable-blocks/src/lock-unlock.js index c33f209c9d76a..c0bc2d1529f7d 100644 --- a/packages/reusable-blocks/src/lock-unlock.js +++ b/packages/reusable-blocks/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/reusable-blocks' ); diff --git a/packages/router/src/lock-unlock.js b/packages/router/src/lock-unlock.js index d148f785fe944..d7f4e92b4a542 100644 --- a/packages/router/src/lock-unlock.js +++ b/packages/router/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/router' ); From 84ed4a69e9715e71bcc4f3593154c3b82dd16531 Mon Sep 17 00:00:00 2001 From: Cullen Whitmore Date: Tue, 10 Oct 2023 19:41:22 -0500 Subject: [PATCH 06/32] docs: Update broken anchor link (#55233) --- packages/create-block/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index edcdd020caf38..88ac97c34c2cf 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -28,7 +28,7 @@ $ cd todo-list $ npm start ``` -The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation). +The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation-1). _(requires `node` version `14.0.0` or above, and `npm` version `6.14.4` or above)_ From 7602b560eca577d58ccbdf41d42ed5186caccc80 Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 10 Oct 2023 13:58:37 -0700 Subject: [PATCH 07/32] Block Supports: Backport optimization from Core for Elements Support Brings over optimization surfaced during the WordPress 6.4 beta release for block supports elements, which entails skipping needless iteration when it's known that the iteration need not continue. See WordPress/wordpress-develop#5411 See [#59544-trac](https://core.trac.wordpress.org/ticket/59544) --- lib/block-supports/elements.php | 88 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 2106360c4bd04..85dbd7d39797c 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -13,7 +13,7 @@ * @return string Filtered block content. */ function gutenberg_render_elements_support( $block_content, $block ) { - if ( ! $block_content || empty( $block['attrs'] ) ) { + if ( ! $block_content || ! isset( $block['attrs']['style']['elements'] ) ) { return $block_content; } @@ -23,42 +23,42 @@ function gutenberg_render_elements_support( $block_content, $block ) { 'button' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ), 'paths' => array( - 'style.elements.button.color.text', - 'style.elements.button.color.background', - 'style.elements.button.color.gradient', + array( 'button', 'color', 'text' ), + array( 'button', 'color', 'background' ), + array( 'button', 'color', 'gradient' ), ), ), 'link' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ), 'paths' => array( - 'style.elements.link.color.text', - 'style.elements.link.:hover.color.text', + array( 'link', 'color', 'text' ), + array( 'link', ':hover', 'color', 'text' ), ), ), 'heading' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ), 'paths' => array( - 'style.elements.heading.color.text', - 'style.elements.heading.color.background', - 'style.elements.heading.color.gradient', - 'style.elements.h1.color.text', - 'style.elements.h1.color.background', - 'style.elements.h1.color.gradient', - 'style.elements.h2.color.text', - 'style.elements.h2.color.background', - 'style.elements.h2.color.gradient', - 'style.elements.h3.color.text', - 'style.elements.h3.color.background', - 'style.elements.h3.color.gradient', - 'style.elements.h4.color.text', - 'style.elements.h4.color.background', - 'style.elements.h4.color.gradient', - 'style.elements.h5.color.text', - 'style.elements.h5.color.background', - 'style.elements.h5.color.gradient', - 'style.elements.h6.color.text', - 'style.elements.h6.color.background', - 'style.elements.h6.color.gradient', + array( 'heading', 'color', 'text' ), + array( 'heading', 'color', 'background' ), + array( 'heading', 'color', 'gradient' ), + array( 'h1', 'color', 'text' ), + array( 'h1', 'color', 'background' ), + array( 'h1', 'color', 'gradient' ), + array( 'h2', 'color', 'text' ), + array( 'h2', 'color', 'background' ), + array( 'h2', 'color', 'gradient' ), + array( 'h3', 'color', 'text' ), + array( 'h3', 'color', 'background' ), + array( 'h3', 'color', 'gradient' ), + array( 'h4', 'color', 'text' ), + array( 'h4', 'color', 'background' ), + array( 'h4', 'color', 'gradient' ), + array( 'h5', 'color', 'text' ), + array( 'h5', 'color', 'background' ), + array( 'h5', 'color', 'gradient' ), + array( 'h6', 'color', 'text' ), + array( 'h6', 'color', 'background' ), + array( 'h6', 'color', 'gradient' ), ), ), ); @@ -71,7 +71,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { return $block_content; } - $element_colors_set = 0; + $elements_style_attributes = $block['attrs']['style']['elements']; foreach ( $element_color_properties as $element_config ) { if ( $element_config['skip'] ) { @@ -79,24 +79,28 @@ function gutenberg_render_elements_support( $block_content, $block ) { } foreach ( $element_config['paths'] as $path ) { - if ( null !== _wp_array_get( $block['attrs'], explode( '.', $path ), null ) ) { - ++$element_colors_set; + if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) { + /* + * It only takes a single custom attribute to require that the custom + * class name be added to the block, so once one is found there's no + * need to continue looking for others. + * + * As is done with the layout hook, this code assumes that the block + * contains a single wrapper and that it's the first element in the + * rendered output. That first element, if it exists, gets the class. + */ + $tags = new WP_HTML_Tag_Processor( $block_content ); + if ( $tags->next_tag() ) { + $tags->add_class( wp_get_elements_class_name( $block ) ); + } + + return $tags->get_updated_html(); } } } - if ( ! $element_colors_set ) { - return $block_content; - } - - // Like the layout hook this assumes the hook only applies to blocks with a single wrapper. - // Add the class name to the first element, presuming it's the wrapper, if it exists. - $tags = new WP_HTML_Tag_Processor( $block_content ); - if ( $tags->next_tag() ) { - $tags->add_class( wp_get_elements_class_name( $block ) ); - } - - return $tags->get_updated_html(); + // If no custom attributes were found then there's nothing to modify. + return $block_content; } /** From 4d04850d1a03c55689844bccc20916129b962519 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 11 Oct 2023 14:04:04 +1100 Subject: [PATCH 08/32] Remove `@return void` from PHP function docs. (#55237) --- packages/block-library/src/form/index.php | 4 ---- packages/block-library/src/image/index.php | 4 ---- packages/block-library/src/pattern/index.php | 2 -- packages/block-library/src/search/index.php | 4 ---- 4 files changed, 14 deletions(-) diff --git a/packages/block-library/src/form/index.php b/packages/block-library/src/form/index.php index 0dbbaf6838740..b9e3a9c25c628 100644 --- a/packages/block-library/src/form/index.php +++ b/packages/block-library/src/form/index.php @@ -83,8 +83,6 @@ function block_core_form_extra_fields_comment_form( $extra_fields, $attributes ) /** * Sends an email if the form is a contact form. - * - * @return void */ function block_core_form_send_email() { check_ajax_referer( 'wp-block-form' ); @@ -126,8 +124,6 @@ function block_core_form_send_email() { /** * Send the data export/remove request if the form is a privacy-request form. - * - * @return void */ function block_core_form_privacy_form() { // Get the POST data. diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index e1f71964622c0..9cce87d9e8bd7 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -310,8 +310,6 @@ function block_core_image_render_lightbox( $block_content, $block ) { * @since 6.4.0 * * @global WP_Scripts $wp_scripts - * - * @return void */ function block_core_image_ensure_interactivity_dependency() { global $wp_scripts; @@ -327,8 +325,6 @@ function block_core_image_ensure_interactivity_dependency() { /** * Registers the `core/image` block on server. - * - * @return void */ function register_block_core_image() { register_block_type_from_metadata( diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index fc4652a7c22e8..1f5477968b92d 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -7,8 +7,6 @@ /** * Registers the `core/pattern` block on the server. - * - * @return void */ function register_block_core_pattern() { register_block_type_from_metadata( diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index ed3d1cf4b847a..f00ecfe6abe1c 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -281,8 +281,6 @@ function classnames_for_block_core_search( $attributes ) { * @param array $wrapper_styles Current collection of wrapper styles. * @param array $button_styles Current collection of button styles. * @param array $input_styles Current collection of input styles. - * - * @return void */ function apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) { $is_button_inside = isset( $attributes['buttonPosition'] ) && 'button-inside' === $attributes['buttonPosition']; @@ -327,8 +325,6 @@ function apply_block_core_search_border_style( $attributes, $property, $side, &$ * @param array $wrapper_styles Current collection of wrapper styles. * @param array $button_styles Current collection of button styles. * @param array $input_styles Current collection of input styles. - * - * @return void */ function apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) { apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles ); From f29a96b3fa63eabbd1d97f0f7e66b070986752b1 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr Date: Wed, 11 Oct 2023 08:49:34 +0200 Subject: [PATCH 09/32] useBlockSettings: add missing useMemo dependencies (#55204) --- packages/block-editor/src/hooks/utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index f81fc118ea84b..8e0d422c5fbec 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -279,6 +279,8 @@ export function useBlockSettings( name, parentLayout ) { isBackgroundEnabled, isLinkEnabled, isTextEnabled, + isHeadingEnabled, + isButtonEnabled, ] ); return useSettingsForBlockElement( rawSettings, name ); From 8a9cb70272edcfdfd34f3557848949eb0fd29921 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Oct 2023 07:56:23 +0100 Subject: [PATCH 10/32] DataViews: Allow actions to be provided declaratively as a prop (#55192) * DataViews: Allow actions to be provided declaratively as a prop * Restore PageActions component * Rename variable * Fix typo --- .../src/components/actions/trash-post.js | 55 +++++++++++++++++++ .../src/components/dataviews/dataviews.js | 51 ++++++++++++++++- .../src/components/page-actions/index.js | 8 +-- .../src/components/page-pages/index.js | 18 ++---- 4 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 packages/edit-site/src/components/actions/trash-post.js diff --git a/packages/edit-site/src/components/actions/trash-post.js b/packages/edit-site/src/components/actions/trash-post.js new file mode 100644 index 0000000000000..7977ed3d11e00 --- /dev/null +++ b/packages/edit-site/src/components/actions/trash-post.js @@ -0,0 +1,55 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { decodeEntities } from '@wordpress/html-entities'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useMemo } from '@wordpress/element'; + +export default function useMoveToTrashAction() { + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + const { deleteEntityRecord } = useDispatch( coreStore ); + + return useMemo( + () => ( { + id: 'move-to-trash', + label: __( 'Move to Trash' ), + async perform( post ) { + try { + await deleteEntityRecord( + 'postType', + post.type, + post.id, + {}, + { throwOnError: true } + ); + createSuccessNotice( + sprintf( + /* translators: The page's title. */ + __( '"%s" moved to the Trash.' ), + decodeEntities( post.title.rendered ) + ), + { + type: 'snackbar', + id: 'edit-site-page-trashed', + } + ); + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( + 'An error occurred while moving the page to the trash.' + ); + + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + }, + isDesctructive: true, + } ), + [ createSuccessNotice, createErrorNotice, deleteEntityRecord ] + ); +} diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 4628d850a023c..13e27ddfacae5 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -15,7 +15,13 @@ import { import { __experimentalVStack as VStack, __experimentalHStack as HStack, + VisuallyHidden, + DropdownMenu, + MenuGroup, + MenuItem, } from '@wordpress/components'; +import { useMemo } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -24,8 +30,10 @@ import ListView from './list-view'; import { Pagination } from './pagination'; import ViewActions from './view-actions'; import TextFilter from './text-filter'; +import { moreVertical } from '@wordpress/icons'; export default function DataViews( { + actions, data, fields, view, @@ -34,9 +42,50 @@ export default function DataViews( { paginationInfo, options: { pageCount }, } ) { + const columns = useMemo( () => { + const _columns = [ ...fields ]; + if ( actions && actions.length ) { + _columns.push( { + header: { __( 'Actions' ) }, + id: 'actions', + cell: ( props ) => { + return ( + + { () => ( + + { actions.map( ( action ) => ( + + action.perform( + props.row.original + ) + } + isDestructive={ + action.isDesctructive + } + > + { action.label } + + ) ) } + + ) } + + ); + }, + enableHiding: false, + } ); + } + + return _columns; + }, [ fields, actions ] ); + const dataView = useReactTable( { data, - columns: fields, + columns, manualSorting: true, manualFiltering: true, manualPagination: true, diff --git a/packages/edit-site/src/components/page-actions/index.js b/packages/edit-site/src/components/page-actions/index.js index f6f0119a16454..d42a706c36796 100644 --- a/packages/edit-site/src/components/page-actions/index.js +++ b/packages/edit-site/src/components/page-actions/index.js @@ -10,17 +10,11 @@ import { moreVertical } from '@wordpress/icons'; */ import TrashPageMenuItem from './trash-page-menu-item'; -export default function PageActions( { - postId, - className, - toggleProps, - onRemove, -} ) { +export default function PageActions( { postId, toggleProps, onRemove } ) { return ( { () => ( diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 56575248453f0..2c7b07044dbdd 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { - VisuallyHidden, __experimentalHeading as Heading, __experimentalVStack as VStack, } from '@wordpress/components'; @@ -16,8 +15,8 @@ import { useState, useMemo } from '@wordpress/element'; */ import Page from '../page'; import Link from '../routes/link'; -import PageActions from '../page-actions'; import { DataViews } from '../dataviews'; +import useTrashPostAction from '../actions/trash-post'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -118,27 +117,22 @@ export default function PagePages() { postStatuses[ page.status ] ?? page.status, enableSorting: false, }, - { - header: { __( 'Actions' ) }, - id: 'actions', - cell: ( props ) => { - const page = props.row.original; - return ; - }, - enableHiding: false, - }, ], [ postStatuses ] ); + const trashPostAction = useTrashPostAction(); + const actions = useMemo( () => [ trashPostAction ], [ trashPostAction ] ); + // TODO: we need to handle properly `data={ data || EMPTY_ARRAY }` for when `isLoading`. return ( Date: Wed, 11 Oct 2023 10:02:46 +0200 Subject: [PATCH 11/32] Remove the lightbox filter and view file when the lightbox setting is disabled. (#55120) * Remove the filter and view file of the lightbox when the lightbox setting is disabled. * Make sure to add filter and view file when needed. * Fix block comment indentation. --- packages/block-library/src/image/index.php | 62 +++++++++++----------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 9cce87d9e8bd7..4213350ab05c8 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -32,45 +32,47 @@ function render_block_core_image( $attributes, $content, $block ) { $processor->set_attribute( 'data-id', $attributes['data-id'] ); } - $lightbox_enabled = false; $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block ); - // If the lightbox is enabled and the image is not linked, flag the lightbox to be rendered. - if ( isset( $lightbox_settings ) && 'none' === $link_destination ) { + $view_js_file_handle = 'wp-block-image-view'; + $script_handles = $block->block_type->view_script_handles; - if ( isset( $lightbox_settings['enabled'] ) && true === $lightbox_settings['enabled'] ) { - $lightbox_enabled = true; - } - } - - // If at least one block in the page has the lightbox, mark the block type as interactive. - if ( $lightbox_enabled ) { + /* + * If the lightbox is enabled and the image is not linked, add the filter + * and the JavaScript view file. + */ + if ( + isset( $lightbox_settings ) && + 'none' === $link_destination && + isset( $lightbox_settings['enabled'] ) && + true === $lightbox_settings['enabled'] + ) { $block->block_type->supports['interactivity'] = true; - } - - // Determine whether the view script should be enqueued or not. - $view_js_file = 'wp-block-image-view'; - if ( ! wp_script_is( $view_js_file ) ) { - $script_handles = $block->block_type->view_script_handles; - // If the script is not needed, and it is still in the `view_script_handles`, remove it. - if ( ! $lightbox_enabled && in_array( $view_js_file, $script_handles, true ) ) { - $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) ); - } - // If the script is needed, but it was previously removed, add it again. - if ( $lightbox_enabled && ! in_array( $view_js_file, $script_handles, true ) ) { - $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) ); + if ( ! in_array( $view_js_file_handle, $script_handles, true ) ) { + $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file_handle ) ); } - } - if ( $lightbox_enabled ) { - // This render needs to happen in a filter with priority 15 to ensure that it - // runs after the duotone filter and that duotone styles are applied to the image - // in the lightbox. We also need to ensure that the lightbox works with any plugins - // that might use filters as well. We can consider removing this in the future if the - // way the blocks are rendered changes, or if a new kind of filter is introduced. + /* + * This render needs to happen in a filter with priority 15 to ensure + * that it runs after the duotone filter and that duotone styles are + * applied to the image in the lightbox. We also need to ensure that the + * lightbox works with any plugins that might use filters as well. We + * can consider removing this in the future if the way the blocks are + * rendered changes, or if a new kind of filter is introduced. + */ add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 ); + } else { + /* + * Remove the filter and the JavaScript view file if previously added by + * other Image blocks. + */ + remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 ); + // If the script is not needed, and it is still in the `view_script_handles`, remove it. + if ( in_array( $view_js_file_handle, $script_handles, true ) ) { + $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file_handle ) ); + } } return $processor->get_updated_html(); From e1258031c11cd23d8d30bcf2521a81d04e512491 Mon Sep 17 00:00:00 2001 From: Andrew Hayward Date: Wed, 11 Oct 2023 09:48:07 +0100 Subject: [PATCH 12/32] Add `type="button"` to vanilla `` elements (#55125) * Adding `type="button` to buttons as needed * Updating test snapshots * Updating `CHANGELOG.md` --- .../color-palette/test/__snapshots__/control.js.snap | 1 + packages/block-library/src/page-list-item/edit.js | 2 ++ packages/components/CHANGELOG.md | 3 ++- packages/components/src/color-palette/index.tsx | 1 + .../test/__snapshots__/index.tsx.snap | 8 ++++++++ .../toggle-group-control-option-base/component.tsx | 1 + .../src/components/block-editor/resize-handle.js | 1 + .../edit-site/src/components/page-patterns/grid-item.js | 1 + 8 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index 242218705b3cf..3942c05ce96f1 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -175,6 +175,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` aria-label="Custom color picker. The currently selected color is called "red" and has a value of "#f00"." class="components-color-palette__custom-color-button" style="background: rgb(255, 0, 0);" + type="button" /> @@ -90,6 +91,7 @@ export default function PageListItemEdit( { context, attributes } ) { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3dfc268ad2163..0605bda1a47e5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). ### Bug Fix @@ -52,7 +53,7 @@ ### Experimental -- Introduce `Tabs`, an experimental v2 of `TabPanel`: ([#53960](https://github.com/WordPress/gutenberg/pull/53960)). +- Introduce `Tabs`, an experimental v2 of `TabPanel`: ([#53960](https://github.com/WordPress/gutenberg/pull/53960)). ## 25.8.0 (2023-09-20) diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index f87d46e64bc09..297e03f389e3e 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -299,6 +299,7 @@ function UnforwardedColorPalette( style={ { background: value, } } + type="button" /> { onFocusProp?.( event ); diff --git a/packages/edit-site/src/components/block-editor/resize-handle.js b/packages/edit-site/src/components/block-editor/resize-handle.js index 199ca09869cf9..0e9fae084ec89 100644 --- a/packages/edit-site/src/components/block-editor/resize-handle.js +++ b/packages/edit-site/src/components/block-editor/resize-handle.js @@ -35,6 +35,7 @@ export default function ResizeHandle( { aria-label={ __( 'Drag to resize' ) } aria-describedby={ `resizable-editor__resize-help-${ direction }` } onKeyDown={ handleKeyDown } + type="button" /> Date: Wed, 11 Oct 2023 11:37:25 +0200 Subject: [PATCH 13/32] Patterns: Remove the version enforcement for npm in `engines` field (#55245) * Patterns: Remove the version enforcement for npm in `engines` * Regenerate the lock file --- package-lock.json | 3 +-- packages/patterns/package.json | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 341db8407614b..c457a01b4b74b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57445,8 +57445,7 @@ "@wordpress/url": "file:../url" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8 <9" + "node": ">=16.0.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 0cb8857df9a4b..d8cabf9fae235 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -19,8 +19,7 @@ "url": "https://github.com/WordPress/gutenberg/issues" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8 <9" + "node": ">=16.0.0" }, "main": "build/index.js", "module": "build-module/index.js", From 3c75843af3002ff943dc8802d4f8b7e83cbf209a Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Wed, 11 Oct 2023 11:41:10 +0100 Subject: [PATCH 14/32] fix: Fix border visibility in block-based themes (#54964) --- packages/primitives/src/block-quotation/index.native.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/primitives/src/block-quotation/index.native.js b/packages/primitives/src/block-quotation/index.native.js index 01e8b7cdb4c50..3d0d29c297245 100644 --- a/packages/primitives/src/block-quotation/index.native.js +++ b/packages/primitives/src/block-quotation/index.native.js @@ -20,6 +20,9 @@ export const BlockQuotation = forwardRef( ( { ...props }, ref ) => { styles.wpBlockQuoteLight, styles.wpBlockQuoteDark ), + style?.baseColors?.color?.text && { + borderLeftColor: style.baseColors.color.text, + }, style?.color && { borderLeftColor: style.color, }, From 0c216e400b3cc7764cc27713bf44c31e3712dc57 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 11 Oct 2023 14:45:32 +0300 Subject: [PATCH 15/32] [DataViews]: Update the view config to include fields visibility (#55247) * [DataViews]: Update the view config to include fields visibility * fix typo * use array instead of Set for `hidden` * use `hiddenFields` top level prop --- .../src/components/dataviews/dataviews.js | 39 ++++++++++++++++++- .../src/components/dataviews/view-actions.js | 6 +-- .../src/components/page-pages/index.js | 16 ++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 13e27ddfacae5..0131040bf83af 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -32,6 +32,8 @@ import ViewActions from './view-actions'; import TextFilter from './text-filter'; import { moreVertical } from '@wordpress/icons'; +const EMPTY_OBJECT = {}; + export default function DataViews( { actions, data, @@ -44,7 +46,7 @@ export default function DataViews( { } ) { const columns = useMemo( () => { const _columns = [ ...fields ]; - if ( actions && actions.length ) { + if ( actions?.length ) { _columns.push( { header: { __( 'Actions' ) }, id: 'actions', @@ -83,6 +85,19 @@ export default function DataViews( { return _columns; }, [ fields, actions ] ); + const columnVisibility = useMemo( () => { + if ( ! view.hiddenFields?.length ) { + return; + } + return view.hiddenFields.reduce( + ( accumulator, fieldId ) => ( { + ...accumulator, + [ fieldId ]: false, + } ), + {} + ); + }, [ view.hiddenFields ] ); + const dataView = useReactTable( { data, columns, @@ -104,6 +119,7 @@ export default function DataViews( { pageIndex: view.page, pageSize: view.perPage, }, + columnVisibility: columnVisibility ?? EMPTY_OBJECT, }, onSortingChange: ( sortingUpdater ) => { onChangeView( ( currentView ) => { @@ -135,6 +151,27 @@ export default function DataViews( { }; } ); }, + onColumnVisibilityChange: ( columnVisibilityUpdater ) => { + onChangeView( ( currentView ) => { + const hiddenFields = Object.entries( + columnVisibilityUpdater() + ).reduce( + ( accumulator, [ fieldId, value ] ) => { + if ( value ) { + return accumulator.filter( + ( id ) => id !== fieldId + ); + } + return [ ...accumulator, fieldId ]; + }, + [ ...( currentView.hiddenFields || [] ) ] + ); + return { + ...currentView, + hiddenFields, + }; + } ); + }, onGlobalFilterChange: ( value ) => { onChangeView( { ...view, search: value, page: 0 } ); }, diff --git a/packages/edit-site/src/components/dataviews/view-actions.js b/packages/edit-site/src/components/dataviews/view-actions.js index 1ede6ebcd8b75..ab9f3be88c200 100644 --- a/packages/edit-site/src/components/dataviews/view-actions.js +++ b/packages/edit-site/src/components/dataviews/view-actions.js @@ -102,10 +102,10 @@ function PageSizeMenu( { dataView } ) { } function FieldsVisibilityMenu( { dataView } ) { - const hideableFields = dataView + const hidableFields = dataView .getAllColumns() .filter( ( columnn ) => columnn.getCanHide() ); - if ( ! hideableFields?.length ) { + if ( ! hidableFields?.length ) { return null; } return ( @@ -118,7 +118,7 @@ function FieldsVisibilityMenu( { dataView } ) { } > - { hideableFields?.map( ( field ) => { + { hidableFields?.map( ( field ) => { return ( { + const formattedDate = dateI18n( + getSettings().formats.datetimeAbbreviated, + getDate( props.row.original.date ) + ); + return { formattedDate }; + }, + enableSorting: false, + }, ], [ postStatuses ] ); From 75ea690cae00f70366357b2976e2aaa0e72c576e Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:04:27 +0300 Subject: [PATCH 16/32] Data views: add linked title fallback (#55248) --- packages/edit-site/src/components/page-pages/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 62276f314f746..ec27265302748 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -91,7 +91,8 @@ export default function PagePages() { canvas: 'edit', } } > - { decodeEntities( props.getValue() ) } + { decodeEntities( props.getValue() ) || + __( '(no title)' ) } From 9e11bfc6f4066a9a288f1e4ddba1e3037d6a53d0 Mon Sep 17 00:00:00 2001 From: Artemio Morales Date: Wed, 11 Oct 2023 07:12:43 -0500 Subject: [PATCH 17/32] Image: Disable lightbox editor UI for linked images (#55141) * Disable lightbox UI and add help text for linked images * Update help text --- packages/block-library/src/image/image.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index d49a8f7cd0578..1f602c4380e88 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -377,6 +377,8 @@ export default function Image( { const lightboxChecked = !! lightbox?.enabled || ( ! lightbox && !! lightboxSetting?.enabled ); + const lightboxToggleDisabled = linkDestination !== 'none'; + const dimensionsControl = ( ) } From bd3ea8771a09e6e86f6d662fe0242089d81c7873 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 11 Oct 2023 14:42:59 +0100 Subject: [PATCH 18/32] Only handle rename UI if selected (#55250) --- packages/block-editor/src/hooks/block-rename-ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-rename-ui.js b/packages/block-editor/src/hooks/block-rename-ui.js index 6a98dcf2e2fad..aec11a9b2c657 100644 --- a/packages/block-editor/src/hooks/block-rename-ui.js +++ b/packages/block-editor/src/hooks/block-rename-ui.js @@ -189,13 +189,13 @@ function BlockRenameControl( props ) { export const withBlockRenameControl = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { - const { clientId, name, attributes, setAttributes } = props; + const { clientId, name, attributes, setAttributes, isSelected } = props; const supportsBlockNaming = hasBlockSupport( name, 'renaming', true ); return ( <> - { supportsBlockNaming && ( + { isSelected && supportsBlockNaming && ( <> Date: Wed, 11 Oct 2023 15:53:52 +0200 Subject: [PATCH 19/32] Colors: Fix color button border radii (#55207) * Apply the classname prop to `ToolsPanelItem` only when it s not a placeholder * Color Gradient panel: use new selctors to select first and last items * Add fallback for browsers not yet supporting the `:has()` selector * Use nth-child notation instead of :has and sibling selector * CHANGELOG --- .../src/components/colors-gradients/style.scss | 6 ++++-- packages/components/CHANGELOG.md | 1 + .../src/tools-panel/tools-panel-item/hook.ts | 10 ++++------ .../components/src/tools-panel/tools-panel/README.md | 3 +++ packages/components/src/tools-panel/types.ts | 2 ++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/colors-gradients/style.scss b/packages/block-editor/src/components/colors-gradients/style.scss index 8b36f04b83552..6cade124b7fe4 100644 --- a/packages/block-editor/src/components/colors-gradients/style.scss +++ b/packages/block-editor/src/components/colors-gradients/style.scss @@ -77,14 +77,16 @@ $swatch-gap: 12px; border-right: 1px solid $gray-300; border-bottom: 1px solid $gray-300; - &.first { + // Identify the first visible instance as placeholder items will not have this class. + &:nth-child(1 of &) { margin-top: $grid-unit-30; border-top-left-radius: $radius-block-ui; border-top-right-radius: $radius-block-ui; border-top: 1px solid $gray-300; } - &.last { + // Identify the last visible instance as placeholder items will not have this class. + &:nth-last-child(1 of &) { border-bottom-left-radius: $radius-block-ui; border-bottom-right-radius: $radius-block-ui; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0605bda1a47e5..b3c01c4db2c70 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- `ToolsPanel`: do not apply the `className` to prop to `ToolsPanelItem` components when rendered as placeholders ([#55207](https://github.com/WordPress/gutenberg/pull/55207)). - `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). ### Bug Fix diff --git a/packages/components/src/tools-panel/tools-panel-item/hook.ts b/packages/components/src/tools-panel/tools-panel-item/hook.ts index 95958ae9f4860..23701afdfcfd0 100644 --- a/packages/components/src/tools-panel/tools-panel-item/hook.ts +++ b/packages/components/src/tools-panel/tools-panel-item/hook.ts @@ -176,18 +176,16 @@ export function useToolsPanelItem( const cx = useCx(); const classes = useMemo( () => { - const placeholderStyle = - shouldRenderPlaceholder && - ! isShown && - styles.ToolsPanelItemPlaceholder; + const shouldApplyPlaceholderStyles = + shouldRenderPlaceholder && ! isShown; const firstItemStyle = firstDisplayedItem === label && __experimentalFirstVisibleItemClass; const lastItemStyle = lastDisplayedItem === label && __experimentalLastVisibleItemClass; return cx( styles.ToolsPanelItem, - placeholderStyle, - className, + shouldApplyPlaceholderStyles && styles.ToolsPanelItemPlaceholder, + ! shouldApplyPlaceholderStyles && className, firstItemStyle, lastItemStyle ); diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md index 6802a6436875a..0ee251592d67b 100644 --- a/packages/components/src/tools-panel/tools-panel/README.md +++ b/packages/components/src/tools-panel/tools-panel/README.md @@ -191,5 +191,8 @@ A function to call when the `Reset all` menu option is selected. As an argument, Advises the `ToolsPanel` that all of its `ToolsPanelItem` children should render placeholder content (instead of `null`) when they are toggled off and hidden. +Note that placeholder items won't apply the `className` that would be +normally applied to a visible `ToolsPanelItem` via the `className` prop. + - Required: No - Default: `false` diff --git a/packages/components/src/tools-panel/types.ts b/packages/components/src/tools-panel/types.ts index 183ed3254fe80..3156137e58044 100644 --- a/packages/components/src/tools-panel/types.ts +++ b/packages/components/src/tools-panel/types.ts @@ -50,6 +50,8 @@ export type ToolsPanelProps = { /** * Advises the `ToolsPanel` that its child `ToolsPanelItem`s should render * placeholder content instead of null when they are toggled off and hidden. + * Note that placeholder items won't apply the `className` that would be + * normally applied to a visible `ToolsPanelItem` via the `className` prop. * * @default false */ From bc47191907929ea89236df76063d434d48bff822 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Oct 2023 14:58:10 +0100 Subject: [PATCH 20/32] DataViews: Add featured image field to the page list (#55246) Co-authored-by: ntsekouras --- .../edit-site/src/components/media/index.js | 27 +++++++++++++++++++ .../src/components/page-pages/index.js | 19 +++++++++++-- .../src/components/page-pages/style.scss | 4 +++ packages/edit-site/src/style.scss | 1 + 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 packages/edit-site/src/components/media/index.js create mode 100644 packages/edit-site/src/components/page-pages/style.scss diff --git a/packages/edit-site/src/components/media/index.js b/packages/edit-site/src/components/media/index.js new file mode 100644 index 0000000000000..7120d7c7f56ce --- /dev/null +++ b/packages/edit-site/src/components/media/index.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { useEntityRecord } from '@wordpress/core-data'; + +function Media( { id, size, ...props } ) { + const { record: media } = useEntityRecord( 'root', 'media', id ); + const sizesPerPriority = [ 'large', 'thumbnail' ]; + const currentSize = + size ?? + sizesPerPriority.find( ( s ) => !! media?.media_details?.sizes[ s ] ); + const mediaDetails = media?.media_details?.sizes[ currentSize ]; + + if ( ! mediaDetails ) { + return null; + } + + return ( + + ); +} + +export default Media; diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index ec27265302748..e34e4cbac5be3 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -18,6 +18,7 @@ import Page from '../page'; import Link from '../routes/link'; import { DataViews } from '../dataviews'; import useTrashPostAction from '../actions/trash-post'; +import Media from '../media'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -34,7 +35,7 @@ export default function PagePages() { }, // All fields are visible by default, so it's // better to keep track of the hidden ones. - hiddenFields: [ 'date' ], + hiddenFields: [ 'date', 'featured-image' ], } ); // Request post statuses to get the proper labels. const { records: statuses } = useEntityRecords( 'root', 'status' ); @@ -75,6 +76,20 @@ export default function PagePages() { const fields = useMemo( () => [ + { + id: 'featured-image', + header: __( 'Featured Image' ), + accessorFn: ( page ) => page.featured_media, + cell: ( props ) => + !! props.row.original.featured_media ? ( + + ) : null, + enableSorting: false, + }, { header: __( 'Title' ), id: 'title', @@ -116,7 +131,7 @@ export default function PagePages() { }, }, { - header: 'Status', + header: __( 'Status' ), id: 'status', accessorFn: ( page ) => postStatuses[ page.status ] ?? page.status, diff --git a/packages/edit-site/src/components/page-pages/style.scss b/packages/edit-site/src/components/page-pages/style.scss new file mode 100644 index 0000000000000..82e124b3ac4fe --- /dev/null +++ b/packages/edit-site/src/components/page-pages/style.scss @@ -0,0 +1,4 @@ +.edit-site-page-pages__featured-image { + border-radius: $radius-block-ui; + max-height: 60px; +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index e95cd3571c419..dadbf48d06e64 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -11,6 +11,7 @@ @import "./components/header-edit-mode/document-actions/style.scss"; @import "./components/list/style.scss"; @import "./components/page/style.scss"; +@import "./components/page-pages/style.scss"; @import "./components/page-patterns/style.scss"; @import "./components/table/style.scss"; @import "./components/sidebar-edit-mode/style.scss"; From bab057e96f30f8e2284feec137de88e300a8e0aa Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 15:55:53 +0100 Subject: [PATCH 21/32] Update: Unset variable set by reference after a foreach loop. (#55261) --- lib/class-wp-theme-json-gutenberg.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 3aa07158df853..8c2857fa89d0c 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1065,6 +1065,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' foreach ( $style_nodes as &$node ) { $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] ); } + unset( $node ); } if ( ! empty( $options['root_selector'] ) ) { From 31d16369947199fd806e37ca0667b9ec8c38dc9c Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 15:56:19 +0100 Subject: [PATCH 22/32] Fix: Use y-webrtc room name terminology instead of docName. (#55260) --- packages/sync/src/connect-indexdb.js | 4 ++-- packages/sync/src/connect-webrtc.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sync/src/connect-indexdb.js b/packages/sync/src/connect-indexdb.js index ee56a463fd995..5523640408f57 100644 --- a/packages/sync/src/connect-indexdb.js +++ b/packages/sync/src/connect-indexdb.js @@ -20,8 +20,8 @@ import { IndexeddbPersistence } from 'y-indexeddb'; * @return {Promise<() => void>} Promise that resolves when the connection is established. */ export function connectIndexDb( objectId, objectType, doc ) { - const docName = `${ objectType }-${ objectId }`; - const provider = new IndexeddbPersistence( docName, doc ); + const roomName = `${ objectType }-${ objectId }`; + const provider = new IndexeddbPersistence( roomName, doc ); return new Promise( ( resolve ) => { provider.on( 'synced', () => { diff --git a/packages/sync/src/connect-webrtc.js b/packages/sync/src/connect-webrtc.js index 867bba39d6892..fefe3fddbb8a5 100644 --- a/packages/sync/src/connect-webrtc.js +++ b/packages/sync/src/connect-webrtc.js @@ -18,8 +18,8 @@ import { WebrtcProvider } from 'y-webrtc'; * @return {Promise<() => void>} Promise that resolves when the connection is established. */ export function connectWebRTC( objectId, objectType, doc ) { - const docName = `${ objectType }-${ objectId }`; - new WebrtcProvider( docName, doc, { + const roomName = `${ objectType }-${ objectId }`; + new WebrtcProvider( roomName, doc, { // @ts-ignore password: window.__experimentalCollaborativeEditingSecret, } ); From bdfb93e6db4334f0022acc512fc2c52bfe6d27ff Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 11 Oct 2023 18:02:46 +0300 Subject: [PATCH 23/32] Add changelog entry for #54415 (#55201) * Add changelog entry for #54415 * Move changelog to components --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b3c01c4db2c70..addb5a4d9ec32 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- Allow using CSS level 4 viewport-relative units ([54415](https://github.com/WordPress/gutenberg/pull/54415)) - `ToolsPanel`: do not apply the `className` to prop to `ToolsPanelItem` components when rendered as placeholders ([#55207](https://github.com/WordPress/gutenberg/pull/55207)). - `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). From c04dadbeb7c6d5f6a6d34536cac0c7cf39b403fe Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 16:33:51 +0100 Subject: [PATCH 24/32] Chore: Fix: Remove third parameter passed to shouldDismissPastedFiles which only receives 2. (#55262) --- packages/block-editor/src/utils/pasting.js | 5 +-- .../block-editor/src/utils/test/pasting.js | 31 +++++++------------ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/utils/pasting.js b/packages/block-editor/src/utils/pasting.js index f9612aad20f14..3ce7c20083269 100644 --- a/packages/block-editor/src/utils/pasting.js +++ b/packages/block-editor/src/utils/pasting.js @@ -77,10 +77,7 @@ export function getPasteEventData( { clipboardData } ) { const files = getFilesFromDataTransfer( clipboardData ); - if ( - files.length && - ! shouldDismissPastedFiles( files, html, plainText ) - ) { + if ( files.length && ! shouldDismissPastedFiles( files, html ) ) { return { files }; } diff --git a/packages/block-editor/src/utils/test/pasting.js b/packages/block-editor/src/utils/test/pasting.js index 7cebac9be6692..2c9dc8654a895 100644 --- a/packages/block-editor/src/utils/test/pasting.js +++ b/packages/block-editor/src/utils/test/pasting.js @@ -11,20 +11,19 @@ const mocks = { describe( 'shouldDismissPastedFiles', () => { it( 'should return false when no HTML is present', () => { - expect( - shouldDismissPastedFiles( [ mocks.pngImageFile ], '', '' ) - ).toBe( false ); + expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], '' ) ).toBe( + false + ); } ); it( 'should return false when file is not an image', () => { - expect( - shouldDismissPastedFiles( [ mocks.documentFile ], '', '' ) - ).toBe( false ); + expect( shouldDismissPastedFiles( [ mocks.documentFile ], '' ) ).toBe( + false + ); } ); it( 'should return false when multiple images are present', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile, mocks.jpgImageFile ], - '', '' ) ).toBe( false ); @@ -33,8 +32,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( false ); } ); @@ -42,8 +40,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( true ); } ); @@ -56,8 +53,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - 'https://lh3.googleusercontent.com/ab/SOMESTRING?authuser=0' + '' ) ).toBe( false ); } ); @@ -66,8 +62,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( false ); } ); @@ -76,8 +71,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - 'Some table text', - 'Some table text' + 'Some table text' ) ).toBe( true ); } ); @@ -86,8 +80,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - 'AB', - 'A\nB' + 'AB' ) ).toBe( true ); } ); From c42302313185c983a4550a7723e3d90f05bc7a30 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:53:48 +0300 Subject: [PATCH 25/32] Writing flow: fix selecting synced pattern (#55221) --- .../components/writing-flow/use-arrow-nav.js | 4 ++++ .../specs/editor/various/writing-flow.spec.js | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js index 02bff32eaefa3..44051b324ff64 100644 --- a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js @@ -114,6 +114,10 @@ export function getClosestTabbable( } function isTabCandidate( node ) { + if ( node.closest( '[inert]' ) ) { + return; + } + // Skip if there's only one child that is content editable (and thus a // better candidate). if ( diff --git a/test/e2e/specs/editor/various/writing-flow.spec.js b/test/e2e/specs/editor/various/writing-flow.spec.js index 98bb00a596f03..a772bd91276c2 100644 --- a/test/e2e/specs/editor/various/writing-flow.spec.js +++ b/test/e2e/specs/editor/various/writing-flow.spec.js @@ -1116,6 +1116,29 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { ) ).toHaveText( /^.a+$/ ); } ); + + test( 'should select synced pattern', async ( { page, editor } ) => { + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'synced' ); + + await editor.clickBlockOptionsMenuItem( 'Create pattern' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.type( 'test' ); + await page.keyboard.press( 'Enter' ); + + await expect( + editor.canvas.locator( '[data-type="core/block"]' ) + ).toBeFocused(); + + await editor.insertBlock( { name: 'core/paragraph' } ); + + await page.keyboard.press( 'ArrowUp' ); + + await expect( + editor.canvas.locator( '[data-type="core/block"]' ) + ).toBeFocused(); + } ); } ); class WritingFlowUtils { From 9087e3dc8381fcb83e666d54595fc3a3e2ac1f85 Mon Sep 17 00:00:00 2001 From: Artemio Morales Date: Wed, 11 Oct 2023 13:36:10 -0500 Subject: [PATCH 26/32] Image: Stop crashing with Lightbox on image blocks without an image (#55269) * Stop crashing with Lightbox on image blocks without an image * Fix PHPCS error --- packages/block-library/src/image/index.php | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 4213350ab05c8..87e17a4c136b4 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -16,11 +16,13 @@ * @return string The block content with the data-id attribute added. */ function render_block_core_image( $attributes, $content, $block ) { + if ( false === stripos( $content, 'next_tag( 'img' ); - if ( $processor->get_attribute( 'src' ) === null ) { + if ( ! $processor->next_tag( 'img' ) || null === $processor->get_attribute( 'src' ) ) { return ''; } @@ -125,11 +127,28 @@ function block_core_image_get_lightbox_settings( $block ) { * @return string Filtered block content. */ function block_core_image_render_lightbox( $block_content, $block ) { + /* + * If it's not possible that an IMG element exists then return the given + * block content as-is. It may be that there's no actual image in the block + * or it could be that another plugin already modified this HTML. + */ + if ( false === stripos( $block_content, 'next_tag( 'img' ); + /* + * If there's definitely no IMG element in the block then return the given + * block content as-is. There's nothing that this code can knowingly modify + * to add the lightbox behavior. + */ + if ( ! $processor->next_tag( 'img' ) ) { + return $block_content; + } + $alt_attribute = $processor->get_attribute( 'alt' ); // An empty alt attribute `alt=""` is valid for decorative images. From a3bde627aa4219c0b6a4ae67644bd9f79079115c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 11 Oct 2023 18:55:41 +0000 Subject: [PATCH 27/32] Bump plugin version to 16.8.0 --- 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 1bfcb11db361b..f2ae747fd9e20 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: 16.8.0-rc.2 + * Version: 16.8.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index c457a01b4b74b..557adb678c325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index cf6ce78f22e7f..9f014a3cfbae0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 5cf349583aa62424fedf213f1e3b5c3e12a90960 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 11 Oct 2023 19:15:21 +0000 Subject: [PATCH 28/32] Update Changelog for 16.8.0 --- changelog.txt | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) diff --git a/changelog.txt b/changelog.txt index 1b7d1150efdaf..801ea6d95cd5e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ == Changelog == += 16.8.0 = + = 16.8.0-rc.2 = ## Changelog @@ -21,6 +23,294 @@ The following contributors merged PRs in this release: @fullofcaffeine @torounit += 16.8.0-rc.1 = + +## Changelog + +### Features + +#### Block Editor +- Adds 'nofollow' setting to Button block. ([54110](https://github.com/WordPress/gutenberg/pull/54110)) + +#### Site Editor +- Add 'Show template' toggle when editing pages. ([52674](https://github.com/WordPress/gutenberg/pull/52674)) + + +### Enhancements + +- Update pattern import menu item. ([54782](https://github.com/WordPress/gutenberg/pull/54782)) + +#### Components +- Adding label/description to `BlockEditor/DuotoneControl`. ([54473](https://github.com/WordPress/gutenberg/pull/54473)) +- Deprecating `isPressed` in `Button` component. ([54740](https://github.com/WordPress/gutenberg/pull/54740)) +- Follow ariakit best practices. ([54696](https://github.com/WordPress/gutenberg/pull/54696)) +- InputControl-based components: Add opt-in prop for next 40px default size. ([53819](https://github.com/WordPress/gutenberg/pull/53819)) +- Modal: Add `contentWidth` prop to support a selection of preset modal sizes. ([54471](https://github.com/WordPress/gutenberg/pull/54471)) +- Remove unused components from `ui/`. ([54573](https://github.com/WordPress/gutenberg/pull/54573)) +- Update ariakit to 0.3.3. ([54818](https://github.com/WordPress/gutenberg/pull/54818)) +- Update compact search control metrics. ([54663](https://github.com/WordPress/gutenberg/pull/54663)) +- Wrapped `TextareaControl` in a `forwardRef` call. ([54975](https://github.com/WordPress/gutenberg/pull/54975)) + +#### Block Library +- Add a brief description to the Footnotes block. ([54613](https://github.com/WordPress/gutenberg/pull/54613)) +- Footnotes: Use core’s meta revisioning if available. ([52988](https://github.com/WordPress/gutenberg/pull/52988)) +- Login/out: Add spacing support. ([45147](https://github.com/WordPress/gutenberg/pull/45147)) +- Query view.js: Code quality. ([54982](https://github.com/WordPress/gutenberg/pull/54982)) +- Set custom color when applying initial background image. ([54054](https://github.com/WordPress/gutenberg/pull/54054)) +- Use `wp_get_inline_script_tag()` in `build_dropdown_script_block_core_categories()`. ([54637](https://github.com/WordPress/gutenberg/pull/54637)) + +#### Block Editor +- Default suggested links to pages. ([54622](https://github.com/WordPress/gutenberg/pull/54622)) +- Remove base URL from link control search results. ([54553](https://github.com/WordPress/gutenberg/pull/54553)) +- Simplify `BlockHTMLConvertButton`. ([54972](https://github.com/WordPress/gutenberg/pull/54972)) +- Update strings in blocks 'RenameModal' component. ([54887](https://github.com/WordPress/gutenberg/pull/54887)) + +#### Post Editor +- Edit Post: Use hooks instead of HoCs in 'PostStatus' components. ([54951](https://github.com/WordPress/gutenberg/pull/54951)) +- Editor: Use hooks instead of HoCs in 'PostSticky' components. ([54949](https://github.com/WordPress/gutenberg/pull/54949)) +- Editor: Use hooks instead of HoCs in 'PostSwitchToDraftButton'. ([54695](https://github.com/WordPress/gutenberg/pull/54695)) +- Show confirmation dialog when moving a post to the trash. ([50219](https://github.com/WordPress/gutenberg/pull/50219)) + +#### Site Editor +- Add template replace flow to template inspector. ([54609](https://github.com/WordPress/gutenberg/pull/54609)) +- [Site Editor]: Update copy of using the default template in a page. ([54728](https://github.com/WordPress/gutenberg/pull/54728)) + +#### Patterns +- Remove category description in inserter panel. ([54894](https://github.com/WordPress/gutenberg/pull/54894)) + +#### Typography +- Font Library: Refactor endpoint permissions. ([54829](https://github.com/WordPress/gutenberg/pull/54829)) + + +### Bug Fixes + +- Fix the ShortcutProvider usage. ([54851](https://github.com/WordPress/gutenberg/pull/54851)) +- Fix warning when a template calls a template area twice. ([54861](https://github.com/WordPress/gutenberg/pull/54861)) +- Revert "Fix warning when a template calls a template area twice". ([54926](https://github.com/WordPress/gutenberg/pull/54926)) + +#### Block Library +- All Nav block items to break long titles. ([54866](https://github.com/WordPress/gutenberg/pull/54866)) +- Fallback to Twitter provider when embedding X URLs. ([54876](https://github.com/WordPress/gutenberg/pull/54876)) +- Fix Deleted Navigation Menu warning string. ([55033](https://github.com/WordPress/gutenberg/pull/55033)) +- Fix Search Block not updating in Nav block. ([54823](https://github.com/WordPress/gutenberg/pull/54823)) +- Fix left and right aligmnent in children of Post Template. ([54997](https://github.com/WordPress/gutenberg/pull/54997)) +- Fix output of Navigation block classnames in the editor. ([54992](https://github.com/WordPress/gutenberg/pull/54992)) +- Fix overwriting of published post meta when previewing footnote changes. ([54339](https://github.com/WordPress/gutenberg/pull/54339)) +- Image: Ensure Expand on Click toggle is shown if block-level lightbox setting exists. ([54878](https://github.com/WordPress/gutenberg/pull/54878)) +- Image: Fix layout shift when lightbox is opened and closed. ([53026](https://github.com/WordPress/gutenberg/pull/53026)) +- Media & Text: Fix React warning. ([55038](https://github.com/WordPress/gutenberg/pull/55038)) +- Search block: Allow space for input field only when form expanded. ([54846](https://github.com/WordPress/gutenberg/pull/54846)) +- Search block: Update alignment and icon button width. ([54773](https://github.com/WordPress/gutenberg/pull/54773)) + +#### Site Editor +- Avoid same key warnings in template parts area listings. ([54863](https://github.com/WordPress/gutenberg/pull/54863)) +- Avoid stale navigation block values when parsing entity record. ([54996](https://github.com/WordPress/gutenberg/pull/54996)) +- Don't display the navigation section in template parts details when a menu is missing. ([54993](https://github.com/WordPress/gutenberg/pull/54993)) +- Fix ToolSelector popover variant. ([54840](https://github.com/WordPress/gutenberg/pull/54840)) +- Reset 'Show template' toggle when leaving edit mode. ([54679](https://github.com/WordPress/gutenberg/pull/54679)) +- remove `overflow: Hidden` from the entity title in the site editor sidebar. ([54769](https://github.com/WordPress/gutenberg/pull/54769)) + +#### Components +- FormTokenField: Add `box-sizing` reset style and reset default padding. ([54734](https://github.com/WordPress/gutenberg/pull/54734)) +- Popover: Fix the styles for components that use emotion within popovers. ([54912](https://github.com/WordPress/gutenberg/pull/54912)) +- Remove hover style for secondary Button when aria-disabled is set. ([54978](https://github.com/WordPress/gutenberg/pull/54978)) +- Reverting addition of `aria-selected` style hook in `Button`. ([54931](https://github.com/WordPress/gutenberg/pull/54931)) +- `SlotFill`: Pass `Component` instance to unregisterSlot. ([54765](https://github.com/WordPress/gutenberg/pull/54765)) + +#### Block Editor +- Avoid double-wrapping selectors when transforming the styles. ([54981](https://github.com/WordPress/gutenberg/pull/54981)) +- [Inserter]: Fix reset of registered media categories. ([55012](https://github.com/WordPress/gutenberg/pull/55012)) + +#### Typography +- Font Library: Changed the OTF mime type expected value to be what PHP returns. ([54886](https://github.com/WordPress/gutenberg/pull/54886)) +- Font Library: Move font uploads to a new tab. ([54655](https://github.com/WordPress/gutenberg/pull/54655)) + +#### Global Styles +- Block custom CSS: Fix incorrect CSS when multiple root selectors. ([53602](https://github.com/WordPress/gutenberg/pull/53602)) +- Image: Ensure `false` values are preserved in memory when defined in `theme.json`. ([54639](https://github.com/WordPress/gutenberg/pull/54639)) + +#### List View +- Fix performance issue when selecting all blocks. ([54900](https://github.com/WordPress/gutenberg/pull/54900)) + +#### Colors +- Format Library: Try to fix highlight popover jumping. ([54736](https://github.com/WordPress/gutenberg/pull/54736)) + +#### Interactivity API +- Image: Fix duotone not being applied to lightbox image. ([54670](https://github.com/WordPress/gutenberg/pull/54670)) + + +### Accessibility + +#### Block Library +- Footnotes: Add aria-label to return links. ([54843](https://github.com/WordPress/gutenberg/pull/54843)) +- Table of contents block accessibility improvements. ([54322](https://github.com/WordPress/gutenberg/pull/54322)) + +#### Components +- HTML block: Fix accessibility issues on back-end. ([54408](https://github.com/WordPress/gutenberg/pull/54408)) +- `Modal`: Accessibly hide/show outer modal when nested. ([54743](https://github.com/WordPress/gutenberg/pull/54743)) + +#### Patterns +- Use list role instead of listbox in patterns list. ([54884](https://github.com/WordPress/gutenberg/pull/54884)) + +#### Post Editor +- Editor: Always render the 'Switch to Draft' button to avoid focus loss. ([54722](https://github.com/WordPress/gutenberg/pull/54722)) + +#### Block Editor +- Block Switcher: Use a different label for multi-selection. ([54692](https://github.com/WordPress/gutenberg/pull/54692)) + + +### Performance + +- Tests: Support the Site Editor's legacy spinner. ([54784](https://github.com/WordPress/gutenberg/pull/54784)) +- Use instanceOf over property_exists. ([54835](https://github.com/WordPress/gutenberg/pull/54835)) + +#### Block Editor +- Subscribe only to block editor store in `useBlockSync`. ([55041](https://github.com/WordPress/gutenberg/pull/55041)) + + +### Experiments + +#### Site Editor +- al]: First version of pages list in site editor. ([54966](https://github.com/WordPress/gutenberg/pull/54966)) + +#### Block Editor +- Expose `getDuotoneFilter()` as private API. ([54905](https://github.com/WordPress/gutenberg/pull/54905)) + + +### Documentation + +- Add a documentation page about the block editor settings. ([54870](https://github.com/WordPress/gutenberg/pull/54870)) +- Add a page about the format library to the platform documentation site. ([55037](https://github.com/WordPress/gutenberg/pull/55037)) +- Docs: Add a callout to the `wp-now` documentation to mention it's still experimental. ([55044](https://github.com/WordPress/gutenberg/pull/55044)) +- Docs: Remove outdated info. ([54707](https://github.com/WordPress/gutenberg/pull/54707)) +- Docs: Remove the Full Site Editing doc. ([54516](https://github.com/WordPress/gutenberg/pull/54516)) +- Docs: Rename Block Hooks handbook page to Block Filters. ([54862](https://github.com/WordPress/gutenberg/pull/54862)) +- Document the current state of the Real-Time collaboration experiment. ([54932](https://github.com/WordPress/gutenberg/pull/54932)) +- Fix a broken MD link in callout. ([54772](https://github.com/WordPress/gutenberg/pull/54772)) +- Platform Docs: Add a documentation page explaining how to use the block library. ([54967](https://github.com/WordPress/gutenberg/pull/54967)) +- Update the documentation of the block editor and replace @wordpress/element with react. ([54908](https://github.com/WordPress/gutenberg/pull/54908)) +- Update versions in WP for 6.4. ([54890](https://github.com/WordPress/gutenberg/pull/54890)) + + +### Code Quality + +- Add a unit test for the "ValidBlockLibraryFunctionNameSniff" sniff. ([53928](https://github.com/WordPress/gutenberg/pull/53928)) +- Move dependencies to the right place. ([54597](https://github.com/WordPress/gutenberg/pull/54597)) +- Move mime-type collection generation to a function that can be tested…. ([54844](https://github.com/WordPress/gutenberg/pull/54844)) +- Post Title block should use esc_url(). ([53981](https://github.com/WordPress/gutenberg/pull/53981)) +- Rich text: Use getPasteEventData. ([55048](https://github.com/WordPress/gutenberg/pull/55048)) +- Writing flow: Absorb clipboard handler. ([55006](https://github.com/WordPress/gutenberg/pull/55006)) + +#### Block Library +- Footnotes: Avoid regexes in entity provider. ([54505](https://github.com/WordPress/gutenberg/pull/54505)) +- Image Block: Fix browser console error when clicking "Expand on Click". ([54938](https://github.com/WordPress/gutenberg/pull/54938)) +- Removed unwanted space from the string. ([54654](https://github.com/WordPress/gutenberg/pull/54654)) +- Update CODEOWNERS for `core/image` block. ([54793](https://github.com/WordPress/gutenberg/pull/54793)) + +#### Patterns +- Add a new spec for for adding an unsynced pattern. ([54892](https://github.com/WordPress/gutenberg/pull/54892)) +- Add end-to-end tests for filtering and searching patterns. ([54906](https://github.com/WordPress/gutenberg/pull/54906)) +- Add new end-to-end test for creating a pattern. ([54855](https://github.com/WordPress/gutenberg/pull/54855)) +- Include pattern category in main end-to-end critical path test. ([54923](https://github.com/WordPress/gutenberg/pull/54923)) + +#### Components +- Consolidate utils to remove `ui/`. ([54922](https://github.com/WordPress/gutenberg/pull/54922)) +- Move `ContextSystemProvider` out of `/ui`. ([54847](https://github.com/WordPress/gutenberg/pull/54847)) +- SlotFill: Migrate to Typescript. ([51350](https://github.com/WordPress/gutenberg/pull/51350)) +- Tidying `CircularOptionPicker.Option`. ([54903](https://github.com/WordPress/gutenberg/pull/54903)) + +#### Typography +- Font Library: Syntax refactor repace strpos with str_contains. ([54832](https://github.com/WordPress/gutenberg/pull/54832)) +- Font Library: Use snake_case instead of camelCase on fontFamilies endpoint param. ([54977](https://github.com/WordPress/gutenberg/pull/54977)) + +#### Block Editor +- Rich text: Avoid shortcode logic, adjust paste handler instead. ([55052](https://github.com/WordPress/gutenberg/pull/55052)) + +#### Plugin +- Remove legacy logic for '__unstableResolvedAssets' setting. ([54812](https://github.com/WordPress/gutenberg/pull/54812)) + +#### Data Layer +- createResolversCacheMiddleware: Remove dependency on core/data store. ([54733](https://github.com/WordPress/gutenberg/pull/54733)) + +#### Site Editor +- Use constants rather than hard coded template strings (round 3). ([54705](https://github.com/WordPress/gutenberg/pull/54705)) + + +### Tools + +- Label enforcer workflow: Make accessibility a focus instead of a type. ([54941](https://github.com/WordPress/gutenberg/pull/54941)) +- Scripts: Update webpack and related dependencies to the latest version. ([54657](https://github.com/WordPress/gutenberg/pull/54657)) +- Update changelog automation and test fixtures to match the last a11y label renaming. ([54974](https://github.com/WordPress/gutenberg/pull/54974)) + +#### Testing +- Don’t use TypeScript files in scripts package. ([54856](https://github.com/WordPress/gutenberg/pull/54856)) +- ESLint: Update eslint-plugin-testing-library to v6. ([54910](https://github.com/WordPress/gutenberg/pull/54910)) +- Fix end-to-end test: ”WP Editor Meta Boxes > Should save the changes”. ([51884](https://github.com/WordPress/gutenberg/pull/51884)) +- Font Library: Avoid deprected error in test. ([54802](https://github.com/WordPress/gutenberg/pull/54802)) +- Make `editor.getBlocks` to return only testing-related properties. ([54901](https://github.com/WordPress/gutenberg/pull/54901)) +- Migrate 'Global styles sidebar' test to Playwright. ([55045](https://github.com/WordPress/gutenberg/pull/55045)) +- Migrate 'iframed block editor settings styles' tests to Playwright. ([55014](https://github.com/WordPress/gutenberg/pull/55014)) +- Migrate 'iframed inline styles' tests to Playwright. ([55009](https://github.com/WordPress/gutenberg/pull/55009)) +- Migrate 'iframed masonry block' tests to Playwright. ([55016](https://github.com/WordPress/gutenberg/pull/55016)) +- Migrate 'iframed multiple block stylesheets' tests to Playwright. ([55003](https://github.com/WordPress/gutenberg/pull/55003)) +- Migrate keyboard-navigable-blocks end-to-end tests from puppeteer to playwright. ([54944](https://github.com/WordPress/gutenberg/pull/54944)) +- Scripts: Properly use CommonJS for default Playwright configuration. ([54988](https://github.com/WordPress/gutenberg/pull/54988)) +- Try fixing the flaky 'Toolbar roving tabindex' end-to-end test. ([54785](https://github.com/WordPress/gutenberg/pull/54785)) +- end-to-end Tests: Revert temporary fixes. ([54865](https://github.com/WordPress/gutenberg/pull/54865)) +- end-to-end Utils: Allow overriding username/password. ([53267](https://github.com/WordPress/gutenberg/pull/53267)) + +#### Build Tooling +- Add some @types packages as proper dependencies. ([50231](https://github.com/WordPress/gutenberg/pull/50231)) +- Update the default JSX pragma to React instead of @wordpress/element. ([54494](https://github.com/WordPress/gutenberg/pull/54494)) +- Upgrade wp-prettier to v3.0.3 (final). ([54775](https://github.com/WordPress/gutenberg/pull/54775)) + + +### Security + +#### Data Layer +- Replace turbo-combine-reducers with combineReducers from Redux. ([54606](https://github.com/WordPress/gutenberg/pull/54606)) + + +### Various + +- (chore) Revert the 16.7 RC2 release in order to release it again due to wrong changelog. ([54744](https://github.com/WordPress/gutenberg/pull/54744)) + +#### Design Tools +- Background image block support: Add tests, adjust injection logic slightly. ([54489](https://github.com/WordPress/gutenberg/pull/54489)) +- Background support: Backport fix for undefined array key. ([54850](https://github.com/WordPress/gutenberg/pull/54850)) + +#### Typography +- Revert "Font Library: Avoid rendering font library ui outisde gutenberg plugin". ([54947](https://github.com/WordPress/gutenberg/pull/54947)) + +#### Commands +- Make the reset styles command consistent. ([54841](https://github.com/WordPress/gutenberg/pull/54841)) + +#### Patterns +- Use "Not synced" in place of "Standard" nomenclature for patterns. ([54839](https://github.com/WordPress/gutenberg/pull/54839)) + +#### Block Editor +- Simplify BlockPatternsSyncFilter with clearer labels and additional context. ([54838](https://github.com/WordPress/gutenberg/pull/54838)) + +#### Site Editor +- Use consistent capitalization for template parts in Site Editor constants. ([54709](https://github.com/WordPress/gutenberg/pull/54709)) + + +## First time contributors + +The following PRs were merged by first time contributors: + +- @leemyongpakvn: Fix a broken MD link in callout. ([54772](https://github.com/WordPress/gutenberg/pull/54772)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @alexstine @andrewhayward @andrewserong @annezazu @anton-vlasenko @artemiomorales @aurooba @bangank36 @brookewp @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @dcalhoun @derekblank @draganescu @ellatrix @fluiddot @fullofcaffeine @geriux @getdave @glendaviesnz @gziolo @jameskoster @jeryj @jsnajdr @juhi123 @kevin940726 @leemyongpakvn @madhusudhand @MaggieCabrera @Mamaduka @matiasbenedetto @michalczaplinski @mirka @mtias @mujuonly @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ockham @pbking @priethor @ramonjd @richtabor @scruffian @SiobhyB @spacedmonkey @stokesman @swissspidy @t-hamano @tellthemachines @tellyworth @them-es @torounit @tyxla @westonruter @WunderBart @youknowriad + + + + = 16.7.1 = ## Changelog From 9f38ee31ca51887352c540d02b65cd5de69601c2 Mon Sep 17 00:00:00 2001 From: Brooke <35543432+brookewp@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:01:20 -0700 Subject: [PATCH 29/32] url: update `filterURLForDisplay` to include all image, video, and audio file types (#54920) * url: update display filter to include all file types * Restore regex with defined media files with extended list * Add tooltip to LinkPreview and remove from MediaReplaceFlow * Restore regex to display all file urls * Add test to LinkPreview to check for tooltip * Add test for filter to verify newly included formats * Update link control test based on feedback * Combine new test with existing filename test * Update const naming and add comment * Clean up test by replacing with it.each * Simplify regex to a string Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --------- Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --- .../components/link-control/link-preview.js | 16 +++++++--- .../src/components/link-control/test/index.js | 19 ++++++++++++ .../components/media-replace-flow/index.js | 23 ++++++-------- packages/url/src/filter-url-for-display.js | 5 +-- packages/url/src/test/index.js | 31 +++++++++---------- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/components/link-control/link-preview.js b/packages/block-editor/src/components/link-control/link-preview.js index 8272602cde908..04a67d4478994 100644 --- a/packages/block-editor/src/components/link-control/link-preview.js +++ b/packages/block-editor/src/components/link-control/link-preview.js @@ -11,6 +11,7 @@ import { Button, ExternalLink, __experimentalText as Text, + Tooltip, } from '@wordpress/components'; import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url'; import { Icon, globe, info, linkOff, edit } from '@wordpress/icons'; @@ -87,12 +88,17 @@ export default function LinkPreview( { { ! isEmptyURL ? ( <> - - { displayTitle } - + + { displayTitle } + + { value?.url && displayTitle !== displayURL && ( diff --git a/packages/block-editor/src/components/link-control/test/index.js b/packages/block-editor/src/components/link-control/test/index.js index 5c44f0295249c..e0366a3f27ef5 100644 --- a/packages/block-editor/src/components/link-control/test/index.js +++ b/packages/block-editor/src/components/link-control/test/index.js @@ -2056,6 +2056,25 @@ describe( 'Addition Settings UI', () => { } ) ); } ); + + it( 'should show tooltip with full URL alongside filtered display', async () => { + const user = userEvent.setup(); + const url = + 'http://www.wordpress.org/wp-content/uploads/a-document.pdf'; + render( ); + + const link = screen.getByRole( 'link' ); + + expect( link ).toHaveTextContent( 'a-document.pdf' ); + + await user.hover( link ); + + expect( await screen.findByRole( 'tooltip' ) ).toHaveTextContent( url ); + + await user.unhover( link ); + + expect( screen.queryByRole( 'tooltip' ) ).not.toBeInTheDocument(); + } ); } ); describe( 'Post types', () => { diff --git a/packages/block-editor/src/components/media-replace-flow/index.js b/packages/block-editor/src/components/media-replace-flow/index.js index c331761af5852..33419676eaab8 100644 --- a/packages/block-editor/src/components/media-replace-flow/index.js +++ b/packages/block-editor/src/components/media-replace-flow/index.js @@ -16,7 +16,6 @@ import { ToolbarButton, Dropdown, withFilters, - Tooltip, } from '@wordpress/components'; import { useSelect, withDispatch } from '@wordpress/data'; import { DOWN } from '@wordpress/keycodes'; @@ -220,19 +219,15 @@ const MediaReplaceFlow = ( { { __( 'Current media URL:' ) } - - - { - onSelectURL( url ); - editMediaButtonRef.current.focus(); - } } - /> - - + { + onSelectURL( url ); + editMediaButtonRef.current.focus(); + } } + /> ) } > diff --git a/packages/url/src/filter-url-for-display.js b/packages/url/src/filter-url-for-display.js index 2d3247e6d1da9..eede264e8e801 100644 --- a/packages/url/src/filter-url-for-display.js +++ b/packages/url/src/filter-url-for-display.js @@ -21,12 +21,13 @@ export function filterURLForDisplay( url, maxLength = null ) { filteredURL = filteredURL.replace( '/', '' ); } - const mediaRegexp = /([\w|:])*\.(?:jpg|jpeg|gif|png|svg)/; + // capture file name from URL + const fileRegexp = /\/([^\/?]+)\.(?:[\w]+)(?=\?|$)/; if ( ! maxLength || filteredURL.length <= maxLength || - ! filteredURL.match( mediaRegexp ) + ! filteredURL.match( fileRegexp ) ) { return filteredURL; } diff --git a/packages/url/src/test/index.js b/packages/url/src/test/index.js index 9aa53dca512df..e258e112b2987 100644 --- a/packages/url/src/test/index.js +++ b/packages/url/src/test/index.js @@ -254,23 +254,20 @@ describe( 'isValidPath', () => { } ); describe( 'getFilename', () => { - it( 'returns the filename part of the URL', () => { - expect( getFilename( 'https://wordpress.org/image.jpg' ) ).toBe( - 'image.jpg' - ); - expect( - getFilename( 'https://wordpress.org/image.jpg?query=test' ) - ).toBe( 'image.jpg' ); - expect( getFilename( 'https://wordpress.org/image.jpg#anchor' ) ).toBe( - 'image.jpg' - ); - expect( - getFilename( 'http://localhost:8080/a/path/to/an/image.jpg' ) - ).toBe( 'image.jpg' ); - expect( getFilename( '/path/to/an/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( 'path/to/an/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( '/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( 'image.jpg' ) ).toBe( 'image.jpg' ); + it.each( [ + [ 'https://wordpress.org/image.jpg', 'image.jpg' ], + [ 'https://wordpress.org/image.jpg?query=test', 'image.jpg' ], + [ 'https://wordpress.org/image.jpg#anchor', 'image.jpg' ], + [ 'http://localhost:8080/a/path/to/an/image.jpg', 'image.jpg' ], + [ '/path/to/an/image.jpg', 'image.jpg' ], + [ 'path/to/an/image.jpg', 'image.jpg' ], + [ '/image.jpg', 'image.jpg' ], + [ 'https://wordpress.org/file.pdf', 'file.pdf' ], + [ 'https://wordpress.org/image.webp?query=test', 'image.webp' ], + [ 'https://wordpress.org/video.mov#anchor', 'video.mov' ], + [ 'http://localhost:8080/a/path/to/audio.mp3', 'audio.mp3' ], + ] )( 'returns the filename part of the URL: %s', ( url, filename ) => { + expect( getFilename( url ) ).toBe( filename ); } ); it( 'returns undefined when the provided value does not contain a filename', () => { From c39b35245eb3fe187eb0aed5672d3e4d91906a9a Mon Sep 17 00:00:00 2001 From: Rich Tabor Date: Wed, 11 Oct 2023 17:23:46 -0400 Subject: [PATCH 30/32] Update fullscreen icon (#55021) --- packages/icons/src/library/fullscreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/icons/src/library/fullscreen.js b/packages/icons/src/library/fullscreen.js index 8b11ddcac7217..11bef7aebd612 100644 --- a/packages/icons/src/library/fullscreen.js +++ b/packages/icons/src/library/fullscreen.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const fullscreen = ( - + ); From d84da61d9b35da1329ac70d9ac7d158862813160 Mon Sep 17 00:00:00 2001 From: Brooke <35543432+brookewp@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:01:22 -0700 Subject: [PATCH 31/32] Toolbar: Add unstyled variant (#55139) * Toolbar: Add unstyled variant * Add variants to block editor and remove workarounds * Update stories * Add test for new variant * Update changelog * Memoize toolbar context * Clean up and improve CSS * Add to README and update phrasing * Implement feedback to simplify and optimize * Rename and simplify story by reusing default args --- .../block-tools/block-contextual-toolbar.js | 1 + .../src/components/block-tools/style.scss | 1 - .../src/components/tool-selector/index.js | 2 +- packages/components/CHANGELOG.md | 4 +++ .../src/toolbar/stories/index.story.tsx | 15 +++++++++ .../components/src/toolbar/test/index.tsx | 8 +++++ .../components/src/toolbar/toolbar/README.md | 9 +++++ .../components/src/toolbar/toolbar/index.tsx | 33 ++++++++++++------- .../components/src/toolbar/toolbar/style.scss | 9 +++++ .../components/src/toolbar/toolbar/types.ts | 10 ++++++ .../components/header/header-toolbar/index.js | 1 + .../header/header-toolbar/style.scss | 1 - 12 files changed, 79 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js index 439c3d33a3036..fcec9d56b24a8 100644 --- a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js @@ -188,6 +188,7 @@ function BlockContextualToolbar( { focusOnMount, isFixed, ...props } ) { className={ classes } /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } + variant={ isFixed ? 'unstyled' : undefined } { ...props } > { ! isCollapsed && } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 796c513d6d7c2..2cb2edaf1a9c7 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -109,7 +109,6 @@ overflow-y: hidden; } - border: none; border-bottom: $border-width solid $gray-200; border-radius: 0; diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index a0df14f1a19d9..1e93a18cf6bb9 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -51,7 +51,7 @@ function ToolSelector( props, ref ) { label={ __( 'Tools' ) } /> ) } - popoverProps={ { placement: 'bottom-start', variant: undefined } } + popoverProps={ { placement: 'bottom-start' } } renderContent={ () => ( <> diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index addb5a4d9ec32..d1d87acebaa37 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,10 @@ - `ConfirmDialog`: Migrate to TypeScript. ([#54954](https://github.com/WordPress/gutenberg/pull/54954)). +### New Features + +- `Toolbar`: add new `variant` prop for 'unstyled' option ([#55139](https://github.com/WordPress/gutenberg/pull/55139)). + ## 25.9.0 (2023-10-05) ### Enhancements diff --git a/packages/components/src/toolbar/stories/index.story.tsx b/packages/components/src/toolbar/stories/index.story.tsx index 2eecf54a4a493..e4fb3b07e1c90 100644 --- a/packages/components/src/toolbar/stories/index.story.tsx +++ b/packages/components/src/toolbar/stories/index.story.tsx @@ -52,6 +52,10 @@ const meta: Meta< typeof Toolbar > = { }, argTypes: { children: { control: { type: null } }, + variant: { + options: [ undefined, 'unstyled' ], + control: { type: 'radio' }, + }, }, parameters: { controls: { expanded: true }, @@ -181,3 +185,14 @@ WithoutGroup.args = { > ), }; + +/** + * Set the variant to `unstyled` to remove default border styles. + * Otherwise, leave it as `undefined` for default styles. + */ + +export const Unstyled = Template.bind( {} ); +Unstyled.args = { + ...Default.args, + variant: 'unstyled', +}; diff --git a/packages/components/src/toolbar/test/index.tsx b/packages/components/src/toolbar/test/index.tsx index c9e58edc8a80e..74c58804fc099 100644 --- a/packages/components/src/toolbar/test/index.tsx +++ b/packages/components/src/toolbar/test/index.tsx @@ -25,5 +25,13 @@ describe( 'Toolbar', () => { screen.getByLabelText( 'control2', { selector: 'button' } ) ).toBeInTheDocument(); } ); + + it( 'should apply the unstyled variant correctly via the `variant` prop', () => { + render( ); + + expect( screen.getByRole( 'toolbar' ) ).toHaveClass( + 'is-unstyled' + ); + } ); } ); } ); diff --git a/packages/components/src/toolbar/toolbar/README.md b/packages/components/src/toolbar/toolbar/README.md index 6692d3f63f34e..ee89127ded74f 100644 --- a/packages/components/src/toolbar/toolbar/README.md +++ b/packages/components/src/toolbar/toolbar/README.md @@ -71,6 +71,15 @@ An accessible label for the toolbar. - Required: Yes +#### `variant`: `'unstyled' | undefined` + +Specifies the toolbar's style. + +Leave undefined for the default style. Or `'unstyled'` which removes the border from the toolbar, but keeps the default popover style. + +- Required: No +- Default: `undefined` + ## Related components - Toolbar may contain [ToolbarGroup](/packages/components/src/toolbar-group/README.md), [ToolbarButton](/packages/components/src/toolbar-button/README.md) and [ToolbarItem](/packages/components/src/toolbar-Item/README.md) as children. diff --git a/packages/components/src/toolbar/toolbar/index.tsx b/packages/components/src/toolbar/toolbar/index.tsx index b6e83dcf6da2a..47c49b270afef 100644 --- a/packages/components/src/toolbar/toolbar/index.tsx +++ b/packages/components/src/toolbar/toolbar/index.tsx @@ -7,7 +7,7 @@ import type { ForwardedRef } from 'react'; /** * WordPress dependencies */ -import { forwardRef } from '@wordpress/element'; +import { forwardRef, useMemo } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; /** @@ -19,23 +19,30 @@ import type { ToolbarProps } from './types'; import type { WordPressComponentProps } from '../../context'; import { ContextSystemProvider } from '../../context'; -const CONTEXT_SYSTEM_VALUE = { - DropdownMenu: { - variant: 'toolbar', - }, - Dropdown: { - variant: 'toolbar', - }, -}; - function UnforwardedToolbar( { className, label, + variant, ...props }: WordPressComponentProps< ToolbarProps, 'div', false >, ref: ForwardedRef< any > ) { + const isVariantDefined = variant !== undefined; + const contextSystemValue = useMemo( () => { + if ( isVariantDefined ) { + return {}; + } + return { + DropdownMenu: { + variant: 'toolbar', + }, + Dropdown: { + variant: 'toolbar', + }, + }; + }, [ isVariantDefined ] ); + if ( ! label ) { deprecated( 'Using Toolbar without label prop', { since: '5.6', @@ -55,10 +62,12 @@ function UnforwardedToolbar( // `ToolbarGroup` already uses components-toolbar for compatibility reasons. const finalClassName = classnames( 'components-accessible-toolbar', - className + className, + variant && `is-${ variant }` ); + return ( - + .components-toolbar-group:last-child { border-right: none; } + + &.is-unstyled { + border: none; + + & > .components-toolbar-group { + border-right: none; + } + + } } .components-accessible-toolbar, diff --git a/packages/components/src/toolbar/toolbar/types.ts b/packages/components/src/toolbar/toolbar/types.ts index f6a6b9667ab4b..681f1ab2d1af2 100644 --- a/packages/components/src/toolbar/toolbar/types.ts +++ b/packages/components/src/toolbar/toolbar/types.ts @@ -12,4 +12,14 @@ export type ToolbarProps = { * An accessible label for the toolbar. */ label: string; + /** + * Specifies the toolbar's style. + * + * Leave undefined for the default style. Or `'unstyled'` which + * removes the border from the toolbar, but keeps the default + * popover style. + * + * @default undefined + */ + variant?: 'unstyled' | undefined; }; diff --git a/packages/edit-post/src/components/header/header-toolbar/index.js b/packages/edit-post/src/components/header/header-toolbar/index.js index e814f7a49072f..b86e66af7a849 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.js @@ -136,6 +136,7 @@ function HeaderToolbar( { setListViewToggleElement } ) { className="edit-post-header-toolbar" aria-label={ toolbarAriaLabel } shouldUseKeyboardFocusShortcut={ ! blockToolbarCanBeFocused } + variant="unstyled" > .components-button { From d2bf1366d55f8fad5edeebd521eda29b610d19bc Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:44:33 +1000 Subject: [PATCH 32/32] Patterns: Use modal for pattern duplication flow as workaround for changing sync status (#54764) --- .../create-template-part-modal/index.js | 14 +- .../page-patterns/duplicate-menu-item.js | 278 +++++++----------- .../components/page-patterns/use-patterns.js | 5 + .../src/components/create-pattern-modal.js | 22 +- 4 files changed, 130 insertions(+), 189 deletions(-) diff --git a/packages/edit-site/src/components/create-template-part-modal/index.js b/packages/edit-site/src/components/create-template-part-modal/index.js index 0b3a57e0c0744..31f12b6cab56d 100644 --- a/packages/edit-site/src/components/create-template-part-modal/index.js +++ b/packages/edit-site/src/components/create-template-part-modal/index.js @@ -39,17 +39,21 @@ import { } from '../../utils/template-part-create'; export default function CreateTemplatePartModal( { - closeModal, + defaultArea = TEMPLATE_PART_AREA_DEFAULT_CATEGORY, blocks = [], + confirmLabel = __( 'Create' ), + closeModal, + modalTitle = __( 'Create template part' ), onCreate, onError, + defaultTitle = '', } ) { const { createErrorNotice } = useDispatch( noticesStore ); const { saveEntityRecord } = useDispatch( coreStore ); const existingTemplateParts = useExistingTemplateParts(); - const [ title, setTitle ] = useState( '' ); - const [ area, setArea ] = useState( TEMPLATE_PART_AREA_DEFAULT_CATEGORY ); + const [ title, setTitle ] = useState( defaultTitle ); + const [ area, setArea ] = useState( defaultArea ); const [ isSubmitting, setIsSubmitting ] = useState( false ); const instanceId = useInstanceId( CreateTemplatePartModal ); @@ -104,7 +108,7 @@ export default function CreateTemplatePartModal( { return ( @@ -181,7 +185,7 @@ export default function CreateTemplatePartModal( { aria-disabled={ ! title || isSubmitting } isBusy={ isSubmitting } > - { __( 'Create' ) } + { confirmLabel } diff --git a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js index a882de95bdaeb..a0842cf9002a0 100644 --- a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js @@ -2,10 +2,11 @@ * WordPress dependencies */ import { MenuItem } from '@wordpress/components'; -import { store as coreStore } from '@wordpress/core-data'; import { useDispatch } from '@wordpress/data'; +import { useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -13,206 +14,131 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; */ import { TEMPLATE_PART_POST_TYPE, - PATTERN_TYPES, PATTERN_SYNC_TYPES, + PATTERN_TYPES, } from '../../utils/constants'; -import { - useExistingTemplateParts, - getUniqueTemplatePartTitle, - getCleanTemplatePartSlug, -} from '../../utils/template-part-create'; import { unlock } from '../../lock-unlock'; -import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories'; +import CreateTemplatePartModal from '../create-template-part-modal'; +const { CreatePatternModal } = unlock( patternsPrivateApis ); const { useHistory } = unlock( routerPrivateApis ); -function getPatternMeta( item ) { - if ( item.type === PATTERN_TYPES.theme ) { - return { wp_pattern_sync_status: PATTERN_SYNC_TYPES.unsynced }; - } - - const syncStatus = item.patternBlock.wp_pattern_sync_status; - const isUnsynced = syncStatus === PATTERN_SYNC_TYPES.unsynced; - - return { - ...item.patternBlock.meta, - wp_pattern_sync_status: isUnsynced ? syncStatus : undefined, - }; -} - export default function DuplicateMenuItem( { categoryId, item, label = __( 'Duplicate' ), onClose, } ) { - const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore ); - const { createErrorNotice, createSuccessNotice } = - useDispatch( noticesStore ); - + const { createSuccessNotice } = useDispatch( noticesStore ); + const [ isModalOpen, setIsModalOpen ] = useState( false ); const history = useHistory(); - const existingTemplateParts = useExistingTemplateParts(); - const { patternCategories } = usePatternCategories(); - async function createTemplatePart() { - try { - const copiedTitle = sprintf( - /* translators: %s: Existing template part title */ - __( '%s (Copy)' ), - item.title - ); - const title = getUniqueTemplatePartTitle( - copiedTitle, - existingTemplateParts - ); - const slug = getCleanTemplatePartSlug( title ); - const { area, content } = item.templatePart; - - const result = await saveEntityRecord( - 'postType', - TEMPLATE_PART_POST_TYPE, - { slug, title, content, area }, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: The new template part's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), - item.title - ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - - history.push( { - postType: TEMPLATE_PART_POST_TYPE, - postId: result?.id, - categoryType: TEMPLATE_PART_POST_TYPE, - categoryId, - } ); + const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - onClose(); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( - 'An error occurred while creating the template part.' - ); - - createErrorNotice( errorMessage, { + async function onTemplatePartSuccess( templatePart ) { + createSuccessNotice( + sprintf( + // translators: %s: The new template part's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + item.title + ), + { type: 'snackbar', - id: 'edit-site-patterns-error', - } ); - onClose(); - } - } - - async function findOrCreateTerm( term ) { - try { - const newTerm = await saveEntityRecord( - 'taxonomy', - 'wp_pattern_category', - { - name: term.label, - slug: term.name, - description: term.description, - }, - { - throwOnError: true, - } - ); - invalidateResolution( 'getUserPatternCategories' ); - return newTerm.id; - } catch ( error ) { - if ( error.code !== 'term_exists' ) { - throw error; + id: 'edit-site-patterns-success', } + ); - return error.data.term_id; - } + history.push( { + postType: TEMPLATE_PART_POST_TYPE, + postId: templatePart?.id, + categoryType: TEMPLATE_PART_POST_TYPE, + categoryId, + } ); + + onClose(); } - async function getCategories( categories ) { - const terms = categories.map( ( category ) => { - const fullCategory = patternCategories.find( - ( cat ) => cat.name === category - ); - if ( fullCategory.id ) { - return fullCategory.id; + function onPatternSuccess( { pattern } ) { + createSuccessNotice( + sprintf( + // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + pattern.title.raw + ), + { + type: 'snackbar', + id: 'edit-site-patterns-success', } - return findOrCreateTerm( fullCategory ); + ); + + history.push( { + categoryType: PATTERN_TYPES.theme, + categoryId, + postType: PATTERN_TYPES.user, + postId: pattern.id, } ); - return Promise.all( terms ); + onClose(); } - async function createPattern() { - try { - const isThemePattern = item.type === PATTERN_TYPES.theme; - const title = sprintf( - /* translators: %s: Existing pattern title */ - __( '%s (Copy)' ), - item.title || item.name - ); - const categories = await getCategories( item.categories || [] ); - - const result = await saveEntityRecord( - 'postType', - PATTERN_TYPES.user, - { - content: isThemePattern - ? item.content - : item.patternBlock.content, - meta: getPatternMeta( item ), - status: 'publish', - title, - wp_pattern_category: categories, - }, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), + const isThemePattern = item.type === PATTERN_TYPES.theme; + const closeModal = () => setIsModalOpen( false ); + const duplicatedProps = isTemplatePart + ? { + blocks: item.blocks, + defaultArea: item.templatePart.area, + defaultTitle: sprintf( + /* translators: %s: Existing template part title */ + __( '%s (Copy)' ), + item.title + ), + } + : { + defaultCategories: isThemePattern + ? item.categories + : item.termLabels, + content: isThemePattern + ? item.content + : item.patternBlock.content, + defaultSyncType: isThemePattern + ? PATTERN_SYNC_TYPES.unsynced + : item.syncStatus, + defaultTitle: sprintf( + /* translators: %s: Existing pattern title */ + __( '%s (Copy)' ), item.title || item.name ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - - history.push( { - categoryType: PATTERN_TYPES.theme, - categoryId, - postType: PATTERN_TYPES.user, - postId: result?.id, - } ); - - onClose(); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while creating the pattern.' ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - id: 'edit-site-patterns-error', - } ); - onClose(); - } - } - - const createItem = - item.type === TEMPLATE_PART_POST_TYPE - ? createTemplatePart - : createPattern; - - return { label }; + }; + + return ( + <> + setIsModalOpen( true ) } + aria-expanded={ isModalOpen } + aria-haspopup="dialog" + > + { label } + + { isModalOpen && ! isTemplatePart && ( + + ) } + { isModalOpen && isTemplatePart && ( + + ) } + > + ); } diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index 6504b6f59684c..fde4eaadb5dc0 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -195,6 +195,11 @@ const patternBlockToPattern = ( patternBlock, categories ) => ( { : patternCategoryId ), } ), + termLabels: patternBlock.wp_pattern_category.map( ( patternCategoryId ) => + categories?.get( patternCategoryId ) + ? categories.get( patternCategoryId ).label + : patternCategoryId + ), id: patternBlock.id, name: patternBlock.slug, syncStatus: patternBlock.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full, diff --git a/packages/patterns/src/components/create-pattern-modal.js b/packages/patterns/src/components/create-pattern-modal.js index 37dd725ef9226..6dd162605506e 100644 --- a/packages/patterns/src/components/create-pattern-modal.js +++ b/packages/patterns/src/components/create-pattern-modal.js @@ -28,15 +28,21 @@ import CategorySelector, { CATEGORY_SLUG } from './category-selector'; import { unlock } from '../lock-unlock'; export default function CreatePatternModal( { - onSuccess, - onError, + confirmLabel = __( 'Create' ), + defaultCategories = [], + className = 'patterns-menu-items__convert-modal', content, + modalTitle = __( 'Create pattern' ), onClose, - className = 'patterns-menu-items__convert-modal', + onError, + onSuccess, + defaultSyncType = PATTERN_SYNC_TYPES.full, + defaultTitle = '', } ) { - const [ syncType, setSyncType ] = useState( PATTERN_SYNC_TYPES.full ); - const [ categoryTerms, setCategoryTerms ] = useState( [] ); - const [ title, setTitle ] = useState( '' ); + const [ syncType, setSyncType ] = useState( defaultSyncType ); + const [ categoryTerms, setCategoryTerms ] = useState( defaultCategories ); + const [ title, setTitle ] = useState( defaultTitle ); + const [ isSaving, setIsSaving ] = useState( false ); const { createPattern } = unlock( useDispatch( patternsStore ) ); const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore ); @@ -145,7 +151,7 @@ export default function CreatePatternModal( { return ( { onClose(); setTitle( '' ); @@ -203,7 +209,7 @@ export default function CreatePatternModal( { aria-disabled={ ! title || isSaving } isBusy={ isSaving } > - { __( 'Create' ) } + { confirmLabel }
' ); * false === $processor->next_tag(); * WP_HTML_Processor::ERROR_UNSUPPORTED === $processor->get_last_error(); * @@ -361,6 +361,7 @@ public function get_last_error() { * Defaults to first tag. * @type string|null $class_name Tag must contain this whole class name to match. * @type string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. * } * @return bool Whether a tag was matched. */ @@ -410,26 +411,67 @@ public function next_tag( $query = null ) { $breadcrumbs = $query['breadcrumbs']; $match_offset = isset( $query['match_offset'] ) ? (int) $query['match_offset'] : 1; - $crumb = end( $breadcrumbs ); - $target = strtoupper( $crumb ); while ( $match_offset > 0 && $this->step() ) { - if ( $target !== $this->get_tag() ) { - continue; + if ( $this->matches_breadcrumbs( $breadcrumbs ) && 0 === --$match_offset ) { + return true; } + } - // Look up the stack to see if the breadcrumbs match. - foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { - if ( strtoupper( $crumb ) !== $node->node_name ) { - break; - } + return false; + } - $crumb = prev( $breadcrumbs ); - if ( false === $crumb && 0 === --$match_offset && ! $this->is_tag_closer() ) { - return true; - } + /** + * Indicates if the currently-matched tag matches the given breadcrumbs. + * + * A "*" represents a single tag wildcard, where any tag matches, but not no tags. + * + * At some point this function _may_ support a `**` syntax for matching any number + * of unspecified tags in the breadcrumb stack. This has been intentionally left + * out, however, to keep this function simple and to avoid introducing backtracking, + * which could open up surprising performance breakdowns. + * + * Example: + * + * $processor = WP_HTML_Processor::create_fragment( '' ); + * $processor->next_tag( 'img' ); + * true === $processor->matches_breadcrumbs( array( 'figure', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', 'figure', 'img' ) ); + * false === $processor->matches_breadcrumbs( array( 'span', 'img' ) ); + * true === $processor->matches_breadcrumbs( array( 'span', '*', 'img' ) ); + * + * @since 6.4.0 + * + * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. + * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. + * @return bool Whether the currently-matched tag is found at the given nested structure. + */ + public function matches_breadcrumbs( $breadcrumbs ) { + if ( ! $this->get_tag() ) { + return false; + } + + // Everything matches when there are zero constraints. + if ( 0 === count( $breadcrumbs ) ) { + return true; + } + + // Start at the last crumb. + $crumb = end( $breadcrumbs ); + + if ( '*' !== $crumb && $this->get_tag() !== strtoupper( $crumb ) ) { + return false; + } + + foreach ( $this->state->stack_of_open_elements->walk_up() as $node ) { + $crumb = strtoupper( current( $breadcrumbs ) ); + + if ( '*' !== $crumb && $node->node_name !== $crumb ) { + return false; } - $crumb = end( $breadcrumbs ); + if ( false === prev( $breadcrumbs ) ) { + return true; + } } return false; @@ -519,7 +561,7 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { * * Example * - * $processor = WP_HTML_Processor::createFragment( '' ); + * $processor = WP_HTML_Processor::create_fragment( '' ); * $processor->next_tag( 'IMG' ); * $processor->get_breadcrumbs() === array( 'HTML', 'BODY', 'P', 'STRONG', 'EM', 'IMG' ); * @@ -1401,5 +1443,5 @@ public static function is_void( $tag_name ) { * * @access private */ - const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::createFragment instead of calling the class constructor directly.'; + const CONSTRUCTOR_UNLOCK_CODE = 'Use WP_HTML_Processor::create_fragment() instead of calling the class constructor directly.'; } From 887cf3dfc4b3426ce5696a383216186233c468e1 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:42:00 +1100 Subject: [PATCH 05/32] Private APIs: Update consent string for unlocking access. (#55182) Replace the consent string with `I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress`. --- docs/contributors/code/coding-guidelines.md | 2 +- packages/block-editor/src/lock-unlock.js | 2 +- packages/block-library/src/lock-unlock.js | 2 +- packages/blocks/src/lock-unlock.js | 2 +- packages/commands/src/lock-unlock.js | 2 +- packages/components/src/private-apis.ts | 2 +- packages/core-commands/src/lock-unlock.js | 2 +- packages/core-data/src/private-apis.js | 2 +- packages/customize-widgets/src/lock-unlock.js | 2 +- packages/data/src/lock-unlock.js | 2 +- packages/edit-post/src/lock-unlock.js | 2 +- packages/edit-site/src/lock-unlock.js | 2 +- packages/edit-widgets/src/lock-unlock.js | 2 +- packages/editor/src/lock-unlock.js | 2 +- packages/patterns/src/lock-unlock.js | 2 +- packages/private-apis/README.md | 4 ++-- packages/private-apis/src/implementation.js | 2 +- packages/private-apis/src/test/index.js | 2 +- packages/reusable-blocks/src/lock-unlock.js | 2 +- packages/router/src/lock-unlock.js | 2 +- 20 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/contributors/code/coding-guidelines.md b/docs/contributors/code/coding-guidelines.md index 90fb5c7adf81f..53f0a0f8d1000 100644 --- a/docs/contributors/code/coding-guidelines.md +++ b/docs/contributors/code/coding-guidelines.md @@ -162,7 +162,7 @@ do so by opting-in to `@wordpress/private-apis`: import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' // Name of the package calling __dangerousOptInToUnstableAPIsOnlyForCoreModules, // (not the name of the package whose APIs you want to access) ); diff --git a/packages/block-editor/src/lock-unlock.js b/packages/block-editor/src/lock-unlock.js index 019821d284b36..433a61a12aec0 100644 --- a/packages/block-editor/src/lock-unlock.js +++ b/packages/block-editor/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' ); diff --git a/packages/block-library/src/lock-unlock.js b/packages/block-library/src/lock-unlock.js index 3fef0820721be..3c18e76b798cd 100644 --- a/packages/block-library/src/lock-unlock.js +++ b/packages/block-library/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-library' ); diff --git a/packages/blocks/src/lock-unlock.js b/packages/blocks/src/lock-unlock.js index 363b51af7d233..0a98fcfb19d29 100644 --- a/packages/blocks/src/lock-unlock.js +++ b/packages/blocks/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/blocks' ); diff --git a/packages/commands/src/lock-unlock.js b/packages/commands/src/lock-unlock.js index 0665114d842c3..e11bd687d8742 100644 --- a/packages/commands/src/lock-unlock.js +++ b/packages/commands/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/commands' ); diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index fd61c2564e6b0..fa086f783b4b2 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -34,7 +34,7 @@ import Theme from './theme'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/components' ); diff --git a/packages/core-commands/src/lock-unlock.js b/packages/core-commands/src/lock-unlock.js index 24973274f1897..6f0712a8069fd 100644 --- a/packages/core-commands/src/lock-unlock.js +++ b/packages/core-commands/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/core-commands' ); diff --git a/packages/core-data/src/private-apis.js b/packages/core-data/src/private-apis.js index a5b93a25dbf77..53f0dc2dfa133 100644 --- a/packages/core-data/src/private-apis.js +++ b/packages/core-data/src/private-apis.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/core-data' ); diff --git a/packages/customize-widgets/src/lock-unlock.js b/packages/customize-widgets/src/lock-unlock.js index f428bbaac936a..01d57a2835d5d 100644 --- a/packages/customize-widgets/src/lock-unlock.js +++ b/packages/customize-widgets/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/customize-widgets' ); diff --git a/packages/data/src/lock-unlock.js b/packages/data/src/lock-unlock.js index 5fdca775a27b8..b5b1f9cbed5a5 100644 --- a/packages/data/src/lock-unlock.js +++ b/packages/data/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/data' ); diff --git a/packages/edit-post/src/lock-unlock.js b/packages/edit-post/src/lock-unlock.js index 172d18df7d1ba..bf65b262d9f48 100644 --- a/packages/edit-post/src/lock-unlock.js +++ b/packages/edit-post/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-post' ); diff --git a/packages/edit-site/src/lock-unlock.js b/packages/edit-site/src/lock-unlock.js index 9934484ea2347..5c335db46b9d4 100644 --- a/packages/edit-site/src/lock-unlock.js +++ b/packages/edit-site/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-site' ); diff --git a/packages/edit-widgets/src/lock-unlock.js b/packages/edit-widgets/src/lock-unlock.js index a13068520e077..003e53788068c 100644 --- a/packages/edit-widgets/src/lock-unlock.js +++ b/packages/edit-widgets/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/edit-widgets' ); diff --git a/packages/editor/src/lock-unlock.js b/packages/editor/src/lock-unlock.js index 5a36d0cd752f4..12df6f4711b23 100644 --- a/packages/editor/src/lock-unlock.js +++ b/packages/editor/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/editor' ); diff --git a/packages/patterns/src/lock-unlock.js b/packages/patterns/src/lock-unlock.js index 51adc98f32cac..d727871d71439 100644 --- a/packages/patterns/src/lock-unlock.js +++ b/packages/patterns/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/patterns' ); diff --git a/packages/private-apis/README.md b/packages/private-apis/README.md index 9faaada853200..cdc1db2180e2c 100644 --- a/packages/private-apis/README.md +++ b/packages/private-apis/README.md @@ -12,7 +12,7 @@ Every `@wordpress` package wanting to privately access or expose experimental AP import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/block-editor' // Name of the package calling __dangerousOptInToUnstableAPIsOnlyForCoreModules, // (not the name of the package whose APIs you want to access) ); @@ -22,7 +22,7 @@ Each package may only opt in once. The function name communicates that plugins a The function will throw an error if the following conditions are not met: -1. The first argument must exactly match the required consent string: `'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'`. +1. The first argument must exactly match the required consent string: `'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'`. 2. The second argument must be a known `@wordpress` package that hasn't yet opted into `@wordpress/private-apis` Once the opt-in is complete, the obtained `lock()` and `unlock()` utilities enable hiding `__experimental` APIs from the naked eye: diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index 4f1877bff569e..14d3048eff68b 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -51,7 +51,7 @@ const registeredPrivateApis = []; * CHANGE MAY OCCUR IN EITHER A MAJOR OR MINOR RELEASE. */ const requiredConsent = - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'; /** @type {boolean} */ let allowReRegistration; diff --git a/packages/private-apis/src/test/index.js b/packages/private-apis/src/test/index.js index 2e73a1a58eaa1..d91f7d3bcdafe 100644 --- a/packages/private-apis/src/test/index.js +++ b/packages/private-apis/src/test/index.js @@ -16,7 +16,7 @@ beforeEach( () => { } ); const requiredConsent = - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.'; + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.'; describe( '__dangerousOptInToUnstableAPIsOnlyForCoreModules', () => { it( 'Should require a consent string', () => { diff --git a/packages/reusable-blocks/src/lock-unlock.js b/packages/reusable-blocks/src/lock-unlock.js index c33f209c9d76a..c0bc2d1529f7d 100644 --- a/packages/reusable-blocks/src/lock-unlock.js +++ b/packages/reusable-blocks/src/lock-unlock.js @@ -4,6 +4,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; export const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/reusable-blocks' ); diff --git a/packages/router/src/lock-unlock.js b/packages/router/src/lock-unlock.js index d148f785fe944..d7f4e92b4a542 100644 --- a/packages/router/src/lock-unlock.js +++ b/packages/router/src/lock-unlock.js @@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( - 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.', '@wordpress/router' ); From 84ed4a69e9715e71bcc4f3593154c3b82dd16531 Mon Sep 17 00:00:00 2001 From: Cullen Whitmore Date: Tue, 10 Oct 2023 19:41:22 -0500 Subject: [PATCH 06/32] docs: Update broken anchor link (#55233) --- packages/create-block/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index edcdd020caf38..88ac97c34c2cf 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -28,7 +28,7 @@ $ cd todo-list $ npm start ``` -The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation). +The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation-1). _(requires `node` version `14.0.0` or above, and `npm` version `6.14.4` or above)_ From 7602b560eca577d58ccbdf41d42ed5186caccc80 Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 10 Oct 2023 13:58:37 -0700 Subject: [PATCH 07/32] Block Supports: Backport optimization from Core for Elements Support Brings over optimization surfaced during the WordPress 6.4 beta release for block supports elements, which entails skipping needless iteration when it's known that the iteration need not continue. See WordPress/wordpress-develop#5411 See [#59544-trac](https://core.trac.wordpress.org/ticket/59544) --- lib/block-supports/elements.php | 88 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 2106360c4bd04..85dbd7d39797c 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -13,7 +13,7 @@ * @return string Filtered block content. */ function gutenberg_render_elements_support( $block_content, $block ) { - if ( ! $block_content || empty( $block['attrs'] ) ) { + if ( ! $block_content || ! isset( $block['attrs']['style']['elements'] ) ) { return $block_content; } @@ -23,42 +23,42 @@ function gutenberg_render_elements_support( $block_content, $block ) { 'button' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ), 'paths' => array( - 'style.elements.button.color.text', - 'style.elements.button.color.background', - 'style.elements.button.color.gradient', + array( 'button', 'color', 'text' ), + array( 'button', 'color', 'background' ), + array( 'button', 'color', 'gradient' ), ), ), 'link' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ), 'paths' => array( - 'style.elements.link.color.text', - 'style.elements.link.:hover.color.text', + array( 'link', 'color', 'text' ), + array( 'link', ':hover', 'color', 'text' ), ), ), 'heading' => array( 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ), 'paths' => array( - 'style.elements.heading.color.text', - 'style.elements.heading.color.background', - 'style.elements.heading.color.gradient', - 'style.elements.h1.color.text', - 'style.elements.h1.color.background', - 'style.elements.h1.color.gradient', - 'style.elements.h2.color.text', - 'style.elements.h2.color.background', - 'style.elements.h2.color.gradient', - 'style.elements.h3.color.text', - 'style.elements.h3.color.background', - 'style.elements.h3.color.gradient', - 'style.elements.h4.color.text', - 'style.elements.h4.color.background', - 'style.elements.h4.color.gradient', - 'style.elements.h5.color.text', - 'style.elements.h5.color.background', - 'style.elements.h5.color.gradient', - 'style.elements.h6.color.text', - 'style.elements.h6.color.background', - 'style.elements.h6.color.gradient', + array( 'heading', 'color', 'text' ), + array( 'heading', 'color', 'background' ), + array( 'heading', 'color', 'gradient' ), + array( 'h1', 'color', 'text' ), + array( 'h1', 'color', 'background' ), + array( 'h1', 'color', 'gradient' ), + array( 'h2', 'color', 'text' ), + array( 'h2', 'color', 'background' ), + array( 'h2', 'color', 'gradient' ), + array( 'h3', 'color', 'text' ), + array( 'h3', 'color', 'background' ), + array( 'h3', 'color', 'gradient' ), + array( 'h4', 'color', 'text' ), + array( 'h4', 'color', 'background' ), + array( 'h4', 'color', 'gradient' ), + array( 'h5', 'color', 'text' ), + array( 'h5', 'color', 'background' ), + array( 'h5', 'color', 'gradient' ), + array( 'h6', 'color', 'text' ), + array( 'h6', 'color', 'background' ), + array( 'h6', 'color', 'gradient' ), ), ), ); @@ -71,7 +71,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { return $block_content; } - $element_colors_set = 0; + $elements_style_attributes = $block['attrs']['style']['elements']; foreach ( $element_color_properties as $element_config ) { if ( $element_config['skip'] ) { @@ -79,24 +79,28 @@ function gutenberg_render_elements_support( $block_content, $block ) { } foreach ( $element_config['paths'] as $path ) { - if ( null !== _wp_array_get( $block['attrs'], explode( '.', $path ), null ) ) { - ++$element_colors_set; + if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) { + /* + * It only takes a single custom attribute to require that the custom + * class name be added to the block, so once one is found there's no + * need to continue looking for others. + * + * As is done with the layout hook, this code assumes that the block + * contains a single wrapper and that it's the first element in the + * rendered output. That first element, if it exists, gets the class. + */ + $tags = new WP_HTML_Tag_Processor( $block_content ); + if ( $tags->next_tag() ) { + $tags->add_class( wp_get_elements_class_name( $block ) ); + } + + return $tags->get_updated_html(); } } } - if ( ! $element_colors_set ) { - return $block_content; - } - - // Like the layout hook this assumes the hook only applies to blocks with a single wrapper. - // Add the class name to the first element, presuming it's the wrapper, if it exists. - $tags = new WP_HTML_Tag_Processor( $block_content ); - if ( $tags->next_tag() ) { - $tags->add_class( wp_get_elements_class_name( $block ) ); - } - - return $tags->get_updated_html(); + // If no custom attributes were found then there's nothing to modify. + return $block_content; } /** From 4d04850d1a03c55689844bccc20916129b962519 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 11 Oct 2023 14:04:04 +1100 Subject: [PATCH 08/32] Remove `@return void` from PHP function docs. (#55237) --- packages/block-library/src/form/index.php | 4 ---- packages/block-library/src/image/index.php | 4 ---- packages/block-library/src/pattern/index.php | 2 -- packages/block-library/src/search/index.php | 4 ---- 4 files changed, 14 deletions(-) diff --git a/packages/block-library/src/form/index.php b/packages/block-library/src/form/index.php index 0dbbaf6838740..b9e3a9c25c628 100644 --- a/packages/block-library/src/form/index.php +++ b/packages/block-library/src/form/index.php @@ -83,8 +83,6 @@ function block_core_form_extra_fields_comment_form( $extra_fields, $attributes ) /** * Sends an email if the form is a contact form. - * - * @return void */ function block_core_form_send_email() { check_ajax_referer( 'wp-block-form' ); @@ -126,8 +124,6 @@ function block_core_form_send_email() { /** * Send the data export/remove request if the form is a privacy-request form. - * - * @return void */ function block_core_form_privacy_form() { // Get the POST data. diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index e1f71964622c0..9cce87d9e8bd7 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -310,8 +310,6 @@ function block_core_image_render_lightbox( $block_content, $block ) { * @since 6.4.0 * * @global WP_Scripts $wp_scripts - * - * @return void */ function block_core_image_ensure_interactivity_dependency() { global $wp_scripts; @@ -327,8 +325,6 @@ function block_core_image_ensure_interactivity_dependency() { /** * Registers the `core/image` block on server. - * - * @return void */ function register_block_core_image() { register_block_type_from_metadata( diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index fc4652a7c22e8..1f5477968b92d 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -7,8 +7,6 @@ /** * Registers the `core/pattern` block on the server. - * - * @return void */ function register_block_core_pattern() { register_block_type_from_metadata( diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index ed3d1cf4b847a..f00ecfe6abe1c 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -281,8 +281,6 @@ function classnames_for_block_core_search( $attributes ) { * @param array $wrapper_styles Current collection of wrapper styles. * @param array $button_styles Current collection of button styles. * @param array $input_styles Current collection of input styles. - * - * @return void */ function apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) { $is_button_inside = isset( $attributes['buttonPosition'] ) && 'button-inside' === $attributes['buttonPosition']; @@ -327,8 +325,6 @@ function apply_block_core_search_border_style( $attributes, $property, $side, &$ * @param array $wrapper_styles Current collection of wrapper styles. * @param array $button_styles Current collection of button styles. * @param array $input_styles Current collection of input styles. - * - * @return void */ function apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) { apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles ); From f29a96b3fa63eabbd1d97f0f7e66b070986752b1 Mon Sep 17 00:00:00 2001 From: Jarda Snajdr Date: Wed, 11 Oct 2023 08:49:34 +0200 Subject: [PATCH 09/32] useBlockSettings: add missing useMemo dependencies (#55204) --- packages/block-editor/src/hooks/utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index f81fc118ea84b..8e0d422c5fbec 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -279,6 +279,8 @@ export function useBlockSettings( name, parentLayout ) { isBackgroundEnabled, isLinkEnabled, isTextEnabled, + isHeadingEnabled, + isButtonEnabled, ] ); return useSettingsForBlockElement( rawSettings, name ); From 8a9cb70272edcfdfd34f3557848949eb0fd29921 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Oct 2023 07:56:23 +0100 Subject: [PATCH 10/32] DataViews: Allow actions to be provided declaratively as a prop (#55192) * DataViews: Allow actions to be provided declaratively as a prop * Restore PageActions component * Rename variable * Fix typo --- .../src/components/actions/trash-post.js | 55 +++++++++++++++++++ .../src/components/dataviews/dataviews.js | 51 ++++++++++++++++- .../src/components/page-actions/index.js | 8 +-- .../src/components/page-pages/index.js | 18 ++---- 4 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 packages/edit-site/src/components/actions/trash-post.js diff --git a/packages/edit-site/src/components/actions/trash-post.js b/packages/edit-site/src/components/actions/trash-post.js new file mode 100644 index 0000000000000..7977ed3d11e00 --- /dev/null +++ b/packages/edit-site/src/components/actions/trash-post.js @@ -0,0 +1,55 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { decodeEntities } from '@wordpress/html-entities'; +import { store as coreStore } from '@wordpress/core-data'; +import { __, sprintf } from '@wordpress/i18n'; +import { store as noticesStore } from '@wordpress/notices'; +import { useMemo } from '@wordpress/element'; + +export default function useMoveToTrashAction() { + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + const { deleteEntityRecord } = useDispatch( coreStore ); + + return useMemo( + () => ( { + id: 'move-to-trash', + label: __( 'Move to Trash' ), + async perform( post ) { + try { + await deleteEntityRecord( + 'postType', + post.type, + post.id, + {}, + { throwOnError: true } + ); + createSuccessNotice( + sprintf( + /* translators: The page's title. */ + __( '"%s" moved to the Trash.' ), + decodeEntities( post.title.rendered ) + ), + { + type: 'snackbar', + id: 'edit-site-page-trashed', + } + ); + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( + 'An error occurred while moving the page to the trash.' + ); + + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + }, + isDesctructive: true, + } ), + [ createSuccessNotice, createErrorNotice, deleteEntityRecord ] + ); +} diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 4628d850a023c..13e27ddfacae5 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -15,7 +15,13 @@ import { import { __experimentalVStack as VStack, __experimentalHStack as HStack, + VisuallyHidden, + DropdownMenu, + MenuGroup, + MenuItem, } from '@wordpress/components'; +import { useMemo } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -24,8 +30,10 @@ import ListView from './list-view'; import { Pagination } from './pagination'; import ViewActions from './view-actions'; import TextFilter from './text-filter'; +import { moreVertical } from '@wordpress/icons'; export default function DataViews( { + actions, data, fields, view, @@ -34,9 +42,50 @@ export default function DataViews( { paginationInfo, options: { pageCount }, } ) { + const columns = useMemo( () => { + const _columns = [ ...fields ]; + if ( actions && actions.length ) { + _columns.push( { + header: { __( 'Actions' ) }, + id: 'actions', + cell: ( props ) => { + return ( + + { () => ( + + { actions.map( ( action ) => ( + + action.perform( + props.row.original + ) + } + isDestructive={ + action.isDesctructive + } + > + { action.label } + + ) ) } + + ) } + + ); + }, + enableHiding: false, + } ); + } + + return _columns; + }, [ fields, actions ] ); + const dataView = useReactTable( { data, - columns: fields, + columns, manualSorting: true, manualFiltering: true, manualPagination: true, diff --git a/packages/edit-site/src/components/page-actions/index.js b/packages/edit-site/src/components/page-actions/index.js index f6f0119a16454..d42a706c36796 100644 --- a/packages/edit-site/src/components/page-actions/index.js +++ b/packages/edit-site/src/components/page-actions/index.js @@ -10,17 +10,11 @@ import { moreVertical } from '@wordpress/icons'; */ import TrashPageMenuItem from './trash-page-menu-item'; -export default function PageActions( { - postId, - className, - toggleProps, - onRemove, -} ) { +export default function PageActions( { postId, toggleProps, onRemove } ) { return ( { () => ( diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 56575248453f0..2c7b07044dbdd 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { - VisuallyHidden, __experimentalHeading as Heading, __experimentalVStack as VStack, } from '@wordpress/components'; @@ -16,8 +15,8 @@ import { useState, useMemo } from '@wordpress/element'; */ import Page from '../page'; import Link from '../routes/link'; -import PageActions from '../page-actions'; import { DataViews } from '../dataviews'; +import useTrashPostAction from '../actions/trash-post'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -118,27 +117,22 @@ export default function PagePages() { postStatuses[ page.status ] ?? page.status, enableSorting: false, }, - { - header: { __( 'Actions' ) }, - id: 'actions', - cell: ( props ) => { - const page = props.row.original; - return ; - }, - enableHiding: false, - }, ], [ postStatuses ] ); + const trashPostAction = useTrashPostAction(); + const actions = useMemo( () => [ trashPostAction ], [ trashPostAction ] ); + // TODO: we need to handle properly `data={ data || EMPTY_ARRAY }` for when `isLoading`. return ( Date: Wed, 11 Oct 2023 10:02:46 +0200 Subject: [PATCH 11/32] Remove the lightbox filter and view file when the lightbox setting is disabled. (#55120) * Remove the filter and view file of the lightbox when the lightbox setting is disabled. * Make sure to add filter and view file when needed. * Fix block comment indentation. --- packages/block-library/src/image/index.php | 62 +++++++++++----------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 9cce87d9e8bd7..4213350ab05c8 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -32,45 +32,47 @@ function render_block_core_image( $attributes, $content, $block ) { $processor->set_attribute( 'data-id', $attributes['data-id'] ); } - $lightbox_enabled = false; $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block ); - // If the lightbox is enabled and the image is not linked, flag the lightbox to be rendered. - if ( isset( $lightbox_settings ) && 'none' === $link_destination ) { + $view_js_file_handle = 'wp-block-image-view'; + $script_handles = $block->block_type->view_script_handles; - if ( isset( $lightbox_settings['enabled'] ) && true === $lightbox_settings['enabled'] ) { - $lightbox_enabled = true; - } - } - - // If at least one block in the page has the lightbox, mark the block type as interactive. - if ( $lightbox_enabled ) { + /* + * If the lightbox is enabled and the image is not linked, add the filter + * and the JavaScript view file. + */ + if ( + isset( $lightbox_settings ) && + 'none' === $link_destination && + isset( $lightbox_settings['enabled'] ) && + true === $lightbox_settings['enabled'] + ) { $block->block_type->supports['interactivity'] = true; - } - - // Determine whether the view script should be enqueued or not. - $view_js_file = 'wp-block-image-view'; - if ( ! wp_script_is( $view_js_file ) ) { - $script_handles = $block->block_type->view_script_handles; - // If the script is not needed, and it is still in the `view_script_handles`, remove it. - if ( ! $lightbox_enabled && in_array( $view_js_file, $script_handles, true ) ) { - $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) ); - } - // If the script is needed, but it was previously removed, add it again. - if ( $lightbox_enabled && ! in_array( $view_js_file, $script_handles, true ) ) { - $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) ); + if ( ! in_array( $view_js_file_handle, $script_handles, true ) ) { + $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file_handle ) ); } - } - if ( $lightbox_enabled ) { - // This render needs to happen in a filter with priority 15 to ensure that it - // runs after the duotone filter and that duotone styles are applied to the image - // in the lightbox. We also need to ensure that the lightbox works with any plugins - // that might use filters as well. We can consider removing this in the future if the - // way the blocks are rendered changes, or if a new kind of filter is introduced. + /* + * This render needs to happen in a filter with priority 15 to ensure + * that it runs after the duotone filter and that duotone styles are + * applied to the image in the lightbox. We also need to ensure that the + * lightbox works with any plugins that might use filters as well. We + * can consider removing this in the future if the way the blocks are + * rendered changes, or if a new kind of filter is introduced. + */ add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 ); + } else { + /* + * Remove the filter and the JavaScript view file if previously added by + * other Image blocks. + */ + remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 ); + // If the script is not needed, and it is still in the `view_script_handles`, remove it. + if ( in_array( $view_js_file_handle, $script_handles, true ) ) { + $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file_handle ) ); + } } return $processor->get_updated_html(); From e1258031c11cd23d8d30bcf2521a81d04e512491 Mon Sep 17 00:00:00 2001 From: Andrew Hayward Date: Wed, 11 Oct 2023 09:48:07 +0100 Subject: [PATCH 12/32] Add `type="button"` to vanilla `` elements (#55125) * Adding `type="button` to buttons as needed * Updating test snapshots * Updating `CHANGELOG.md` --- .../color-palette/test/__snapshots__/control.js.snap | 1 + packages/block-library/src/page-list-item/edit.js | 2 ++ packages/components/CHANGELOG.md | 3 ++- packages/components/src/color-palette/index.tsx | 1 + .../test/__snapshots__/index.tsx.snap | 8 ++++++++ .../toggle-group-control-option-base/component.tsx | 1 + .../src/components/block-editor/resize-handle.js | 1 + .../edit-site/src/components/page-patterns/grid-item.js | 1 + 8 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index 242218705b3cf..3942c05ce96f1 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -175,6 +175,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` aria-label="Custom color picker. The currently selected color is called "red" and has a value of "#f00"." class="components-color-palette__custom-color-button" style="background: rgb(255, 0, 0);" + type="button" /> @@ -90,6 +91,7 @@ export default function PageListItemEdit( { context, attributes } ) { diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3dfc268ad2163..0605bda1a47e5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). ### Bug Fix @@ -52,7 +53,7 @@ ### Experimental -- Introduce `Tabs`, an experimental v2 of `TabPanel`: ([#53960](https://github.com/WordPress/gutenberg/pull/53960)). +- Introduce `Tabs`, an experimental v2 of `TabPanel`: ([#53960](https://github.com/WordPress/gutenberg/pull/53960)). ## 25.8.0 (2023-09-20) diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index f87d46e64bc09..297e03f389e3e 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -299,6 +299,7 @@ function UnforwardedColorPalette( style={ { background: value, } } + type="button" /> { onFocusProp?.( event ); diff --git a/packages/edit-site/src/components/block-editor/resize-handle.js b/packages/edit-site/src/components/block-editor/resize-handle.js index 199ca09869cf9..0e9fae084ec89 100644 --- a/packages/edit-site/src/components/block-editor/resize-handle.js +++ b/packages/edit-site/src/components/block-editor/resize-handle.js @@ -35,6 +35,7 @@ export default function ResizeHandle( { aria-label={ __( 'Drag to resize' ) } aria-describedby={ `resizable-editor__resize-help-${ direction }` } onKeyDown={ handleKeyDown } + type="button" /> Date: Wed, 11 Oct 2023 11:37:25 +0200 Subject: [PATCH 13/32] Patterns: Remove the version enforcement for npm in `engines` field (#55245) * Patterns: Remove the version enforcement for npm in `engines` * Regenerate the lock file --- package-lock.json | 3 +-- packages/patterns/package.json | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 341db8407614b..c457a01b4b74b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57445,8 +57445,7 @@ "@wordpress/url": "file:../url" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8 <9" + "node": ">=16.0.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/patterns/package.json b/packages/patterns/package.json index 0cb8857df9a4b..d8cabf9fae235 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -19,8 +19,7 @@ "url": "https://github.com/WordPress/gutenberg/issues" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8 <9" + "node": ">=16.0.0" }, "main": "build/index.js", "module": "build-module/index.js", From 3c75843af3002ff943dc8802d4f8b7e83cbf209a Mon Sep 17 00:00:00 2001 From: Siobhan Bamber Date: Wed, 11 Oct 2023 11:41:10 +0100 Subject: [PATCH 14/32] fix: Fix border visibility in block-based themes (#54964) --- packages/primitives/src/block-quotation/index.native.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/primitives/src/block-quotation/index.native.js b/packages/primitives/src/block-quotation/index.native.js index 01e8b7cdb4c50..3d0d29c297245 100644 --- a/packages/primitives/src/block-quotation/index.native.js +++ b/packages/primitives/src/block-quotation/index.native.js @@ -20,6 +20,9 @@ export const BlockQuotation = forwardRef( ( { ...props }, ref ) => { styles.wpBlockQuoteLight, styles.wpBlockQuoteDark ), + style?.baseColors?.color?.text && { + borderLeftColor: style.baseColors.color.text, + }, style?.color && { borderLeftColor: style.color, }, From 0c216e400b3cc7764cc27713bf44c31e3712dc57 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 11 Oct 2023 14:45:32 +0300 Subject: [PATCH 15/32] [DataViews]: Update the view config to include fields visibility (#55247) * [DataViews]: Update the view config to include fields visibility * fix typo * use array instead of Set for `hidden` * use `hiddenFields` top level prop --- .../src/components/dataviews/dataviews.js | 39 ++++++++++++++++++- .../src/components/dataviews/view-actions.js | 6 +-- .../src/components/page-pages/index.js | 16 ++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index 13e27ddfacae5..0131040bf83af 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -32,6 +32,8 @@ import ViewActions from './view-actions'; import TextFilter from './text-filter'; import { moreVertical } from '@wordpress/icons'; +const EMPTY_OBJECT = {}; + export default function DataViews( { actions, data, @@ -44,7 +46,7 @@ export default function DataViews( { } ) { const columns = useMemo( () => { const _columns = [ ...fields ]; - if ( actions && actions.length ) { + if ( actions?.length ) { _columns.push( { header: { __( 'Actions' ) }, id: 'actions', @@ -83,6 +85,19 @@ export default function DataViews( { return _columns; }, [ fields, actions ] ); + const columnVisibility = useMemo( () => { + if ( ! view.hiddenFields?.length ) { + return; + } + return view.hiddenFields.reduce( + ( accumulator, fieldId ) => ( { + ...accumulator, + [ fieldId ]: false, + } ), + {} + ); + }, [ view.hiddenFields ] ); + const dataView = useReactTable( { data, columns, @@ -104,6 +119,7 @@ export default function DataViews( { pageIndex: view.page, pageSize: view.perPage, }, + columnVisibility: columnVisibility ?? EMPTY_OBJECT, }, onSortingChange: ( sortingUpdater ) => { onChangeView( ( currentView ) => { @@ -135,6 +151,27 @@ export default function DataViews( { }; } ); }, + onColumnVisibilityChange: ( columnVisibilityUpdater ) => { + onChangeView( ( currentView ) => { + const hiddenFields = Object.entries( + columnVisibilityUpdater() + ).reduce( + ( accumulator, [ fieldId, value ] ) => { + if ( value ) { + return accumulator.filter( + ( id ) => id !== fieldId + ); + } + return [ ...accumulator, fieldId ]; + }, + [ ...( currentView.hiddenFields || [] ) ] + ); + return { + ...currentView, + hiddenFields, + }; + } ); + }, onGlobalFilterChange: ( value ) => { onChangeView( { ...view, search: value, page: 0 } ); }, diff --git a/packages/edit-site/src/components/dataviews/view-actions.js b/packages/edit-site/src/components/dataviews/view-actions.js index 1ede6ebcd8b75..ab9f3be88c200 100644 --- a/packages/edit-site/src/components/dataviews/view-actions.js +++ b/packages/edit-site/src/components/dataviews/view-actions.js @@ -102,10 +102,10 @@ function PageSizeMenu( { dataView } ) { } function FieldsVisibilityMenu( { dataView } ) { - const hideableFields = dataView + const hidableFields = dataView .getAllColumns() .filter( ( columnn ) => columnn.getCanHide() ); - if ( ! hideableFields?.length ) { + if ( ! hidableFields?.length ) { return null; } return ( @@ -118,7 +118,7 @@ function FieldsVisibilityMenu( { dataView } ) { } > - { hideableFields?.map( ( field ) => { + { hidableFields?.map( ( field ) => { return ( { + const formattedDate = dateI18n( + getSettings().formats.datetimeAbbreviated, + getDate( props.row.original.date ) + ); + return { formattedDate }; + }, + enableSorting: false, + }, ], [ postStatuses ] ); From 75ea690cae00f70366357b2976e2aaa0e72c576e Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:04:27 +0300 Subject: [PATCH 16/32] Data views: add linked title fallback (#55248) --- packages/edit-site/src/components/page-pages/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 62276f314f746..ec27265302748 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -91,7 +91,8 @@ export default function PagePages() { canvas: 'edit', } } > - { decodeEntities( props.getValue() ) } + { decodeEntities( props.getValue() ) || + __( '(no title)' ) } From 9e11bfc6f4066a9a288f1e4ddba1e3037d6a53d0 Mon Sep 17 00:00:00 2001 From: Artemio Morales Date: Wed, 11 Oct 2023 07:12:43 -0500 Subject: [PATCH 17/32] Image: Disable lightbox editor UI for linked images (#55141) * Disable lightbox UI and add help text for linked images * Update help text --- packages/block-library/src/image/image.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index d49a8f7cd0578..1f602c4380e88 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -377,6 +377,8 @@ export default function Image( { const lightboxChecked = !! lightbox?.enabled || ( ! lightbox && !! lightboxSetting?.enabled ); + const lightboxToggleDisabled = linkDestination !== 'none'; + const dimensionsControl = ( ) } From bd3ea8771a09e6e86f6d662fe0242089d81c7873 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 11 Oct 2023 14:42:59 +0100 Subject: [PATCH 18/32] Only handle rename UI if selected (#55250) --- packages/block-editor/src/hooks/block-rename-ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/block-rename-ui.js b/packages/block-editor/src/hooks/block-rename-ui.js index 6a98dcf2e2fad..aec11a9b2c657 100644 --- a/packages/block-editor/src/hooks/block-rename-ui.js +++ b/packages/block-editor/src/hooks/block-rename-ui.js @@ -189,13 +189,13 @@ function BlockRenameControl( props ) { export const withBlockRenameControl = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { - const { clientId, name, attributes, setAttributes } = props; + const { clientId, name, attributes, setAttributes, isSelected } = props; const supportsBlockNaming = hasBlockSupport( name, 'renaming', true ); return ( <> - { supportsBlockNaming && ( + { isSelected && supportsBlockNaming && ( <> Date: Wed, 11 Oct 2023 15:53:52 +0200 Subject: [PATCH 19/32] Colors: Fix color button border radii (#55207) * Apply the classname prop to `ToolsPanelItem` only when it s not a placeholder * Color Gradient panel: use new selctors to select first and last items * Add fallback for browsers not yet supporting the `:has()` selector * Use nth-child notation instead of :has and sibling selector * CHANGELOG --- .../src/components/colors-gradients/style.scss | 6 ++++-- packages/components/CHANGELOG.md | 1 + .../src/tools-panel/tools-panel-item/hook.ts | 10 ++++------ .../components/src/tools-panel/tools-panel/README.md | 3 +++ packages/components/src/tools-panel/types.ts | 2 ++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/colors-gradients/style.scss b/packages/block-editor/src/components/colors-gradients/style.scss index 8b36f04b83552..6cade124b7fe4 100644 --- a/packages/block-editor/src/components/colors-gradients/style.scss +++ b/packages/block-editor/src/components/colors-gradients/style.scss @@ -77,14 +77,16 @@ $swatch-gap: 12px; border-right: 1px solid $gray-300; border-bottom: 1px solid $gray-300; - &.first { + // Identify the first visible instance as placeholder items will not have this class. + &:nth-child(1 of &) { margin-top: $grid-unit-30; border-top-left-radius: $radius-block-ui; border-top-right-radius: $radius-block-ui; border-top: 1px solid $gray-300; } - &.last { + // Identify the last visible instance as placeholder items will not have this class. + &:nth-last-child(1 of &) { border-bottom-left-radius: $radius-block-ui; border-bottom-right-radius: $radius-block-ui; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 0605bda1a47e5..b3c01c4db2c70 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- `ToolsPanel`: do not apply the `className` to prop to `ToolsPanelItem` components when rendered as placeholders ([#55207](https://github.com/WordPress/gutenberg/pull/55207)). - `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). ### Bug Fix diff --git a/packages/components/src/tools-panel/tools-panel-item/hook.ts b/packages/components/src/tools-panel/tools-panel-item/hook.ts index 95958ae9f4860..23701afdfcfd0 100644 --- a/packages/components/src/tools-panel/tools-panel-item/hook.ts +++ b/packages/components/src/tools-panel/tools-panel-item/hook.ts @@ -176,18 +176,16 @@ export function useToolsPanelItem( const cx = useCx(); const classes = useMemo( () => { - const placeholderStyle = - shouldRenderPlaceholder && - ! isShown && - styles.ToolsPanelItemPlaceholder; + const shouldApplyPlaceholderStyles = + shouldRenderPlaceholder && ! isShown; const firstItemStyle = firstDisplayedItem === label && __experimentalFirstVisibleItemClass; const lastItemStyle = lastDisplayedItem === label && __experimentalLastVisibleItemClass; return cx( styles.ToolsPanelItem, - placeholderStyle, - className, + shouldApplyPlaceholderStyles && styles.ToolsPanelItemPlaceholder, + ! shouldApplyPlaceholderStyles && className, firstItemStyle, lastItemStyle ); diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md index 6802a6436875a..0ee251592d67b 100644 --- a/packages/components/src/tools-panel/tools-panel/README.md +++ b/packages/components/src/tools-panel/tools-panel/README.md @@ -191,5 +191,8 @@ A function to call when the `Reset all` menu option is selected. As an argument, Advises the `ToolsPanel` that all of its `ToolsPanelItem` children should render placeholder content (instead of `null`) when they are toggled off and hidden. +Note that placeholder items won't apply the `className` that would be +normally applied to a visible `ToolsPanelItem` via the `className` prop. + - Required: No - Default: `false` diff --git a/packages/components/src/tools-panel/types.ts b/packages/components/src/tools-panel/types.ts index 183ed3254fe80..3156137e58044 100644 --- a/packages/components/src/tools-panel/types.ts +++ b/packages/components/src/tools-panel/types.ts @@ -50,6 +50,8 @@ export type ToolsPanelProps = { /** * Advises the `ToolsPanel` that its child `ToolsPanelItem`s should render * placeholder content instead of null when they are toggled off and hidden. + * Note that placeholder items won't apply the `className` that would be + * normally applied to a visible `ToolsPanelItem` via the `className` prop. * * @default false */ From bc47191907929ea89236df76063d434d48bff822 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Oct 2023 14:58:10 +0100 Subject: [PATCH 20/32] DataViews: Add featured image field to the page list (#55246) Co-authored-by: ntsekouras --- .../edit-site/src/components/media/index.js | 27 +++++++++++++++++++ .../src/components/page-pages/index.js | 19 +++++++++++-- .../src/components/page-pages/style.scss | 4 +++ packages/edit-site/src/style.scss | 1 + 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 packages/edit-site/src/components/media/index.js create mode 100644 packages/edit-site/src/components/page-pages/style.scss diff --git a/packages/edit-site/src/components/media/index.js b/packages/edit-site/src/components/media/index.js new file mode 100644 index 0000000000000..7120d7c7f56ce --- /dev/null +++ b/packages/edit-site/src/components/media/index.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { useEntityRecord } from '@wordpress/core-data'; + +function Media( { id, size, ...props } ) { + const { record: media } = useEntityRecord( 'root', 'media', id ); + const sizesPerPriority = [ 'large', 'thumbnail' ]; + const currentSize = + size ?? + sizesPerPriority.find( ( s ) => !! media?.media_details?.sizes[ s ] ); + const mediaDetails = media?.media_details?.sizes[ currentSize ]; + + if ( ! mediaDetails ) { + return null; + } + + return ( + + ); +} + +export default Media; diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index ec27265302748..e34e4cbac5be3 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -18,6 +18,7 @@ import Page from '../page'; import Link from '../routes/link'; import { DataViews } from '../dataviews'; import useTrashPostAction from '../actions/trash-post'; +import Media from '../media'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; @@ -34,7 +35,7 @@ export default function PagePages() { }, // All fields are visible by default, so it's // better to keep track of the hidden ones. - hiddenFields: [ 'date' ], + hiddenFields: [ 'date', 'featured-image' ], } ); // Request post statuses to get the proper labels. const { records: statuses } = useEntityRecords( 'root', 'status' ); @@ -75,6 +76,20 @@ export default function PagePages() { const fields = useMemo( () => [ + { + id: 'featured-image', + header: __( 'Featured Image' ), + accessorFn: ( page ) => page.featured_media, + cell: ( props ) => + !! props.row.original.featured_media ? ( + + ) : null, + enableSorting: false, + }, { header: __( 'Title' ), id: 'title', @@ -116,7 +131,7 @@ export default function PagePages() { }, }, { - header: 'Status', + header: __( 'Status' ), id: 'status', accessorFn: ( page ) => postStatuses[ page.status ] ?? page.status, diff --git a/packages/edit-site/src/components/page-pages/style.scss b/packages/edit-site/src/components/page-pages/style.scss new file mode 100644 index 0000000000000..82e124b3ac4fe --- /dev/null +++ b/packages/edit-site/src/components/page-pages/style.scss @@ -0,0 +1,4 @@ +.edit-site-page-pages__featured-image { + border-radius: $radius-block-ui; + max-height: 60px; +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index e95cd3571c419..dadbf48d06e64 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -11,6 +11,7 @@ @import "./components/header-edit-mode/document-actions/style.scss"; @import "./components/list/style.scss"; @import "./components/page/style.scss"; +@import "./components/page-pages/style.scss"; @import "./components/page-patterns/style.scss"; @import "./components/table/style.scss"; @import "./components/sidebar-edit-mode/style.scss"; From bab057e96f30f8e2284feec137de88e300a8e0aa Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 15:55:53 +0100 Subject: [PATCH 21/32] Update: Unset variable set by reference after a foreach loop. (#55261) --- lib/class-wp-theme-json-gutenberg.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 3aa07158df853..8c2857fa89d0c 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1065,6 +1065,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' foreach ( $style_nodes as &$node ) { $node['selector'] = static::scope_selector( $options['scope'], $node['selector'] ); } + unset( $node ); } if ( ! empty( $options['root_selector'] ) ) { From 31d16369947199fd806e37ca0667b9ec8c38dc9c Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 15:56:19 +0100 Subject: [PATCH 22/32] Fix: Use y-webrtc room name terminology instead of docName. (#55260) --- packages/sync/src/connect-indexdb.js | 4 ++-- packages/sync/src/connect-webrtc.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sync/src/connect-indexdb.js b/packages/sync/src/connect-indexdb.js index ee56a463fd995..5523640408f57 100644 --- a/packages/sync/src/connect-indexdb.js +++ b/packages/sync/src/connect-indexdb.js @@ -20,8 +20,8 @@ import { IndexeddbPersistence } from 'y-indexeddb'; * @return {Promise<() => void>} Promise that resolves when the connection is established. */ export function connectIndexDb( objectId, objectType, doc ) { - const docName = `${ objectType }-${ objectId }`; - const provider = new IndexeddbPersistence( docName, doc ); + const roomName = `${ objectType }-${ objectId }`; + const provider = new IndexeddbPersistence( roomName, doc ); return new Promise( ( resolve ) => { provider.on( 'synced', () => { diff --git a/packages/sync/src/connect-webrtc.js b/packages/sync/src/connect-webrtc.js index 867bba39d6892..fefe3fddbb8a5 100644 --- a/packages/sync/src/connect-webrtc.js +++ b/packages/sync/src/connect-webrtc.js @@ -18,8 +18,8 @@ import { WebrtcProvider } from 'y-webrtc'; * @return {Promise<() => void>} Promise that resolves when the connection is established. */ export function connectWebRTC( objectId, objectType, doc ) { - const docName = `${ objectType }-${ objectId }`; - new WebrtcProvider( docName, doc, { + const roomName = `${ objectType }-${ objectId }`; + new WebrtcProvider( roomName, doc, { // @ts-ignore password: window.__experimentalCollaborativeEditingSecret, } ); From bdfb93e6db4334f0022acc512fc2c52bfe6d27ff Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 11 Oct 2023 18:02:46 +0300 Subject: [PATCH 23/32] Add changelog entry for #54415 (#55201) * Add changelog entry for #54415 * Move changelog to components --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index b3c01c4db2c70..addb5a4d9ec32 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - `Notice`: Remove margins from `Notice` component ([#54800](https://github.com/WordPress/gutenberg/pull/54800)). +- Allow using CSS level 4 viewport-relative units ([54415](https://github.com/WordPress/gutenberg/pull/54415)) - `ToolsPanel`: do not apply the `className` to prop to `ToolsPanelItem` components when rendered as placeholders ([#55207](https://github.com/WordPress/gutenberg/pull/55207)). - `ColorPalette`/`ToggleGroupControl/ToggleGroupControlOptionBase`: add `type="button"` attribute to native ``s ([#55125](https://github.com/WordPress/gutenberg/pull/55125)). From c04dadbeb7c6d5f6a6d34536cac0c7cf39b403fe Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 11 Oct 2023 16:33:51 +0100 Subject: [PATCH 24/32] Chore: Fix: Remove third parameter passed to shouldDismissPastedFiles which only receives 2. (#55262) --- packages/block-editor/src/utils/pasting.js | 5 +-- .../block-editor/src/utils/test/pasting.js | 31 +++++++------------ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/utils/pasting.js b/packages/block-editor/src/utils/pasting.js index f9612aad20f14..3ce7c20083269 100644 --- a/packages/block-editor/src/utils/pasting.js +++ b/packages/block-editor/src/utils/pasting.js @@ -77,10 +77,7 @@ export function getPasteEventData( { clipboardData } ) { const files = getFilesFromDataTransfer( clipboardData ); - if ( - files.length && - ! shouldDismissPastedFiles( files, html, plainText ) - ) { + if ( files.length && ! shouldDismissPastedFiles( files, html ) ) { return { files }; } diff --git a/packages/block-editor/src/utils/test/pasting.js b/packages/block-editor/src/utils/test/pasting.js index 7cebac9be6692..2c9dc8654a895 100644 --- a/packages/block-editor/src/utils/test/pasting.js +++ b/packages/block-editor/src/utils/test/pasting.js @@ -11,20 +11,19 @@ const mocks = { describe( 'shouldDismissPastedFiles', () => { it( 'should return false when no HTML is present', () => { - expect( - shouldDismissPastedFiles( [ mocks.pngImageFile ], '', '' ) - ).toBe( false ); + expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], '' ) ).toBe( + false + ); } ); it( 'should return false when file is not an image', () => { - expect( - shouldDismissPastedFiles( [ mocks.documentFile ], '', '' ) - ).toBe( false ); + expect( shouldDismissPastedFiles( [ mocks.documentFile ], '' ) ).toBe( + false + ); } ); it( 'should return false when multiple images are present', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile, mocks.jpgImageFile ], - '', '' ) ).toBe( false ); @@ -33,8 +32,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( false ); } ); @@ -42,8 +40,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( true ); } ); @@ -56,8 +53,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - 'https://lh3.googleusercontent.com/ab/SOMESTRING?authuser=0' + '' ) ).toBe( false ); } ); @@ -66,8 +62,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - '', - '' + '' ) ).toBe( false ); } ); @@ -76,8 +71,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - 'Some table text', - 'Some table text' + 'Some table text' ) ).toBe( true ); } ); @@ -86,8 +80,7 @@ describe( 'shouldDismissPastedFiles', () => { expect( shouldDismissPastedFiles( [ mocks.pngImageFile ], - 'AB', - 'A\nB' + 'AB' ) ).toBe( true ); } ); From c42302313185c983a4550a7723e3d90f05bc7a30 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 11 Oct 2023 20:53:48 +0300 Subject: [PATCH 25/32] Writing flow: fix selecting synced pattern (#55221) --- .../components/writing-flow/use-arrow-nav.js | 4 ++++ .../specs/editor/various/writing-flow.spec.js | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js index 02bff32eaefa3..44051b324ff64 100644 --- a/packages/block-editor/src/components/writing-flow/use-arrow-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-arrow-nav.js @@ -114,6 +114,10 @@ export function getClosestTabbable( } function isTabCandidate( node ) { + if ( node.closest( '[inert]' ) ) { + return; + } + // Skip if there's only one child that is content editable (and thus a // better candidate). if ( diff --git a/test/e2e/specs/editor/various/writing-flow.spec.js b/test/e2e/specs/editor/various/writing-flow.spec.js index 98bb00a596f03..a772bd91276c2 100644 --- a/test/e2e/specs/editor/various/writing-flow.spec.js +++ b/test/e2e/specs/editor/various/writing-flow.spec.js @@ -1116,6 +1116,29 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { ) ).toHaveText( /^.a+$/ ); } ); + + test( 'should select synced pattern', async ( { page, editor } ) => { + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'synced' ); + + await editor.clickBlockOptionsMenuItem( 'Create pattern' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.type( 'test' ); + await page.keyboard.press( 'Enter' ); + + await expect( + editor.canvas.locator( '[data-type="core/block"]' ) + ).toBeFocused(); + + await editor.insertBlock( { name: 'core/paragraph' } ); + + await page.keyboard.press( 'ArrowUp' ); + + await expect( + editor.canvas.locator( '[data-type="core/block"]' ) + ).toBeFocused(); + } ); } ); class WritingFlowUtils { From 9087e3dc8381fcb83e666d54595fc3a3e2ac1f85 Mon Sep 17 00:00:00 2001 From: Artemio Morales Date: Wed, 11 Oct 2023 13:36:10 -0500 Subject: [PATCH 26/32] Image: Stop crashing with Lightbox on image blocks without an image (#55269) * Stop crashing with Lightbox on image blocks without an image * Fix PHPCS error --- packages/block-library/src/image/index.php | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 4213350ab05c8..87e17a4c136b4 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -16,11 +16,13 @@ * @return string The block content with the data-id attribute added. */ function render_block_core_image( $attributes, $content, $block ) { + if ( false === stripos( $content, 'next_tag( 'img' ); - if ( $processor->get_attribute( 'src' ) === null ) { + if ( ! $processor->next_tag( 'img' ) || null === $processor->get_attribute( 'src' ) ) { return ''; } @@ -125,11 +127,28 @@ function block_core_image_get_lightbox_settings( $block ) { * @return string Filtered block content. */ function block_core_image_render_lightbox( $block_content, $block ) { + /* + * If it's not possible that an IMG element exists then return the given + * block content as-is. It may be that there's no actual image in the block + * or it could be that another plugin already modified this HTML. + */ + if ( false === stripos( $block_content, 'next_tag( 'img' ); + /* + * If there's definitely no IMG element in the block then return the given + * block content as-is. There's nothing that this code can knowingly modify + * to add the lightbox behavior. + */ + if ( ! $processor->next_tag( 'img' ) ) { + return $block_content; + } + $alt_attribute = $processor->get_attribute( 'alt' ); // An empty alt attribute `alt=""` is valid for decorative images. From a3bde627aa4219c0b6a4ae67644bd9f79079115c Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 11 Oct 2023 18:55:41 +0000 Subject: [PATCH 27/32] Bump plugin version to 16.8.0 --- 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 1bfcb11db361b..f2ae747fd9e20 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: 16.8.0-rc.2 + * Version: 16.8.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index c457a01b4b74b..557adb678c325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index cf6ce78f22e7f..9f014a3cfbae0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "16.8.0-rc.2", + "version": "16.8.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 5cf349583aa62424fedf213f1e3b5c3e12a90960 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 11 Oct 2023 19:15:21 +0000 Subject: [PATCH 28/32] Update Changelog for 16.8.0 --- changelog.txt | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) diff --git a/changelog.txt b/changelog.txt index 1b7d1150efdaf..801ea6d95cd5e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ == Changelog == += 16.8.0 = + = 16.8.0-rc.2 = ## Changelog @@ -21,6 +23,294 @@ The following contributors merged PRs in this release: @fullofcaffeine @torounit += 16.8.0-rc.1 = + +## Changelog + +### Features + +#### Block Editor +- Adds 'nofollow' setting to Button block. ([54110](https://github.com/WordPress/gutenberg/pull/54110)) + +#### Site Editor +- Add 'Show template' toggle when editing pages. ([52674](https://github.com/WordPress/gutenberg/pull/52674)) + + +### Enhancements + +- Update pattern import menu item. ([54782](https://github.com/WordPress/gutenberg/pull/54782)) + +#### Components +- Adding label/description to `BlockEditor/DuotoneControl`. ([54473](https://github.com/WordPress/gutenberg/pull/54473)) +- Deprecating `isPressed` in `Button` component. ([54740](https://github.com/WordPress/gutenberg/pull/54740)) +- Follow ariakit best practices. ([54696](https://github.com/WordPress/gutenberg/pull/54696)) +- InputControl-based components: Add opt-in prop for next 40px default size. ([53819](https://github.com/WordPress/gutenberg/pull/53819)) +- Modal: Add `contentWidth` prop to support a selection of preset modal sizes. ([54471](https://github.com/WordPress/gutenberg/pull/54471)) +- Remove unused components from `ui/`. ([54573](https://github.com/WordPress/gutenberg/pull/54573)) +- Update ariakit to 0.3.3. ([54818](https://github.com/WordPress/gutenberg/pull/54818)) +- Update compact search control metrics. ([54663](https://github.com/WordPress/gutenberg/pull/54663)) +- Wrapped `TextareaControl` in a `forwardRef` call. ([54975](https://github.com/WordPress/gutenberg/pull/54975)) + +#### Block Library +- Add a brief description to the Footnotes block. ([54613](https://github.com/WordPress/gutenberg/pull/54613)) +- Footnotes: Use core’s meta revisioning if available. ([52988](https://github.com/WordPress/gutenberg/pull/52988)) +- Login/out: Add spacing support. ([45147](https://github.com/WordPress/gutenberg/pull/45147)) +- Query view.js: Code quality. ([54982](https://github.com/WordPress/gutenberg/pull/54982)) +- Set custom color when applying initial background image. ([54054](https://github.com/WordPress/gutenberg/pull/54054)) +- Use `wp_get_inline_script_tag()` in `build_dropdown_script_block_core_categories()`. ([54637](https://github.com/WordPress/gutenberg/pull/54637)) + +#### Block Editor +- Default suggested links to pages. ([54622](https://github.com/WordPress/gutenberg/pull/54622)) +- Remove base URL from link control search results. ([54553](https://github.com/WordPress/gutenberg/pull/54553)) +- Simplify `BlockHTMLConvertButton`. ([54972](https://github.com/WordPress/gutenberg/pull/54972)) +- Update strings in blocks 'RenameModal' component. ([54887](https://github.com/WordPress/gutenberg/pull/54887)) + +#### Post Editor +- Edit Post: Use hooks instead of HoCs in 'PostStatus' components. ([54951](https://github.com/WordPress/gutenberg/pull/54951)) +- Editor: Use hooks instead of HoCs in 'PostSticky' components. ([54949](https://github.com/WordPress/gutenberg/pull/54949)) +- Editor: Use hooks instead of HoCs in 'PostSwitchToDraftButton'. ([54695](https://github.com/WordPress/gutenberg/pull/54695)) +- Show confirmation dialog when moving a post to the trash. ([50219](https://github.com/WordPress/gutenberg/pull/50219)) + +#### Site Editor +- Add template replace flow to template inspector. ([54609](https://github.com/WordPress/gutenberg/pull/54609)) +- [Site Editor]: Update copy of using the default template in a page. ([54728](https://github.com/WordPress/gutenberg/pull/54728)) + +#### Patterns +- Remove category description in inserter panel. ([54894](https://github.com/WordPress/gutenberg/pull/54894)) + +#### Typography +- Font Library: Refactor endpoint permissions. ([54829](https://github.com/WordPress/gutenberg/pull/54829)) + + +### Bug Fixes + +- Fix the ShortcutProvider usage. ([54851](https://github.com/WordPress/gutenberg/pull/54851)) +- Fix warning when a template calls a template area twice. ([54861](https://github.com/WordPress/gutenberg/pull/54861)) +- Revert "Fix warning when a template calls a template area twice". ([54926](https://github.com/WordPress/gutenberg/pull/54926)) + +#### Block Library +- All Nav block items to break long titles. ([54866](https://github.com/WordPress/gutenberg/pull/54866)) +- Fallback to Twitter provider when embedding X URLs. ([54876](https://github.com/WordPress/gutenberg/pull/54876)) +- Fix Deleted Navigation Menu warning string. ([55033](https://github.com/WordPress/gutenberg/pull/55033)) +- Fix Search Block not updating in Nav block. ([54823](https://github.com/WordPress/gutenberg/pull/54823)) +- Fix left and right aligmnent in children of Post Template. ([54997](https://github.com/WordPress/gutenberg/pull/54997)) +- Fix output of Navigation block classnames in the editor. ([54992](https://github.com/WordPress/gutenberg/pull/54992)) +- Fix overwriting of published post meta when previewing footnote changes. ([54339](https://github.com/WordPress/gutenberg/pull/54339)) +- Image: Ensure Expand on Click toggle is shown if block-level lightbox setting exists. ([54878](https://github.com/WordPress/gutenberg/pull/54878)) +- Image: Fix layout shift when lightbox is opened and closed. ([53026](https://github.com/WordPress/gutenberg/pull/53026)) +- Media & Text: Fix React warning. ([55038](https://github.com/WordPress/gutenberg/pull/55038)) +- Search block: Allow space for input field only when form expanded. ([54846](https://github.com/WordPress/gutenberg/pull/54846)) +- Search block: Update alignment and icon button width. ([54773](https://github.com/WordPress/gutenberg/pull/54773)) + +#### Site Editor +- Avoid same key warnings in template parts area listings. ([54863](https://github.com/WordPress/gutenberg/pull/54863)) +- Avoid stale navigation block values when parsing entity record. ([54996](https://github.com/WordPress/gutenberg/pull/54996)) +- Don't display the navigation section in template parts details when a menu is missing. ([54993](https://github.com/WordPress/gutenberg/pull/54993)) +- Fix ToolSelector popover variant. ([54840](https://github.com/WordPress/gutenberg/pull/54840)) +- Reset 'Show template' toggle when leaving edit mode. ([54679](https://github.com/WordPress/gutenberg/pull/54679)) +- remove `overflow: Hidden` from the entity title in the site editor sidebar. ([54769](https://github.com/WordPress/gutenberg/pull/54769)) + +#### Components +- FormTokenField: Add `box-sizing` reset style and reset default padding. ([54734](https://github.com/WordPress/gutenberg/pull/54734)) +- Popover: Fix the styles for components that use emotion within popovers. ([54912](https://github.com/WordPress/gutenberg/pull/54912)) +- Remove hover style for secondary Button when aria-disabled is set. ([54978](https://github.com/WordPress/gutenberg/pull/54978)) +- Reverting addition of `aria-selected` style hook in `Button`. ([54931](https://github.com/WordPress/gutenberg/pull/54931)) +- `SlotFill`: Pass `Component` instance to unregisterSlot. ([54765](https://github.com/WordPress/gutenberg/pull/54765)) + +#### Block Editor +- Avoid double-wrapping selectors when transforming the styles. ([54981](https://github.com/WordPress/gutenberg/pull/54981)) +- [Inserter]: Fix reset of registered media categories. ([55012](https://github.com/WordPress/gutenberg/pull/55012)) + +#### Typography +- Font Library: Changed the OTF mime type expected value to be what PHP returns. ([54886](https://github.com/WordPress/gutenberg/pull/54886)) +- Font Library: Move font uploads to a new tab. ([54655](https://github.com/WordPress/gutenberg/pull/54655)) + +#### Global Styles +- Block custom CSS: Fix incorrect CSS when multiple root selectors. ([53602](https://github.com/WordPress/gutenberg/pull/53602)) +- Image: Ensure `false` values are preserved in memory when defined in `theme.json`. ([54639](https://github.com/WordPress/gutenberg/pull/54639)) + +#### List View +- Fix performance issue when selecting all blocks. ([54900](https://github.com/WordPress/gutenberg/pull/54900)) + +#### Colors +- Format Library: Try to fix highlight popover jumping. ([54736](https://github.com/WordPress/gutenberg/pull/54736)) + +#### Interactivity API +- Image: Fix duotone not being applied to lightbox image. ([54670](https://github.com/WordPress/gutenberg/pull/54670)) + + +### Accessibility + +#### Block Library +- Footnotes: Add aria-label to return links. ([54843](https://github.com/WordPress/gutenberg/pull/54843)) +- Table of contents block accessibility improvements. ([54322](https://github.com/WordPress/gutenberg/pull/54322)) + +#### Components +- HTML block: Fix accessibility issues on back-end. ([54408](https://github.com/WordPress/gutenberg/pull/54408)) +- `Modal`: Accessibly hide/show outer modal when nested. ([54743](https://github.com/WordPress/gutenberg/pull/54743)) + +#### Patterns +- Use list role instead of listbox in patterns list. ([54884](https://github.com/WordPress/gutenberg/pull/54884)) + +#### Post Editor +- Editor: Always render the 'Switch to Draft' button to avoid focus loss. ([54722](https://github.com/WordPress/gutenberg/pull/54722)) + +#### Block Editor +- Block Switcher: Use a different label for multi-selection. ([54692](https://github.com/WordPress/gutenberg/pull/54692)) + + +### Performance + +- Tests: Support the Site Editor's legacy spinner. ([54784](https://github.com/WordPress/gutenberg/pull/54784)) +- Use instanceOf over property_exists. ([54835](https://github.com/WordPress/gutenberg/pull/54835)) + +#### Block Editor +- Subscribe only to block editor store in `useBlockSync`. ([55041](https://github.com/WordPress/gutenberg/pull/55041)) + + +### Experiments + +#### Site Editor +- al]: First version of pages list in site editor. ([54966](https://github.com/WordPress/gutenberg/pull/54966)) + +#### Block Editor +- Expose `getDuotoneFilter()` as private API. ([54905](https://github.com/WordPress/gutenberg/pull/54905)) + + +### Documentation + +- Add a documentation page about the block editor settings. ([54870](https://github.com/WordPress/gutenberg/pull/54870)) +- Add a page about the format library to the platform documentation site. ([55037](https://github.com/WordPress/gutenberg/pull/55037)) +- Docs: Add a callout to the `wp-now` documentation to mention it's still experimental. ([55044](https://github.com/WordPress/gutenberg/pull/55044)) +- Docs: Remove outdated info. ([54707](https://github.com/WordPress/gutenberg/pull/54707)) +- Docs: Remove the Full Site Editing doc. ([54516](https://github.com/WordPress/gutenberg/pull/54516)) +- Docs: Rename Block Hooks handbook page to Block Filters. ([54862](https://github.com/WordPress/gutenberg/pull/54862)) +- Document the current state of the Real-Time collaboration experiment. ([54932](https://github.com/WordPress/gutenberg/pull/54932)) +- Fix a broken MD link in callout. ([54772](https://github.com/WordPress/gutenberg/pull/54772)) +- Platform Docs: Add a documentation page explaining how to use the block library. ([54967](https://github.com/WordPress/gutenberg/pull/54967)) +- Update the documentation of the block editor and replace @wordpress/element with react. ([54908](https://github.com/WordPress/gutenberg/pull/54908)) +- Update versions in WP for 6.4. ([54890](https://github.com/WordPress/gutenberg/pull/54890)) + + +### Code Quality + +- Add a unit test for the "ValidBlockLibraryFunctionNameSniff" sniff. ([53928](https://github.com/WordPress/gutenberg/pull/53928)) +- Move dependencies to the right place. ([54597](https://github.com/WordPress/gutenberg/pull/54597)) +- Move mime-type collection generation to a function that can be tested…. ([54844](https://github.com/WordPress/gutenberg/pull/54844)) +- Post Title block should use esc_url(). ([53981](https://github.com/WordPress/gutenberg/pull/53981)) +- Rich text: Use getPasteEventData. ([55048](https://github.com/WordPress/gutenberg/pull/55048)) +- Writing flow: Absorb clipboard handler. ([55006](https://github.com/WordPress/gutenberg/pull/55006)) + +#### Block Library +- Footnotes: Avoid regexes in entity provider. ([54505](https://github.com/WordPress/gutenberg/pull/54505)) +- Image Block: Fix browser console error when clicking "Expand on Click". ([54938](https://github.com/WordPress/gutenberg/pull/54938)) +- Removed unwanted space from the string. ([54654](https://github.com/WordPress/gutenberg/pull/54654)) +- Update CODEOWNERS for `core/image` block. ([54793](https://github.com/WordPress/gutenberg/pull/54793)) + +#### Patterns +- Add a new spec for for adding an unsynced pattern. ([54892](https://github.com/WordPress/gutenberg/pull/54892)) +- Add end-to-end tests for filtering and searching patterns. ([54906](https://github.com/WordPress/gutenberg/pull/54906)) +- Add new end-to-end test for creating a pattern. ([54855](https://github.com/WordPress/gutenberg/pull/54855)) +- Include pattern category in main end-to-end critical path test. ([54923](https://github.com/WordPress/gutenberg/pull/54923)) + +#### Components +- Consolidate utils to remove `ui/`. ([54922](https://github.com/WordPress/gutenberg/pull/54922)) +- Move `ContextSystemProvider` out of `/ui`. ([54847](https://github.com/WordPress/gutenberg/pull/54847)) +- SlotFill: Migrate to Typescript. ([51350](https://github.com/WordPress/gutenberg/pull/51350)) +- Tidying `CircularOptionPicker.Option`. ([54903](https://github.com/WordPress/gutenberg/pull/54903)) + +#### Typography +- Font Library: Syntax refactor repace strpos with str_contains. ([54832](https://github.com/WordPress/gutenberg/pull/54832)) +- Font Library: Use snake_case instead of camelCase on fontFamilies endpoint param. ([54977](https://github.com/WordPress/gutenberg/pull/54977)) + +#### Block Editor +- Rich text: Avoid shortcode logic, adjust paste handler instead. ([55052](https://github.com/WordPress/gutenberg/pull/55052)) + +#### Plugin +- Remove legacy logic for '__unstableResolvedAssets' setting. ([54812](https://github.com/WordPress/gutenberg/pull/54812)) + +#### Data Layer +- createResolversCacheMiddleware: Remove dependency on core/data store. ([54733](https://github.com/WordPress/gutenberg/pull/54733)) + +#### Site Editor +- Use constants rather than hard coded template strings (round 3). ([54705](https://github.com/WordPress/gutenberg/pull/54705)) + + +### Tools + +- Label enforcer workflow: Make accessibility a focus instead of a type. ([54941](https://github.com/WordPress/gutenberg/pull/54941)) +- Scripts: Update webpack and related dependencies to the latest version. ([54657](https://github.com/WordPress/gutenberg/pull/54657)) +- Update changelog automation and test fixtures to match the last a11y label renaming. ([54974](https://github.com/WordPress/gutenberg/pull/54974)) + +#### Testing +- Don’t use TypeScript files in scripts package. ([54856](https://github.com/WordPress/gutenberg/pull/54856)) +- ESLint: Update eslint-plugin-testing-library to v6. ([54910](https://github.com/WordPress/gutenberg/pull/54910)) +- Fix end-to-end test: ”WP Editor Meta Boxes > Should save the changes”. ([51884](https://github.com/WordPress/gutenberg/pull/51884)) +- Font Library: Avoid deprected error in test. ([54802](https://github.com/WordPress/gutenberg/pull/54802)) +- Make `editor.getBlocks` to return only testing-related properties. ([54901](https://github.com/WordPress/gutenberg/pull/54901)) +- Migrate 'Global styles sidebar' test to Playwright. ([55045](https://github.com/WordPress/gutenberg/pull/55045)) +- Migrate 'iframed block editor settings styles' tests to Playwright. ([55014](https://github.com/WordPress/gutenberg/pull/55014)) +- Migrate 'iframed inline styles' tests to Playwright. ([55009](https://github.com/WordPress/gutenberg/pull/55009)) +- Migrate 'iframed masonry block' tests to Playwright. ([55016](https://github.com/WordPress/gutenberg/pull/55016)) +- Migrate 'iframed multiple block stylesheets' tests to Playwright. ([55003](https://github.com/WordPress/gutenberg/pull/55003)) +- Migrate keyboard-navigable-blocks end-to-end tests from puppeteer to playwright. ([54944](https://github.com/WordPress/gutenberg/pull/54944)) +- Scripts: Properly use CommonJS for default Playwright configuration. ([54988](https://github.com/WordPress/gutenberg/pull/54988)) +- Try fixing the flaky 'Toolbar roving tabindex' end-to-end test. ([54785](https://github.com/WordPress/gutenberg/pull/54785)) +- end-to-end Tests: Revert temporary fixes. ([54865](https://github.com/WordPress/gutenberg/pull/54865)) +- end-to-end Utils: Allow overriding username/password. ([53267](https://github.com/WordPress/gutenberg/pull/53267)) + +#### Build Tooling +- Add some @types packages as proper dependencies. ([50231](https://github.com/WordPress/gutenberg/pull/50231)) +- Update the default JSX pragma to React instead of @wordpress/element. ([54494](https://github.com/WordPress/gutenberg/pull/54494)) +- Upgrade wp-prettier to v3.0.3 (final). ([54775](https://github.com/WordPress/gutenberg/pull/54775)) + + +### Security + +#### Data Layer +- Replace turbo-combine-reducers with combineReducers from Redux. ([54606](https://github.com/WordPress/gutenberg/pull/54606)) + + +### Various + +- (chore) Revert the 16.7 RC2 release in order to release it again due to wrong changelog. ([54744](https://github.com/WordPress/gutenberg/pull/54744)) + +#### Design Tools +- Background image block support: Add tests, adjust injection logic slightly. ([54489](https://github.com/WordPress/gutenberg/pull/54489)) +- Background support: Backport fix for undefined array key. ([54850](https://github.com/WordPress/gutenberg/pull/54850)) + +#### Typography +- Revert "Font Library: Avoid rendering font library ui outisde gutenberg plugin". ([54947](https://github.com/WordPress/gutenberg/pull/54947)) + +#### Commands +- Make the reset styles command consistent. ([54841](https://github.com/WordPress/gutenberg/pull/54841)) + +#### Patterns +- Use "Not synced" in place of "Standard" nomenclature for patterns. ([54839](https://github.com/WordPress/gutenberg/pull/54839)) + +#### Block Editor +- Simplify BlockPatternsSyncFilter with clearer labels and additional context. ([54838](https://github.com/WordPress/gutenberg/pull/54838)) + +#### Site Editor +- Use consistent capitalization for template parts in Site Editor constants. ([54709](https://github.com/WordPress/gutenberg/pull/54709)) + + +## First time contributors + +The following PRs were merged by first time contributors: + +- @leemyongpakvn: Fix a broken MD link in callout. ([54772](https://github.com/WordPress/gutenberg/pull/54772)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @adamsilverstein @alexstine @andrewhayward @andrewserong @annezazu @anton-vlasenko @artemiomorales @aurooba @bangank36 @brookewp @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @dcalhoun @derekblank @draganescu @ellatrix @fluiddot @fullofcaffeine @geriux @getdave @glendaviesnz @gziolo @jameskoster @jeryj @jsnajdr @juhi123 @kevin940726 @leemyongpakvn @madhusudhand @MaggieCabrera @Mamaduka @matiasbenedetto @michalczaplinski @mirka @mtias @mujuonly @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ockham @pbking @priethor @ramonjd @richtabor @scruffian @SiobhyB @spacedmonkey @stokesman @swissspidy @t-hamano @tellthemachines @tellyworth @them-es @torounit @tyxla @westonruter @WunderBart @youknowriad + + + + = 16.7.1 = ## Changelog From 9f38ee31ca51887352c540d02b65cd5de69601c2 Mon Sep 17 00:00:00 2001 From: Brooke <35543432+brookewp@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:01:20 -0700 Subject: [PATCH 29/32] url: update `filterURLForDisplay` to include all image, video, and audio file types (#54920) * url: update display filter to include all file types * Restore regex with defined media files with extended list * Add tooltip to LinkPreview and remove from MediaReplaceFlow * Restore regex to display all file urls * Add test to LinkPreview to check for tooltip * Add test for filter to verify newly included formats * Update link control test based on feedback * Combine new test with existing filename test * Update const naming and add comment * Clean up test by replacing with it.each * Simplify regex to a string Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --------- Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> --- .../components/link-control/link-preview.js | 16 +++++++--- .../src/components/link-control/test/index.js | 19 ++++++++++++ .../components/media-replace-flow/index.js | 23 ++++++-------- packages/url/src/filter-url-for-display.js | 5 +-- packages/url/src/test/index.js | 31 +++++++++---------- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/components/link-control/link-preview.js b/packages/block-editor/src/components/link-control/link-preview.js index 8272602cde908..04a67d4478994 100644 --- a/packages/block-editor/src/components/link-control/link-preview.js +++ b/packages/block-editor/src/components/link-control/link-preview.js @@ -11,6 +11,7 @@ import { Button, ExternalLink, __experimentalText as Text, + Tooltip, } from '@wordpress/components'; import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url'; import { Icon, globe, info, linkOff, edit } from '@wordpress/icons'; @@ -87,12 +88,17 @@ export default function LinkPreview( { { ! isEmptyURL ? ( <> - - { displayTitle } - + + { displayTitle } + + { value?.url && displayTitle !== displayURL && ( diff --git a/packages/block-editor/src/components/link-control/test/index.js b/packages/block-editor/src/components/link-control/test/index.js index 5c44f0295249c..e0366a3f27ef5 100644 --- a/packages/block-editor/src/components/link-control/test/index.js +++ b/packages/block-editor/src/components/link-control/test/index.js @@ -2056,6 +2056,25 @@ describe( 'Addition Settings UI', () => { } ) ); } ); + + it( 'should show tooltip with full URL alongside filtered display', async () => { + const user = userEvent.setup(); + const url = + 'http://www.wordpress.org/wp-content/uploads/a-document.pdf'; + render( ); + + const link = screen.getByRole( 'link' ); + + expect( link ).toHaveTextContent( 'a-document.pdf' ); + + await user.hover( link ); + + expect( await screen.findByRole( 'tooltip' ) ).toHaveTextContent( url ); + + await user.unhover( link ); + + expect( screen.queryByRole( 'tooltip' ) ).not.toBeInTheDocument(); + } ); } ); describe( 'Post types', () => { diff --git a/packages/block-editor/src/components/media-replace-flow/index.js b/packages/block-editor/src/components/media-replace-flow/index.js index c331761af5852..33419676eaab8 100644 --- a/packages/block-editor/src/components/media-replace-flow/index.js +++ b/packages/block-editor/src/components/media-replace-flow/index.js @@ -16,7 +16,6 @@ import { ToolbarButton, Dropdown, withFilters, - Tooltip, } from '@wordpress/components'; import { useSelect, withDispatch } from '@wordpress/data'; import { DOWN } from '@wordpress/keycodes'; @@ -220,19 +219,15 @@ const MediaReplaceFlow = ( { { __( 'Current media URL:' ) } - - - { - onSelectURL( url ); - editMediaButtonRef.current.focus(); - } } - /> - - + { + onSelectURL( url ); + editMediaButtonRef.current.focus(); + } } + /> ) } > diff --git a/packages/url/src/filter-url-for-display.js b/packages/url/src/filter-url-for-display.js index 2d3247e6d1da9..eede264e8e801 100644 --- a/packages/url/src/filter-url-for-display.js +++ b/packages/url/src/filter-url-for-display.js @@ -21,12 +21,13 @@ export function filterURLForDisplay( url, maxLength = null ) { filteredURL = filteredURL.replace( '/', '' ); } - const mediaRegexp = /([\w|:])*\.(?:jpg|jpeg|gif|png|svg)/; + // capture file name from URL + const fileRegexp = /\/([^\/?]+)\.(?:[\w]+)(?=\?|$)/; if ( ! maxLength || filteredURL.length <= maxLength || - ! filteredURL.match( mediaRegexp ) + ! filteredURL.match( fileRegexp ) ) { return filteredURL; } diff --git a/packages/url/src/test/index.js b/packages/url/src/test/index.js index 9aa53dca512df..e258e112b2987 100644 --- a/packages/url/src/test/index.js +++ b/packages/url/src/test/index.js @@ -254,23 +254,20 @@ describe( 'isValidPath', () => { } ); describe( 'getFilename', () => { - it( 'returns the filename part of the URL', () => { - expect( getFilename( 'https://wordpress.org/image.jpg' ) ).toBe( - 'image.jpg' - ); - expect( - getFilename( 'https://wordpress.org/image.jpg?query=test' ) - ).toBe( 'image.jpg' ); - expect( getFilename( 'https://wordpress.org/image.jpg#anchor' ) ).toBe( - 'image.jpg' - ); - expect( - getFilename( 'http://localhost:8080/a/path/to/an/image.jpg' ) - ).toBe( 'image.jpg' ); - expect( getFilename( '/path/to/an/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( 'path/to/an/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( '/image.jpg' ) ).toBe( 'image.jpg' ); - expect( getFilename( 'image.jpg' ) ).toBe( 'image.jpg' ); + it.each( [ + [ 'https://wordpress.org/image.jpg', 'image.jpg' ], + [ 'https://wordpress.org/image.jpg?query=test', 'image.jpg' ], + [ 'https://wordpress.org/image.jpg#anchor', 'image.jpg' ], + [ 'http://localhost:8080/a/path/to/an/image.jpg', 'image.jpg' ], + [ '/path/to/an/image.jpg', 'image.jpg' ], + [ 'path/to/an/image.jpg', 'image.jpg' ], + [ '/image.jpg', 'image.jpg' ], + [ 'https://wordpress.org/file.pdf', 'file.pdf' ], + [ 'https://wordpress.org/image.webp?query=test', 'image.webp' ], + [ 'https://wordpress.org/video.mov#anchor', 'video.mov' ], + [ 'http://localhost:8080/a/path/to/audio.mp3', 'audio.mp3' ], + ] )( 'returns the filename part of the URL: %s', ( url, filename ) => { + expect( getFilename( url ) ).toBe( filename ); } ); it( 'returns undefined when the provided value does not contain a filename', () => { From c39b35245eb3fe187eb0aed5672d3e4d91906a9a Mon Sep 17 00:00:00 2001 From: Rich Tabor Date: Wed, 11 Oct 2023 17:23:46 -0400 Subject: [PATCH 30/32] Update fullscreen icon (#55021) --- packages/icons/src/library/fullscreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/icons/src/library/fullscreen.js b/packages/icons/src/library/fullscreen.js index 8b11ddcac7217..11bef7aebd612 100644 --- a/packages/icons/src/library/fullscreen.js +++ b/packages/icons/src/library/fullscreen.js @@ -5,7 +5,7 @@ import { SVG, Path } from '@wordpress/primitives'; const fullscreen = ( - + ); From d84da61d9b35da1329ac70d9ac7d158862813160 Mon Sep 17 00:00:00 2001 From: Brooke <35543432+brookewp@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:01:22 -0700 Subject: [PATCH 31/32] Toolbar: Add unstyled variant (#55139) * Toolbar: Add unstyled variant * Add variants to block editor and remove workarounds * Update stories * Add test for new variant * Update changelog * Memoize toolbar context * Clean up and improve CSS * Add to README and update phrasing * Implement feedback to simplify and optimize * Rename and simplify story by reusing default args --- .../block-tools/block-contextual-toolbar.js | 1 + .../src/components/block-tools/style.scss | 1 - .../src/components/tool-selector/index.js | 2 +- packages/components/CHANGELOG.md | 4 +++ .../src/toolbar/stories/index.story.tsx | 15 +++++++++ .../components/src/toolbar/test/index.tsx | 8 +++++ .../components/src/toolbar/toolbar/README.md | 9 +++++ .../components/src/toolbar/toolbar/index.tsx | 33 ++++++++++++------- .../components/src/toolbar/toolbar/style.scss | 9 +++++ .../components/src/toolbar/toolbar/types.ts | 10 ++++++ .../components/header/header-toolbar/index.js | 1 + .../header/header-toolbar/style.scss | 1 - 12 files changed, 79 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js index 439c3d33a3036..fcec9d56b24a8 100644 --- a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js @@ -188,6 +188,7 @@ function BlockContextualToolbar( { focusOnMount, isFixed, ...props } ) { className={ classes } /* translators: accessibility text for the block toolbar */ aria-label={ __( 'Block tools' ) } + variant={ isFixed ? 'unstyled' : undefined } { ...props } > { ! isCollapsed && } diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 796c513d6d7c2..2cb2edaf1a9c7 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -109,7 +109,6 @@ overflow-y: hidden; } - border: none; border-bottom: $border-width solid $gray-200; border-radius: 0; diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index a0df14f1a19d9..1e93a18cf6bb9 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -51,7 +51,7 @@ function ToolSelector( props, ref ) { label={ __( 'Tools' ) } /> ) } - popoverProps={ { placement: 'bottom-start', variant: undefined } } + popoverProps={ { placement: 'bottom-start' } } renderContent={ () => ( <> diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index addb5a4d9ec32..d1d87acebaa37 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -17,6 +17,10 @@ - `ConfirmDialog`: Migrate to TypeScript. ([#54954](https://github.com/WordPress/gutenberg/pull/54954)). +### New Features + +- `Toolbar`: add new `variant` prop for 'unstyled' option ([#55139](https://github.com/WordPress/gutenberg/pull/55139)). + ## 25.9.0 (2023-10-05) ### Enhancements diff --git a/packages/components/src/toolbar/stories/index.story.tsx b/packages/components/src/toolbar/stories/index.story.tsx index 2eecf54a4a493..e4fb3b07e1c90 100644 --- a/packages/components/src/toolbar/stories/index.story.tsx +++ b/packages/components/src/toolbar/stories/index.story.tsx @@ -52,6 +52,10 @@ const meta: Meta< typeof Toolbar > = { }, argTypes: { children: { control: { type: null } }, + variant: { + options: [ undefined, 'unstyled' ], + control: { type: 'radio' }, + }, }, parameters: { controls: { expanded: true }, @@ -181,3 +185,14 @@ WithoutGroup.args = { > ), }; + +/** + * Set the variant to `unstyled` to remove default border styles. + * Otherwise, leave it as `undefined` for default styles. + */ + +export const Unstyled = Template.bind( {} ); +Unstyled.args = { + ...Default.args, + variant: 'unstyled', +}; diff --git a/packages/components/src/toolbar/test/index.tsx b/packages/components/src/toolbar/test/index.tsx index c9e58edc8a80e..74c58804fc099 100644 --- a/packages/components/src/toolbar/test/index.tsx +++ b/packages/components/src/toolbar/test/index.tsx @@ -25,5 +25,13 @@ describe( 'Toolbar', () => { screen.getByLabelText( 'control2', { selector: 'button' } ) ).toBeInTheDocument(); } ); + + it( 'should apply the unstyled variant correctly via the `variant` prop', () => { + render( ); + + expect( screen.getByRole( 'toolbar' ) ).toHaveClass( + 'is-unstyled' + ); + } ); } ); } ); diff --git a/packages/components/src/toolbar/toolbar/README.md b/packages/components/src/toolbar/toolbar/README.md index 6692d3f63f34e..ee89127ded74f 100644 --- a/packages/components/src/toolbar/toolbar/README.md +++ b/packages/components/src/toolbar/toolbar/README.md @@ -71,6 +71,15 @@ An accessible label for the toolbar. - Required: Yes +#### `variant`: `'unstyled' | undefined` + +Specifies the toolbar's style. + +Leave undefined for the default style. Or `'unstyled'` which removes the border from the toolbar, but keeps the default popover style. + +- Required: No +- Default: `undefined` + ## Related components - Toolbar may contain [ToolbarGroup](/packages/components/src/toolbar-group/README.md), [ToolbarButton](/packages/components/src/toolbar-button/README.md) and [ToolbarItem](/packages/components/src/toolbar-Item/README.md) as children. diff --git a/packages/components/src/toolbar/toolbar/index.tsx b/packages/components/src/toolbar/toolbar/index.tsx index b6e83dcf6da2a..47c49b270afef 100644 --- a/packages/components/src/toolbar/toolbar/index.tsx +++ b/packages/components/src/toolbar/toolbar/index.tsx @@ -7,7 +7,7 @@ import type { ForwardedRef } from 'react'; /** * WordPress dependencies */ -import { forwardRef } from '@wordpress/element'; +import { forwardRef, useMemo } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; /** @@ -19,23 +19,30 @@ import type { ToolbarProps } from './types'; import type { WordPressComponentProps } from '../../context'; import { ContextSystemProvider } from '../../context'; -const CONTEXT_SYSTEM_VALUE = { - DropdownMenu: { - variant: 'toolbar', - }, - Dropdown: { - variant: 'toolbar', - }, -}; - function UnforwardedToolbar( { className, label, + variant, ...props }: WordPressComponentProps< ToolbarProps, 'div', false >, ref: ForwardedRef< any > ) { + const isVariantDefined = variant !== undefined; + const contextSystemValue = useMemo( () => { + if ( isVariantDefined ) { + return {}; + } + return { + DropdownMenu: { + variant: 'toolbar', + }, + Dropdown: { + variant: 'toolbar', + }, + }; + }, [ isVariantDefined ] ); + if ( ! label ) { deprecated( 'Using Toolbar without label prop', { since: '5.6', @@ -55,10 +62,12 @@ function UnforwardedToolbar( // `ToolbarGroup` already uses components-toolbar for compatibility reasons. const finalClassName = classnames( 'components-accessible-toolbar', - className + className, + variant && `is-${ variant }` ); + return ( - + .components-toolbar-group:last-child { border-right: none; } + + &.is-unstyled { + border: none; + + & > .components-toolbar-group { + border-right: none; + } + + } } .components-accessible-toolbar, diff --git a/packages/components/src/toolbar/toolbar/types.ts b/packages/components/src/toolbar/toolbar/types.ts index f6a6b9667ab4b..681f1ab2d1af2 100644 --- a/packages/components/src/toolbar/toolbar/types.ts +++ b/packages/components/src/toolbar/toolbar/types.ts @@ -12,4 +12,14 @@ export type ToolbarProps = { * An accessible label for the toolbar. */ label: string; + /** + * Specifies the toolbar's style. + * + * Leave undefined for the default style. Or `'unstyled'` which + * removes the border from the toolbar, but keeps the default + * popover style. + * + * @default undefined + */ + variant?: 'unstyled' | undefined; }; diff --git a/packages/edit-post/src/components/header/header-toolbar/index.js b/packages/edit-post/src/components/header/header-toolbar/index.js index e814f7a49072f..b86e66af7a849 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.js @@ -136,6 +136,7 @@ function HeaderToolbar( { setListViewToggleElement } ) { className="edit-post-header-toolbar" aria-label={ toolbarAriaLabel } shouldUseKeyboardFocusShortcut={ ! blockToolbarCanBeFocused } + variant="unstyled" > .components-button { From d2bf1366d55f8fad5edeebd521eda29b610d19bc Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:44:33 +1000 Subject: [PATCH 32/32] Patterns: Use modal for pattern duplication flow as workaround for changing sync status (#54764) --- .../create-template-part-modal/index.js | 14 +- .../page-patterns/duplicate-menu-item.js | 278 +++++++----------- .../components/page-patterns/use-patterns.js | 5 + .../src/components/create-pattern-modal.js | 22 +- 4 files changed, 130 insertions(+), 189 deletions(-) diff --git a/packages/edit-site/src/components/create-template-part-modal/index.js b/packages/edit-site/src/components/create-template-part-modal/index.js index 0b3a57e0c0744..31f12b6cab56d 100644 --- a/packages/edit-site/src/components/create-template-part-modal/index.js +++ b/packages/edit-site/src/components/create-template-part-modal/index.js @@ -39,17 +39,21 @@ import { } from '../../utils/template-part-create'; export default function CreateTemplatePartModal( { - closeModal, + defaultArea = TEMPLATE_PART_AREA_DEFAULT_CATEGORY, blocks = [], + confirmLabel = __( 'Create' ), + closeModal, + modalTitle = __( 'Create template part' ), onCreate, onError, + defaultTitle = '', } ) { const { createErrorNotice } = useDispatch( noticesStore ); const { saveEntityRecord } = useDispatch( coreStore ); const existingTemplateParts = useExistingTemplateParts(); - const [ title, setTitle ] = useState( '' ); - const [ area, setArea ] = useState( TEMPLATE_PART_AREA_DEFAULT_CATEGORY ); + const [ title, setTitle ] = useState( defaultTitle ); + const [ area, setArea ] = useState( defaultArea ); const [ isSubmitting, setIsSubmitting ] = useState( false ); const instanceId = useInstanceId( CreateTemplatePartModal ); @@ -104,7 +108,7 @@ export default function CreateTemplatePartModal( { return ( @@ -181,7 +185,7 @@ export default function CreateTemplatePartModal( { aria-disabled={ ! title || isSubmitting } isBusy={ isSubmitting } > - { __( 'Create' ) } + { confirmLabel } diff --git a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js index a882de95bdaeb..a0842cf9002a0 100644 --- a/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/duplicate-menu-item.js @@ -2,10 +2,11 @@ * WordPress dependencies */ import { MenuItem } from '@wordpress/components'; -import { store as coreStore } from '@wordpress/core-data'; import { useDispatch } from '@wordpress/data'; +import { useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -13,206 +14,131 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; */ import { TEMPLATE_PART_POST_TYPE, - PATTERN_TYPES, PATTERN_SYNC_TYPES, + PATTERN_TYPES, } from '../../utils/constants'; -import { - useExistingTemplateParts, - getUniqueTemplatePartTitle, - getCleanTemplatePartSlug, -} from '../../utils/template-part-create'; import { unlock } from '../../lock-unlock'; -import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories'; +import CreateTemplatePartModal from '../create-template-part-modal'; +const { CreatePatternModal } = unlock( patternsPrivateApis ); const { useHistory } = unlock( routerPrivateApis ); -function getPatternMeta( item ) { - if ( item.type === PATTERN_TYPES.theme ) { - return { wp_pattern_sync_status: PATTERN_SYNC_TYPES.unsynced }; - } - - const syncStatus = item.patternBlock.wp_pattern_sync_status; - const isUnsynced = syncStatus === PATTERN_SYNC_TYPES.unsynced; - - return { - ...item.patternBlock.meta, - wp_pattern_sync_status: isUnsynced ? syncStatus : undefined, - }; -} - export default function DuplicateMenuItem( { categoryId, item, label = __( 'Duplicate' ), onClose, } ) { - const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore ); - const { createErrorNotice, createSuccessNotice } = - useDispatch( noticesStore ); - + const { createSuccessNotice } = useDispatch( noticesStore ); + const [ isModalOpen, setIsModalOpen ] = useState( false ); const history = useHistory(); - const existingTemplateParts = useExistingTemplateParts(); - const { patternCategories } = usePatternCategories(); - async function createTemplatePart() { - try { - const copiedTitle = sprintf( - /* translators: %s: Existing template part title */ - __( '%s (Copy)' ), - item.title - ); - const title = getUniqueTemplatePartTitle( - copiedTitle, - existingTemplateParts - ); - const slug = getCleanTemplatePartSlug( title ); - const { area, content } = item.templatePart; - - const result = await saveEntityRecord( - 'postType', - TEMPLATE_PART_POST_TYPE, - { slug, title, content, area }, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: The new template part's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), - item.title - ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - - history.push( { - postType: TEMPLATE_PART_POST_TYPE, - postId: result?.id, - categoryType: TEMPLATE_PART_POST_TYPE, - categoryId, - } ); + const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; - onClose(); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( - 'An error occurred while creating the template part.' - ); - - createErrorNotice( errorMessage, { + async function onTemplatePartSuccess( templatePart ) { + createSuccessNotice( + sprintf( + // translators: %s: The new template part's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + item.title + ), + { type: 'snackbar', - id: 'edit-site-patterns-error', - } ); - onClose(); - } - } - - async function findOrCreateTerm( term ) { - try { - const newTerm = await saveEntityRecord( - 'taxonomy', - 'wp_pattern_category', - { - name: term.label, - slug: term.name, - description: term.description, - }, - { - throwOnError: true, - } - ); - invalidateResolution( 'getUserPatternCategories' ); - return newTerm.id; - } catch ( error ) { - if ( error.code !== 'term_exists' ) { - throw error; + id: 'edit-site-patterns-success', } + ); - return error.data.term_id; - } + history.push( { + postType: TEMPLATE_PART_POST_TYPE, + postId: templatePart?.id, + categoryType: TEMPLATE_PART_POST_TYPE, + categoryId, + } ); + + onClose(); } - async function getCategories( categories ) { - const terms = categories.map( ( category ) => { - const fullCategory = patternCategories.find( - ( cat ) => cat.name === category - ); - if ( fullCategory.id ) { - return fullCategory.id; + function onPatternSuccess( { pattern } ) { + createSuccessNotice( + sprintf( + // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. + __( '"%s" duplicated.' ), + pattern.title.raw + ), + { + type: 'snackbar', + id: 'edit-site-patterns-success', } - return findOrCreateTerm( fullCategory ); + ); + + history.push( { + categoryType: PATTERN_TYPES.theme, + categoryId, + postType: PATTERN_TYPES.user, + postId: pattern.id, } ); - return Promise.all( terms ); + onClose(); } - async function createPattern() { - try { - const isThemePattern = item.type === PATTERN_TYPES.theme; - const title = sprintf( - /* translators: %s: Existing pattern title */ - __( '%s (Copy)' ), - item.title || item.name - ); - const categories = await getCategories( item.categories || [] ); - - const result = await saveEntityRecord( - 'postType', - PATTERN_TYPES.user, - { - content: isThemePattern - ? item.content - : item.patternBlock.content, - meta: getPatternMeta( item ), - status: 'publish', - title, - wp_pattern_category: categories, - }, - { throwOnError: true } - ); - - createSuccessNotice( - sprintf( - // translators: %s: The new pattern's title e.g. 'Call to action (copy)'. - __( '"%s" duplicated.' ), + const isThemePattern = item.type === PATTERN_TYPES.theme; + const closeModal = () => setIsModalOpen( false ); + const duplicatedProps = isTemplatePart + ? { + blocks: item.blocks, + defaultArea: item.templatePart.area, + defaultTitle: sprintf( + /* translators: %s: Existing template part title */ + __( '%s (Copy)' ), + item.title + ), + } + : { + defaultCategories: isThemePattern + ? item.categories + : item.termLabels, + content: isThemePattern + ? item.content + : item.patternBlock.content, + defaultSyncType: isThemePattern + ? PATTERN_SYNC_TYPES.unsynced + : item.syncStatus, + defaultTitle: sprintf( + /* translators: %s: Existing pattern title */ + __( '%s (Copy)' ), item.title || item.name ), - { - type: 'snackbar', - id: 'edit-site-patterns-success', - } - ); - - history.push( { - categoryType: PATTERN_TYPES.theme, - categoryId, - postType: PATTERN_TYPES.user, - postId: result?.id, - } ); - - onClose(); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while creating the pattern.' ); - - createErrorNotice( errorMessage, { - type: 'snackbar', - id: 'edit-site-patterns-error', - } ); - onClose(); - } - } - - const createItem = - item.type === TEMPLATE_PART_POST_TYPE - ? createTemplatePart - : createPattern; - - return { label }; + }; + + return ( + <> + setIsModalOpen( true ) } + aria-expanded={ isModalOpen } + aria-haspopup="dialog" + > + { label } + + { isModalOpen && ! isTemplatePart && ( + + ) } + { isModalOpen && isTemplatePart && ( + + ) } + > + ); } diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index 6504b6f59684c..fde4eaadb5dc0 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -195,6 +195,11 @@ const patternBlockToPattern = ( patternBlock, categories ) => ( { : patternCategoryId ), } ), + termLabels: patternBlock.wp_pattern_category.map( ( patternCategoryId ) => + categories?.get( patternCategoryId ) + ? categories.get( patternCategoryId ).label + : patternCategoryId + ), id: patternBlock.id, name: patternBlock.slug, syncStatus: patternBlock.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full, diff --git a/packages/patterns/src/components/create-pattern-modal.js b/packages/patterns/src/components/create-pattern-modal.js index 37dd725ef9226..6dd162605506e 100644 --- a/packages/patterns/src/components/create-pattern-modal.js +++ b/packages/patterns/src/components/create-pattern-modal.js @@ -28,15 +28,21 @@ import CategorySelector, { CATEGORY_SLUG } from './category-selector'; import { unlock } from '../lock-unlock'; export default function CreatePatternModal( { - onSuccess, - onError, + confirmLabel = __( 'Create' ), + defaultCategories = [], + className = 'patterns-menu-items__convert-modal', content, + modalTitle = __( 'Create pattern' ), onClose, - className = 'patterns-menu-items__convert-modal', + onError, + onSuccess, + defaultSyncType = PATTERN_SYNC_TYPES.full, + defaultTitle = '', } ) { - const [ syncType, setSyncType ] = useState( PATTERN_SYNC_TYPES.full ); - const [ categoryTerms, setCategoryTerms ] = useState( [] ); - const [ title, setTitle ] = useState( '' ); + const [ syncType, setSyncType ] = useState( defaultSyncType ); + const [ categoryTerms, setCategoryTerms ] = useState( defaultCategories ); + const [ title, setTitle ] = useState( defaultTitle ); + const [ isSaving, setIsSaving ] = useState( false ); const { createPattern } = unlock( useDispatch( patternsStore ) ); const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore ); @@ -145,7 +151,7 @@ export default function CreatePatternModal( { return ( { onClose(); setTitle( '' ); @@ -203,7 +209,7 @@ export default function CreatePatternModal( { aria-disabled={ ! title || isSaving } isBusy={ isSaving } > - { __( 'Create' ) } + { confirmLabel }
A
B