From 74a2ba4e81805ad6e9867f1051e434e6b2e470f2 Mon Sep 17 00:00:00 2001 From: Eshaan Dabasiya <76681468+im3dabasia@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:58:22 +0530 Subject: [PATCH 01/23] TextControl: Fix text direction for URL and email fields in block editor for RTL languages (#68561) * fix: add ltr for email and url in the textcontrol component * doc: Add changelog * doc: Add changelog in unreleased section * doc: Update changelog Co-authored-by: im3dabasia Co-authored-by: t-hamano --- packages/block-library/src/form/edit.js | 2 ++ packages/block-library/src/navigation-link/edit.js | 1 + packages/block-library/src/navigation-submenu/edit.js | 1 + packages/components/CHANGELOG.md | 5 +++++ packages/components/src/text-control/style.scss | 6 ++++++ 5 files changed, 15 insertions(+) diff --git a/packages/block-library/src/form/edit.js b/packages/block-library/src/form/edit.js index a7260afabedf3..227f5ea05014f 100644 --- a/packages/block-library/src/form/edit.js +++ b/packages/block-library/src/form/edit.js @@ -123,6 +123,7 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { help={ __( 'The email address where form submissions will be sent. Separate multiple email addresses with a comma.' ) } + type="email" /> ) } @@ -159,6 +160,7 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { help={ __( 'The URL where the form should be submitted.' ) } + type="url" /> ) } diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index 11a281a44a76d..e3018c274ef78 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -201,6 +201,7 @@ function Controls( { attributes, setAttributes, setIsLabelFieldFocused } ) { ); } } autoComplete="off" + type="url" /> diff --git a/packages/block-library/src/navigation-submenu/edit.js b/packages/block-library/src/navigation-submenu/edit.js index b5f40ffb67677..00ee02c50920f 100644 --- a/packages/block-library/src/navigation-submenu/edit.js +++ b/packages/block-library/src/navigation-submenu/edit.js @@ -431,6 +431,7 @@ export default function NavigationSubmenuEdit( { } } label={ __( 'Link' ) } autoComplete="off" + type="url" /> diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 6917427ef1571..5cdf14f89937f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,7 +2,12 @@ ## Unreleased +### Bug Fixes + +- `TextControl`: Ensures email and url inputs have consistent LTR alignment in RTL languages ([#68561](https://github.com/WordPress/gutenberg/pull/68561)). + ### Enhancement + - `BorderControlDropdown`, `BorderControl`: Reset button is always visible. ([#69066](https://github.com/WordPress/gutenberg/pull/69066)). ### Internal diff --git a/packages/components/src/text-control/style.scss b/packages/components/src/text-control/style.scss index 5ae2a90b82773..3e59c47532a61 100644 --- a/packages/components/src/text-control/style.scss +++ b/packages/components/src/text-control/style.scss @@ -28,3 +28,9 @@ padding-right: $grid-unit-15; } } + +.components-text-control__input[type="email"], +.components-text-control__input[type="url"] { + /* rtl:ignore */ + direction: ltr; +} From d181ce44648e6af799264ccae0eb48d0237579ba Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Mon, 24 Feb 2025 22:12:55 +0400 Subject: [PATCH 02/23] Editor: Use a stable array ref as fallback value in 'BlockVisibility' (#69288) Co-authored-by: Mamaduka Co-authored-by: t-hamano --- .../src/components/preferences-modal/block-visibility.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/preferences-modal/block-visibility.js b/packages/editor/src/components/preferences-modal/block-visibility.js index 8726b114d9748..fc6deab6b5fb5 100644 --- a/packages/editor/src/components/preferences-modal/block-visibility.js +++ b/packages/editor/src/components/preferences-modal/block-visibility.js @@ -14,6 +14,7 @@ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; const { BlockManager } = unlock( blockEditorPrivateApis ); +const EMPTY_ARRAY = []; export default function BlockVisibility() { const { showBlockTypes, hideBlockTypes } = unlock( @@ -31,7 +32,7 @@ export default function BlockVisibility() { select( editorStore ).getEditorSettings().allowedBlockTypes, hiddenBlockTypes: select( preferencesStore ).get( 'core', 'hiddenBlockTypes' ) ?? - [], + EMPTY_ARRAY, }; }, [] ); From 77da6c24e9cf5d4b06658a471d3daa5cbdd2e475 Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Tue, 25 Feb 2025 08:51:02 +0530 Subject: [PATCH 03/23] Added php.net/date links (#69280) * Added php.net/date links * Added php.net/date links Co-authored-by: shail-mehta Co-authored-by: t-hamano --- packages/date/README.md | 10 +++++----- packages/date/src/index.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/date/README.md b/packages/date/README.md index 4f0a64c24aa71..a7543df01cd63 100644 --- a/packages/date/README.md +++ b/packages/date/README.md @@ -27,7 +27,7 @@ _Related_ _Parameters_ -- _dateFormat_ `string`: PHP-style formatting string. See php.net/date. +- _dateFormat_ `string`: PHP-style formatting string. See [php.net/date](https://www.php.net/manual/en/function.date.php). - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. - _timezone_ `string | number | undefined`: Timezone to output result in or a UTC offset. Defaults to timezone from site. @@ -48,7 +48,7 @@ _Related_ _Parameters_ -- _dateFormat_ `string`: PHP-style formatting string. See php.net/date. +- _dateFormat_ `string`: PHP-style formatting string. See [php.net/date](https://www.php.net/manual/en/function.date.php). - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. - _timezone_ `string | number | boolean | undefined=`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons. @@ -62,7 +62,7 @@ Formats a date. Does not alter the date's timezone. _Parameters_ -- _dateFormat_ `string`: PHP-style formatting string. See php.net/date. +- _dateFormat_ `string`: PHP-style formatting string. See [php.net/date](https://www.php.net/manual/en/function.date.php). - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. _Returns_ @@ -95,7 +95,7 @@ Formats a date (like `date()` in PHP), in the UTC timezone. _Parameters_ -- _dateFormat_ `string`: PHP-style formatting string. See php.net/date. +- _dateFormat_ `string`: PHP-style formatting string. See [php.net/date](https://www.php.net/manual/en/function.date.php). - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. _Returns_ @@ -108,7 +108,7 @@ Formats a date (like `wp_date()` in PHP), translating it into site's locale and _Parameters_ -- _dateFormat_ `string`: PHP-style formatting string. See php.net/date. +- _dateFormat_ `string`: PHP-style formatting string. See [php.net/date](https://www.php.net/manual/en/function.date.php). - _dateValue_ `Moment | Date | string | undefined`: Date object or string, parsable by moment.js. _Returns_ diff --git a/packages/date/src/index.js b/packages/date/src/index.js index 8d8f53fd8bc10..5af8b5f4780e8 100644 --- a/packages/date/src/index.js +++ b/packages/date/src/index.js @@ -445,7 +445,7 @@ const formatMap = { * Formats a date. Does not alter the date's timezone. * * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. + * See [php.net/date](https://www.php.net/manual/en/function.date.php). * @param {Moment | Date | string | undefined} dateValue Date object or string, * parsable by moment.js. * @@ -487,7 +487,7 @@ export function format( dateFormat, dateValue = new Date() ) { * Formats a date (like `date()` in PHP). * * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. + * See [php.net/date](https://www.php.net/manual/en/function.date.php). * @param {Moment | Date | string | undefined} dateValue Date object or string, parsable * by moment.js. * @param {string | number | undefined} timezone Timezone to output result in or a @@ -508,7 +508,7 @@ export function date( dateFormat, dateValue = new Date(), timezone ) { * Formats a date (like `date()` in PHP), in the UTC timezone. * * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. + * See [php.net/date](https://www.php.net/manual/en/function.date.php). * @param {Moment | Date | string | undefined} dateValue Date object or string, * parsable by moment.js. * @@ -526,7 +526,7 @@ export function gmdate( dateFormat, dateValue = new Date() ) { * behaves like `gmdateI18n`. * * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. + * See [php.net/date](https://www.php.net/manual/en/function.date.php). * @param {Moment | Date | string | undefined} dateValue Date object or string, parsable by * moment.js. * @param {string | number | boolean | undefined=} timezone Timezone to output result in or a @@ -559,7 +559,7 @@ export function dateI18n( dateFormat, dateValue = new Date(), timezone ) { * and using the UTC timezone. * * @param {string} dateFormat PHP-style formatting string. - * See php.net/date. + * See [php.net/date](https://www.php.net/manual/en/function.date.php). * @param {Moment | Date | string | undefined} dateValue Date object or string, * parsable by moment.js. * From 3e6ddf90261a6e25b9b5610dbbe0255a576c9624 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 25 Feb 2025 13:17:31 +0900 Subject: [PATCH 04/23] Block support: Add server-side processing for ariaLabel (#69096) * Block support: Add server-side processing for ariaLabel * Add backport changelog * Add unit test Co-authored-by: t-hamano Co-authored-by: carolinan Co-authored-by: Mamaduka Co-authored-by: aaronrobertshaw Co-authored-by: joemcgill Co-authored-by: fabiankaegy --- backport-changelog/6.8/8274.md | 3 + lib/block-supports/aria-label.php | 63 ++++++++++++++++ lib/load.php | 1 + phpunit/block-supports/aria-label-test.php | 85 ++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 backport-changelog/6.8/8274.md create mode 100644 lib/block-supports/aria-label.php create mode 100644 phpunit/block-supports/aria-label-test.php diff --git a/backport-changelog/6.8/8274.md b/backport-changelog/6.8/8274.md new file mode 100644 index 0000000000000..f841a6f010d6d --- /dev/null +++ b/backport-changelog/6.8/8274.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/8274 + +* https://github.com/WordPress/gutenberg/pull/69096 diff --git a/lib/block-supports/aria-label.php b/lib/block-supports/aria-label.php new file mode 100644 index 0000000000000..062ff027bf594 --- /dev/null +++ b/lib/block-supports/aria-label.php @@ -0,0 +1,63 @@ +attributes ) { + $block_type->attributes = array(); + } + + if ( ! array_key_exists( 'ariaLabel', $block_type->attributes ) ) { + $block_type->attributes['ariaLabel'] = array( + 'type' => 'string', + ); + } +} + +/** + * Add the aria-label to the output. + * + * @param WP_Block_Type $block_type Block Type. + * @param array $block_attributes Block attributes. + * + * @return array Block aria-label. + */ +function gutenberg_apply_aria_label_support( $block_type, $block_attributes ) { + if ( ! $block_attributes ) { + return array(); + } + + $has_aria_label_support = block_has_support( $block_type, array( 'ariaLabel' ), false ); + if ( ! $has_aria_label_support ) { + return array(); + } + + $has_aria_label = array_key_exists( 'ariaLabel', $block_attributes ); + if ( ! $has_aria_label ) { + return array(); + } + return array( 'aria-label' => $block_attributes['ariaLabel'] ); +} + +// Register the block support. +WP_Block_Supports::get_instance()->register( + 'aria-label', + array( + 'register_attribute' => 'gutenberg_register_aria_label_support', + 'apply' => 'gutenberg_apply_aria_label_support', + ) +); diff --git a/lib/load.php b/lib/load.php index 769066111fb95..25b5189010909 100644 --- a/lib/load.php +++ b/lib/load.php @@ -178,6 +178,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/block-supports/shadow.php'; require __DIR__ . '/block-supports/background.php'; require __DIR__ . '/block-supports/block-style-variations.php'; +require __DIR__ . '/block-supports/aria-label.php'; // Data views. require_once __DIR__ . '/experimental/data-views.php'; diff --git a/phpunit/block-supports/aria-label-test.php b/phpunit/block-supports/aria-label-test.php new file mode 100644 index 0000000000000..52b14edd5b67c --- /dev/null +++ b/phpunit/block-supports/aria-label-test.php @@ -0,0 +1,85 @@ +test_block_name = null; + } + + public function tear_down() { + unregister_block_type( $this->test_block_name ); + $this->test_block_name = null; + parent::tear_down(); + } + + /** + * Registers a new block for testing aria-label support. + * + * @param string $block_name Name for the test block. + * @param array $supports Array defining block support configuration. + * + * @return WP_Block_Type The block type for the newly registered test block. + */ + private function register_aria_label_block_with_support( $block_name, $supports = array() ) { + $this->test_block_name = $block_name; + register_block_type( + $this->test_block_name, + array( + 'api_version' => 3, + 'supports' => $supports, + ) + ); + $registry = WP_Block_Type_Registry::get_instance(); + + return $registry->get_registered( $this->test_block_name ); + } + + /** + * Tests that position block support works as expected. + * + * @dataProvider data_aria_label_block_support + * + * @param boolean|array $support Aria label block support configuration. + * @param string $value Aria label value for attribute object. + * @param array $expected Expected aria label block support styles. + */ + public function test_gutenberg_apply_aria_label_support( $support, $value, $expected ) { + $block_type = self::register_aria_label_block_with_support( + 'test/aria-label-block', + array( 'ariaLabel' => $support ) + ); + $block_attrs = array( 'ariaLabel' => $value ); + $actual = gutenberg_apply_aria_label_support( $block_type, $block_attrs ); + + $this->assertSame( $expected, $actual ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_aria_label_block_support() { + return array( + 'aria-label attribute is applied' => array( + 'support' => true, + 'value' => 'Label', + 'expected' => array( 'aria-label' => 'Label' ), + ), + 'aria-label attribute is not applied if block does not support it' => array( + 'support' => false, + 'value' => 'Label', + 'expected' => array(), + ), + ); + } +} From e532b746c40101e2468383ecbfa92cc5ee244069 Mon Sep 17 00:00:00 2001 From: tomoki shimomura Date: Tue, 25 Feb 2025 15:38:43 +0900 Subject: [PATCH 05/23] Format Library: Prevent the text and color picker from overlapping (#69169) Co-authored-by: shimotmk Co-authored-by: Mamaduka --- packages/format-library/src/text-color/inline.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/format-library/src/text-color/inline.js b/packages/format-library/src/text-color/inline.js index bc1e0eef07b0c..a14240ed9f489 100644 --- a/packages/format-library/src/text-color/inline.js +++ b/packages/format-library/src/text-color/inline.js @@ -142,6 +142,8 @@ function ColorPicker( { name, property, value, onChange } ) { setColors( value, name, colors, { [ property ]: color } ) ); } } + // Prevent the text and color picker from overlapping. + __experimentalIsRenderedInSidebar /> ); } From 9a495f826ed344359df89b79f26b5759e36451fe Mon Sep 17 00:00:00 2001 From: Ankit Kumar Shah Date: Tue, 25 Feb 2025 13:55:50 +0530 Subject: [PATCH 06/23] Test: Add e2e test for 404 page (#69272) * Add e2e test for 404 page * Improve navigation test * Remove unnecessery `visitSiteEditor()` Co-authored-by: Infinite-Null Co-authored-by: t-hamano Co-authored-by: Mamaduka --- test/e2e/specs/site-editor/navigation.spec.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/e2e/specs/site-editor/navigation.spec.js b/test/e2e/specs/site-editor/navigation.spec.js index 18eb6c9904b44..2a886c2048f88 100644 --- a/test/e2e/specs/site-editor/navigation.spec.js +++ b/test/e2e/specs/site-editor/navigation.spec.js @@ -106,6 +106,23 @@ test.describe( 'Site editor navigation', () => { // We should have our editor canvas button back await expect( editorCanvasButton ).toBeVisible(); } ); + + test( 'Should show 404 page when navigating to non-existent template', async ( { + admin, + page, + } ) => { + // Navigate to a non-existent template. + await admin.visitAdminPage( 'site-editor.php', 'p=/template-foo-bar' ); + + // Verify the 404 error notice is displayed with the correct message. + await expect( + page.locator( + '.edit-site-layout__area .components-notice__content' + ) + ).toHaveText( + 'The requested page could not be found. Please check the URL.' + ); + } ); } ); class EditorNavigationUtils { From db7153125f6dcbd7135ac12af3adc6e56f96109f Mon Sep 17 00:00:00 2001 From: Andrea Fercia Date: Tue, 25 Feb 2025 14:48:30 +0100 Subject: [PATCH 07/23] Swap fullscreen mode snackbar notice message. (#69305) Co-authored-by: afercia Co-authored-by: carolinan --- packages/edit-post/src/store/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index 85702ae162285..959c63083a9d3 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -530,8 +530,8 @@ export const toggleFullscreenMode = .dispatch( noticesStore ) .createInfoNotice( isFullscreen - ? __( 'Fullscreen mode activated.' ) - : __( 'Fullscreen mode deactivated.' ), + ? __( 'Fullscreen mode deactivated.' ) + : __( 'Fullscreen mode activated.' ), { id: 'core/edit-post/toggle-fullscreen-mode/notice', type: 'snackbar', From ac34493785a413d666098e3115a6352fb8c17714 Mon Sep 17 00:00:00 2001 From: Bernie Reiter <96308+ockham@users.noreply.github.com> Date: Tue, 25 Feb 2025 20:59:36 +0100 Subject: [PATCH 08/23] Template Part block: Guard against `get_block_file_template` returning `null` (#69309) Co-authored-by: ockham Co-authored-by: paulopmt1 Co-authored-by: josephscott --- packages/block-library/src/template-part/index.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/template-part/index.php b/packages/block-library/src/template-part/index.php index be867c4ced166..c73b64408733d 100644 --- a/packages/block-library/src/template-part/index.php +++ b/packages/block-library/src/template-part/index.php @@ -70,7 +70,9 @@ function render_block_core_template_part( $attributes ) { if ( 0 === validate_file( $attributes['slug'] ) ) { $block_template = get_block_file_template( $template_part_id, 'wp_template_part' ); - $content = $block_template->content; + if ( isset( $block_template->content ) ) { + $content = $block_template->content; + } if ( isset( $block_template->area ) ) { $area = $block_template->area; } From e757d1d5d8a72a37927a49beea7ebfe72adb65f0 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Tue, 25 Feb 2025 20:28:38 +0000 Subject: [PATCH 09/23] Update Changelog for 20.0.3 --- changelog.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/changelog.txt b/changelog.txt index 68e13890ff280..a15d9c02edc90 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,28 @@ == Changelog == += 20.0.3 = + +## Changelog + +### Bug Fixes + +#### Block Hooks + +- Fix truncation of post content. (https://github.com/WordPress/gutenberg/pull/68926) +- Fix duplicated insertion in Post Content. (https://github.com/WordPress/gutenberg/pull/69142) +- Enable first/last child insertion next to Classic block. (https://github.com/WordPress/gutenberg/pull/69241) + +#### Block Library + +- Template Part block: Guard against `get_block_file_template` returning `null`. (https://github.com/WordPress/gutenberg/pull/69309) + +### Code Quality + +#### Block Hooks + +- Add end-to-end test Coverage. (https://github.com/WordPress/gutenberg/pull/69044) + + = 20.0.2 = ### Bug Fixes From 7a4b5aa5d8a63d97b084e1339e6ce544dfc944bb Mon Sep 17 00:00:00 2001 From: David Aguilera Date: Wed, 26 Feb 2025 09:08:49 +0100 Subject: [PATCH 10/23] Url: Fix addQueryArgs and removeQueryArg on URLs with fragments (#69313) Co-authored-by: davilera Co-authored-by: paaljoachim Co-authored-by: gziolo --- packages/url/src/add-query-args.js | 6 ++-- packages/url/src/remove-query-args.js | 8 ++++-- packages/url/src/test/index.js | 40 ++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/packages/url/src/add-query-args.js b/packages/url/src/add-query-args.js index c47c33813c16b..556a3fb706a44 100644 --- a/packages/url/src/add-query-args.js +++ b/packages/url/src/add-query-args.js @@ -3,6 +3,7 @@ */ import { getQueryArgs } from './get-query-args'; import { buildQueryString } from './build-query-string'; +import { getFragment } from './get-fragment'; /** * Appends arguments as querystring to the provided URL. If the URL already @@ -26,7 +27,8 @@ export function addQueryArgs( url = '', args ) { return url; } - let baseUrl = url; + const fragment = getFragment( url ) || ''; + let baseUrl = url.replace( fragment, '' ); // Determine whether URL already had query arguments. const queryStringIndex = url.indexOf( '?' ); @@ -38,5 +40,5 @@ export function addQueryArgs( url = '', args ) { baseUrl = baseUrl.substr( 0, queryStringIndex ); } - return baseUrl + '?' + buildQueryString( args ); + return baseUrl + '?' + buildQueryString( args ) + fragment; } diff --git a/packages/url/src/remove-query-args.js b/packages/url/src/remove-query-args.js index 07fd5467808e0..5d31313b08a74 100644 --- a/packages/url/src/remove-query-args.js +++ b/packages/url/src/remove-query-args.js @@ -18,14 +18,18 @@ import { buildQueryString } from './build-query-string'; * @return {string} Updated URL. */ export function removeQueryArgs( url, ...args ) { + const fragment = url.replace( /^[^#]*/, '' ); + url = url.replace( /#.*/, '' ); + const queryStringIndex = url.indexOf( '?' ); if ( queryStringIndex === -1 ) { - return url; + return url + fragment; } const query = getQueryArgs( url ); const baseURL = url.substr( 0, queryStringIndex ); args.forEach( ( arg ) => delete query[ arg ] ); const queryString = buildQueryString( query ); - return queryString ? baseURL + '?' + queryString : baseURL; + const updatedUrl = queryString ? baseURL + '?' + queryString : baseURL; + return updatedUrl + fragment; } diff --git a/packages/url/src/test/index.js b/packages/url/src/test/index.js index 3d622ad2d8db7..763c2e71c9fcb 100644 --- a/packages/url/src/test/index.js +++ b/packages/url/src/test/index.js @@ -636,7 +636,7 @@ describe( 'addQueryArgs', () => { ); } ); - it( 'should encodes spaces by RFC 3986', () => { + it( 'should encode spaces by RFC 3986', () => { const url = 'https://andalouses.example/beach'; const args = { activity: 'fun in the sun' }; @@ -652,6 +652,15 @@ describe( 'addQueryArgs', () => { expect( addQueryArgs( url, args ) ).toBe( '?sun=true' ); } ); + it( 'should add query args before the url fragment', () => { + const url = 'https://andalouses.example/beach/#fragment'; + const args = { sun: 'true' }; + + expect( addQueryArgs( url, args ) ).toBe( + 'https://andalouses.example/beach/?sun=true#fragment' + ); + } ); + it( 'should return URL argument unaffected if no query arguments to append', () => { [ '', 'https://example.com', 'https://example.com?' ].forEach( ( url ) => { @@ -796,6 +805,12 @@ describe( 'getQueryArg', () => { expect( getQueryArg( url, 'baz' ) ).toBeUndefined(); } ); + it( 'should not return what looks like a query arg after the url fragment', () => { + const url = 'https://andalouses.example/beach#fragment?foo=bar&bar=baz'; + + expect( getQueryArg( url, 'foo' ) ).toBeUndefined(); + } ); + it( 'should get the value of an array query arg', () => { const url = 'https://andalouses.example/beach?foo[]=bar&foo[]=baz'; @@ -823,6 +838,12 @@ describe( 'hasQueryArg', () => { expect( hasQueryArg( url, 'baz' ) ).toBeFalsy(); } ); + it( 'should return false if the query arg is after url fragment', () => { + const url = 'https://andalouses.example/beach#fragment?foo=bar&bar=baz'; + + expect( hasQueryArg( url, 'foo' ) ).toBeFalsy(); + } ); + it( 'should return true for an array query arg', () => { const url = 'https://andalouses.example/beach?foo[]=bar&foo[]=baz'; @@ -867,6 +888,23 @@ describe( 'removeQueryArgs', () => { 'https://andalouses.example/beach?bar=foobar' ); } ); + + it( 'should not remove the url fragment', () => { + const url = + 'https://andalouses.example/beach?foo=bar¶m=value#fragment'; + + expect( removeQueryArgs( url, 'foo' ) ).toEqual( + 'https://andalouses.example/beach?param=value#fragment' + ); + } ); + + it( 'should not remove what looks like a query arg after url fragment', () => { + const url = 'https://andalouses.example/beach#fragment?foo=bar'; + + expect( removeQueryArgs( url, 'foo' ) ).toEqual( + 'https://andalouses.example/beach#fragment?foo=bar' + ); + } ); } ); describe( 'prependHTTP', () => { From c283695c24e674526716b7df6875b99ece80a802 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 26 Feb 2025 19:03:59 +0400 Subject: [PATCH 11/23] Editor: Persist user's 'Show Template' preference (#69286) * Editor: Persist user's 'Show Template' preference * Extract logic and finalize * Simplify the fallback condition * Restore previous preloading e2e test assertion * Fix mobile unit tests * Don't call 'setRenderingMode' while 'defaultMode' is undefined * Metabox: Check default rendering mode before initialization * Cleanup selector getters Co-authored-by: Mamaduka Co-authored-by: t-hamano Co-authored-by: fabiankaegy Co-authored-by: joemcgill Co-authored-by: yogeshbhutkar Co-authored-by: jasmussen Co-authored-by: annezazu --- .../edit-post/src/components/layout/index.js | 29 ++++++---- .../components/post-template/block-theme.js | 14 +++-- .../src/components/preview-dropdown/index.js | 14 +++-- .../editor/src/components/provider/index.js | 50 +++++++--------- packages/editor/src/store/private-actions.js | 33 +++++++++++ .../editor/src/store/private-selectors.js | 57 +++++++++++++++++++ test/e2e/specs/site-editor/preload.spec.js | 3 + .../initialize-editor.js | 2 +- 8 files changed, 148 insertions(+), 54 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 3f9f71b4f4de8..a3deb4a1ba79d 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -379,6 +379,7 @@ function Layout( { const { mode, isFullscreenActive, + hasResolvedMode, hasActiveMetaboxes, hasBlockSelected, showIconLabels, @@ -390,7 +391,7 @@ function Layout( { } = useSelect( ( select ) => { const { get } = select( preferencesStore ); - const { isFeatureActive } = select( editPostStore ); + const { isFeatureActive, hasMetaBoxes } = select( editPostStore ); const { canUser, getPostType, getTemplateId } = unlock( select( coreStore ) ); @@ -402,22 +403,29 @@ function Layout( { kind: 'postType', name: 'wp_template', } ); - const { isZoomOut } = unlock( select( blockEditorStore ) ); - const { getEditorMode, getRenderingMode } = select( editorStore ); + const { getBlockSelectionStart, isZoomOut } = unlock( + select( blockEditorStore ) + ); + const { getEditorMode, getRenderingMode, getDefaultRenderingMode } = + unlock( select( editorStore ) ); const isRenderingPostOnly = getRenderingMode() === 'post-only'; const isNotDesignPostType = ! DESIGN_POST_TYPES.includes( currentPostType ); const isDirectlyEditingPattern = currentPostType === 'wp_block' && ! onNavigateToPreviousEntityRecord; + const _templateId = getTemplateId( currentPostType, currentPostId ); + const defaultMode = getDefaultRenderingMode( currentPostType ); return { mode: getEditorMode(), - isFullscreenActive: - select( editPostStore ).isFeatureActive( 'fullscreenMode' ), - hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(), - hasBlockSelected: - !! select( blockEditorStore ).getBlockSelectionStart(), + isFullscreenActive: isFeatureActive( 'fullscreenMode' ), + hasActiveMetaboxes: hasMetaBoxes(), + hasResolvedMode: + defaultMode === 'template-locked' + ? !! _templateId + : defaultMode !== undefined, + hasBlockSelected: !! getBlockSelectionStart(), showIconLabels: get( 'core', 'showIconLabels' ), isDistractionFree: get( 'core', 'distractionFree' ), showMetaBoxes: @@ -429,7 +437,7 @@ function Layout( { isViewable && canViewTemplate && ! isEditingTemplate - ? getTemplateId( currentPostType, currentPostId ) + ? _templateId : null, enablePaddingAppender: ! isZoomOut() && isRenderingPostOnly && isNotDesignPostType, @@ -443,7 +451,8 @@ function Layout( { onNavigateToPreviousEntityRecord, ] ); - useMetaBoxInitialization( hasActiveMetaboxes ); + + useMetaBoxInitialization( hasActiveMetaboxes && hasResolvedMode ); const [ paddingAppenderRef, paddingStyle ] = usePaddingAppender( enablePaddingAppender diff --git a/packages/editor/src/components/post-template/block-theme.js b/packages/editor/src/components/post-template/block-theme.js index 6d7f7f787b32f..8089e187233e0 100644 --- a/packages/editor/src/components/post-template/block-theme.js +++ b/packages/editor/src/components/post-template/block-theme.js @@ -53,7 +53,9 @@ export default function BlockThemeControl( { id } ) { id ); const { createSuccessNotice } = useDispatch( noticesStore ); - const { setRenderingMode } = useDispatch( editorStore ); + const { setRenderingMode, setDefaultRenderingMode } = unlock( + useDispatch( editorStore ) + ); const canCreateTemplate = useSelect( ( select ) => @@ -149,11 +151,11 @@ export default function BlockThemeControl( { id } ) { isSelected={ ! isTemplateHidden } role="menuitemcheckbox" onClick={ () => { - setRenderingMode( - isTemplateHidden - ? 'template-locked' - : 'post-only' - ); + const newRenderingMode = isTemplateHidden + ? 'template-locked' + : 'post-only'; + setRenderingMode( newRenderingMode ); + setDefaultRenderingMode( newRenderingMode ); } } > { __( 'Show template' ) } diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js index a081564e48ea8..3fa1e211bb7d3 100644 --- a/packages/editor/src/components/preview-dropdown/index.js +++ b/packages/editor/src/components/preview-dropdown/index.js @@ -56,7 +56,9 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { templateId: getCurrentTemplateId(), }; }, [] ); - const { setDeviceType, setRenderingMode } = useDispatch( editorStore ); + const { setDeviceType, setRenderingMode, setDefaultRenderingMode } = unlock( + useDispatch( editorStore ) + ); const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); const handleDevicePreviewChange = ( newDeviceType ) => { @@ -160,11 +162,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) { isSelected={ ! isTemplateHidden } role="menuitemcheckbox" onClick={ () => { - setRenderingMode( - isTemplateHidden - ? 'template-locked' - : 'post-only' - ); + const newRenderingMode = isTemplateHidden + ? 'template-locked' + : 'post-only'; + setRenderingMode( newRenderingMode ); + setDefaultRenderingMode( newRenderingMode ); } } > { __( 'Show template' ) } diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 0e653228fee62..3e9afe3363b1a 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -56,11 +56,6 @@ const NON_CONTEXTUAL_POST_TYPES = [ 'wp_template_part', ]; -/** - * These are rendering modes that the editor supports. - */ -const RENDERING_MODES = [ 'post-only', 'template-locked' ]; - /** * Depending on the post, template and template mode, * returns the appropriate blocks and change handlers for the block editor provider. @@ -183,37 +178,28 @@ export const ExperimentalEditorProvider = withRegistryProvider( getEditorSelection, getRenderingMode, __unstableIsEditorReady, - } = select( editorStore ); - const { - getEntitiesConfig, - getPostType, - hasFinishedResolution, - } = select( coreStore ); - - const postTypeSupports = getPostType( post.type )?.supports; - const hasLoadedPostObject = hasFinishedResolution( - 'getPostType', - [ post.type ] - ); - - const _defaultMode = Array.isArray( postTypeSupports?.editor ) - ? postTypeSupports.editor.find( - ( features ) => 'default-mode' in features - )?.[ 'default-mode' ] - : undefined; - const hasDefaultMode = RENDERING_MODES.includes( _defaultMode ); - - // Wait for template resolution when rendering in a `template-locked` mode. + getDefaultRenderingMode, + } = unlock( select( editorStore ) ); + const { getEntitiesConfig } = select( coreStore ); + + const _defaultMode = getDefaultRenderingMode( post.type ); + /** + * To avoid content "flash", wait until rendering mode has been resolved. + * This is important for the initial render of the editor. + * + * - Wait for template to be resolved if the default mode is 'template-locked'. + * - Wait for default mode to be resolved otherwise. + */ const hasResolvedMode = - hasLoadedPostObject && _defaultMode === 'template-locked' + _defaultMode === 'template-locked' ? hasTemplate - : true; + : _defaultMode !== undefined; return { editorSettings: getEditorSettings(), isReady: __unstableIsEditorReady() && hasResolvedMode, mode: getRenderingMode(), - defaultMode: hasDefaultMode ? _defaultMode : 'post-only', + defaultMode: _defaultMode, selection: getEditorSelection(), postTypeEntities: post.type === 'wp_template' @@ -224,7 +210,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( [ post.type, hasTemplate ] ); - const shouldRenderTemplate = !! template && mode !== 'post-only'; + const shouldRenderTemplate = hasTemplate && mode !== 'post-only'; const rootLevelPost = shouldRenderTemplate ? template : post; const defaultBlockContext = useMemo( () => { const postContext = {}; @@ -341,7 +327,9 @@ export const ExperimentalEditorProvider = withRegistryProvider( // Sets the right rendering mode when loading the editor. useEffect( () => { - setRenderingMode( defaultMode ); + if ( defaultMode ) { + setRenderingMode( defaultMode ); + } }, [ defaultMode, setRenderingMode ] ); useHideBlocksFromInserter( post.type, mode ); diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index 6a83b3ca0b403..f1aa458fdab98 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -492,3 +492,36 @@ export const removeTemplates = .createErrorNotice( errorMessage, { type: 'snackbar' } ); } }; + +/** + * Set the default rendering mode preference for the current post type. + * + * @param {string} mode The rendering mode to set as default. + */ +export const setDefaultRenderingMode = + ( mode ) => + ( { select, registry } ) => { + const postType = select.getCurrentPostType(); + const theme = registry + .select( coreStore ) + .getCurrentTheme()?.stylesheet; + const renderingModes = + registry + .select( preferencesStore ) + .get( 'core', 'renderingModes' )?.[ theme ] ?? {}; + + if ( renderingModes[ postType ] === mode ) { + return; + } + + const newModes = { + [ theme ]: { + ...renderingModes, + [ postType ]: mode, + }, + }; + + registry + .dispatch( preferencesStore ) + .set( 'core', 'renderingModes', newModes ); + }; diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index 73bf19f3d9993..d381d4caa7492 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -16,6 +16,7 @@ import { verse, } from '@wordpress/icons'; import { store as coreStore } from '@wordpress/core-data'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -34,6 +35,11 @@ const EMPTY_INSERTION_POINT = { filterValue: undefined, }; +/** + * These are rendering modes that the editor supports. + */ +const RENDERING_MODES = [ 'post-only', 'template-locked' ]; + /** * Get the inserter. * @@ -215,3 +221,54 @@ export const getPostBlocksByName = createRegistrySelector( ( select ) => () => [ select( blockEditorStore ).getBlocks() ] ) ); + +/** + * Returns the default rendering mode for a post type by user preference or post type configuration. + * + * @param {Object} state Global application state. + * @param {string} postType The post type. + * + * @return {string} The default rendering mode. Returns `undefined` while resolving value. + */ +export const getDefaultRenderingMode = createRegistrySelector( + ( select ) => ( state, postType ) => { + const { getPostType, getCurrentTheme, hasFinishedResolution } = + select( coreStore ); + + // This needs to be called before `hasFinishedResolution`. + // eslint-disable-next-line @wordpress/no-unused-vars-before-return + const currentTheme = getCurrentTheme(); + // eslint-disable-next-line @wordpress/no-unused-vars-before-return + const postTypeEntity = getPostType( postType ); + + // Wait for the post type and theme resolution. + if ( + ! hasFinishedResolution( 'getPostType', [ postType ] ) || + ! hasFinishedResolution( 'getCurrentTheme' ) + ) { + return undefined; + } + + const theme = currentTheme?.stylesheet; + const defaultModePreference = select( preferencesStore ).get( + 'core', + 'renderingModes' + )?.[ theme ]?.[ postType ]; + const postTypeDefaultMode = Array.isArray( + postTypeEntity?.supports?.editor + ) + ? postTypeEntity.supports.editor.find( + ( features ) => 'default-mode' in features + )?.[ 'default-mode' ] + : undefined; + + const defaultMode = defaultModePreference || postTypeDefaultMode; + + // Fallback gracefully to 'post-only' when rendering mode is not supported. + if ( ! RENDERING_MODES.includes( defaultMode ) ) { + return 'post-only'; + } + + return defaultMode; + } +); diff --git a/test/e2e/specs/site-editor/preload.spec.js b/test/e2e/specs/site-editor/preload.spec.js index e618d70ca20b9..b6f9f49aedeb7 100644 --- a/test/e2e/specs/site-editor/preload.spec.js +++ b/test/e2e/specs/site-editor/preload.spec.js @@ -46,6 +46,9 @@ test.describe( 'Preload', () => { expect( requests ).toEqual( [ // Seems to be coming from `enableComplementaryArea`. '/wp/v2/users/me', + // There are two separate settings OPTIONS requests. We should fix + // so the one for canUser and getEntityRecord are reused. + '/wp/v2/settings', ] ); } ); } ); diff --git a/test/native/integration-test-helpers/initialize-editor.js b/test/native/integration-test-helpers/initialize-editor.js index 3b89da979aee3..ffaea764a90ec 100644 --- a/test/native/integration-test-helpers/initialize-editor.js +++ b/test/native/integration-test-helpers/initialize-editor.js @@ -38,7 +38,7 @@ export async function initializeEditor( props, { component } = {} ) { resolutionSpy.mockImplementation( ( selectorName, args ) => { // The mobile editor only supports the `post-only` rendering mode, so we // presume a resolved `getPostType` selector to unblock editor rendering. - if ( 'getPostType' === selectorName ) { + if ( [ 'getPostType', 'getCurrentTheme' ].includes( selectorName ) ) { return true; } From b532402f29c93f866aaefb6324d4f6e9a28f833a Mon Sep 17 00:00:00 2001 From: tomoki shimomura Date: Thu, 27 Feb 2025 00:10:28 +0900 Subject: [PATCH 12/23] Post Navigation Link: Enable all non-interactive formats (#69325) Co-authored-by: shimotmk Co-authored-by: Mamaduka --- packages/block-library/src/post-navigation-link/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/post-navigation-link/edit.js b/packages/block-library/src/post-navigation-link/edit.js index e27d094feb79a..bbdacfeb77397 100644 --- a/packages/block-library/src/post-navigation-link/edit.js +++ b/packages/block-library/src/post-navigation-link/edit.js @@ -198,7 +198,7 @@ export default function PostNavigationLinkEdit( { aria-label={ ariaLabel } placeholder={ placeholder } value={ label } - allowedFormats={ [ 'core/bold', 'core/italic' ] } + withoutInteractiveFormatting onChange={ ( newLabel ) => setAttributes( { label: newLabel } ) } From fc4014766887be55bcbf92116ecc6369b97be7cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:36:27 +0000 Subject: [PATCH 13/23] Bump the github-actions group across 2 directories with 3 updates (#69329) Bumps the github-actions group with 2 updates in the /.github/setup-node directory: [actions/cache](https://github.com/actions/cache) and [actions/upload-artifact](https://github.com/actions/upload-artifact). Bumps the github-actions group with 2 updates in the /.github/workflows directory: [actions/cache](https://github.com/actions/cache) and [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/cache` from 4.2.0 to 4.2.1 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/1bd1e32a3bdc45362d1e726936510720a7c30a57...0c907a75c2c80ebcb7f088228285e798b750cf8f) Updates `actions/upload-artifact` from 4.6.0 to 4.6.1 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08...4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1) Updates `actions/cache` from 4.2.0 to 4.2.1 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/1bd1e32a3bdc45362d1e726936510720a7c30a57...0c907a75c2c80ebcb7f088228285e798b750cf8f) Updates `actions/download-artifact` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4.1.8...v4.1.9) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: desrosj --- .github/setup-node/action.yml | 4 ++-- .github/workflows/build-plugin-zip.yml | 4 ++-- .github/workflows/end2end-test.yml | 2 +- .github/workflows/rnmobile-android-runner.yml | 4 ++-- .github/workflows/rnmobile-ios-runner.yml | 6 +++--- .github/workflows/unit-test.yml | 4 ++-- .github/workflows/upload-release-to-plugin-repo.yml | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/setup-node/action.yml b/.github/setup-node/action.yml index 83c4123fbab93..8a5bf3c3202b3 100644 --- a/.github/setup-node/action.yml +++ b/.github/setup-node/action.yml @@ -25,7 +25,7 @@ runs: - name: Cache node_modules id: cache-node_modules - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: '**/node_modules' key: node_modules-${{ runner.os }}-${{ runner.arch }}-${{ steps.node-version.outputs.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} @@ -36,7 +36,7 @@ runs: npm ci shell: bash - name: Upload npm logs as an artifact on failure - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 if: failure() with: name: npm-logs diff --git a/.github/workflows/build-plugin-zip.yml b/.github/workflows/build-plugin-zip.yml index 281146b63f290..eb073b6e47d69 100644 --- a/.github/workflows/build-plugin-zip.yml +++ b/.github/workflows/build-plugin-zip.yml @@ -273,12 +273,12 @@ jobs: run: echo "version=$(echo $VERSION | cut -d / -f 3 | sed 's/-rc./ RC/' )" >> $GITHUB_OUTPUT - name: Download Plugin Zip Artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 with: name: gutenberg-plugin - name: Download Release Notes Artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 with: name: release-notes diff --git a/.github/workflows/end2end-test.yml b/.github/workflows/end2end-test.yml index ea85a8949573f..ab6054f65ce96 100644 --- a/.github/workflows/end2end-test.yml +++ b/.github/workflows/end2end-test.yml @@ -107,7 +107,7 @@ jobs: ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4.1.9 # Don't fail the job if there isn't any flaky tests report. continue-on-error: true with: diff --git a/.github/workflows/rnmobile-android-runner.yml b/.github/workflows/rnmobile-android-runner.yml index 4989239286462..3237319a53f11 100644 --- a/.github/workflows/rnmobile-android-runner.yml +++ b/.github/workflows/rnmobile-android-runner.yml @@ -38,7 +38,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: | ~/.appium @@ -53,7 +53,7 @@ jobs: # AVD cache disabled as it caused emulator termination to hang indefinitely. # https://github.com/ReactiveCircus/android-emulator-runner/issues/385 # - name: AVD cache - # uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + # uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 # id: avd-cache # with: # path: | diff --git a/.github/workflows/rnmobile-ios-runner.yml b/.github/workflows/rnmobile-ios-runner.yml index 4d6b310e60f97..5eec207bcdc08 100644 --- a/.github/workflows/rnmobile-ios-runner.yml +++ b/.github/workflows/rnmobile-ios-runner.yml @@ -43,7 +43,7 @@ jobs: uses: ./.github/setup-node - name: Restore tests setup cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: | ~/.appium @@ -56,7 +56,7 @@ jobs: run: find package-lock.json packages/react-native-editor/ios packages/react-native-aztec/ios packages/react-native-bridge/ios -type f -print0 | sort -z | xargs -0 shasum | tee ios-checksums.txt - name: Restore build cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: | packages/react-native-editor/ios/build/GutenbergDemo/Build/Products/Release-iphonesimulator/GutenbergDemo.app @@ -64,7 +64,7 @@ jobs: key: ${{ runner.os }}-ios-build-${{ matrix.xcode }}-${{ matrix.device }}-${{ hashFiles('ios-checksums.txt') }} - name: Restore pods cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: | packages/react-native-editor/ios/Pods diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index b5c5e2255da5e..8cfbf13cc8b56 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -206,7 +206,7 @@ jobs: custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F") - name: Download built JavaScript assets - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 with: name: build-assets @@ -296,7 +296,7 @@ jobs: run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT - name: Cache PHPCS scan cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: .cache/phpcs.json key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml index 7d2c780599cdd..997b0cff9a44a 100644 --- a/.github/workflows/upload-release-to-plugin-repo.yml +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -195,7 +195,7 @@ jobs: sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" ./trunk/readme.txt - name: Download Changelog Artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 with: name: changelog trunk path: trunk @@ -246,7 +246,7 @@ jobs: sed -i "s/$STABLE_TAG_PLACEHOLDER/Stable tag: $VERSION/g" "$VERSION/readme.txt" - name: Download Changelog Artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9 with: name: changelog trunk path: ${{ github.event.release.name }} From 5c38661db385abdfbc0093a38fb01849d6793e6b Mon Sep 17 00:00:00 2001 From: Benazeer Hassan <66269472+benazeer-ben@users.noreply.github.com> Date: Thu, 27 Feb 2025 10:09:08 +0530 Subject: [PATCH 14/23] Adding missing center alignment style for pullquote (#68121) Co-authored-by: benazeer-ben Co-authored-by: mrwweb --- packages/block-library/src/pullquote/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-library/src/pullquote/style.scss b/packages/block-library/src/pullquote/style.scss index ff5fe6068dfac..6c6557a1101fb 100644 --- a/packages/block-library/src/pullquote/style.scss +++ b/packages/block-library/src/pullquote/style.scss @@ -46,6 +46,10 @@ .wp-block-pullquote.has-text-align-right blockquote { text-align: right; } +// Ensure that we are reasonably specific to override theme defaults. +.wp-block-pullquote.has-text-align-center blockquote { + text-align: center; +} // .is-style-solid-color is deprecated. // This selector has not been scoped with `:root :where`, as global styles From 0ec29ddbe325d08a38fb8843c97b6d6d48a93cd7 Mon Sep 17 00:00:00 2001 From: Carolina Nymark Date: Thu, 27 Feb 2025 10:10:22 +0100 Subject: [PATCH 15/23] Document outline: Show heading blocks when template-lock is enabled (#69073) * Document outline: Show heading blocks when template-lock is enabled This PR updates the Document Outline to show heading blocks from both the template and the post content when the option "Show template" is enabled. Co-authored-by: carolinan Co-authored-by: Mamaduka Co-authored-by: SainathPoojary Co-authored-by: singhakanshu00 Co-authored-by: rinkalpagdar Co-authored-by: afercia Co-authored-by: t-hamano --- .../src/components/document-outline/index.js | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/editor/src/components/document-outline/index.js b/packages/editor/src/components/document-outline/index.js index 6c498ccc79990..704eccbee6944 100644 --- a/packages/editor/src/components/document-outline/index.js +++ b/packages/editor/src/components/document-outline/index.js @@ -3,7 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; -import { useRef } from '@wordpress/element'; +import { useRef, useMemo } from '@wordpress/element'; import { create, getTextContent } from '@wordpress/rich-text'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; @@ -83,16 +83,13 @@ function EmptyOutlineIllustration() { * @return {Array} An array of heading blocks enhanced with the properties described above. */ const computeOutlineHeadings = ( blocks = [] ) => { - return blocks.flatMap( ( block = {} ) => { - if ( block.name === 'core/heading' ) { - return { - ...block, - level: block.attributes.level, - isEmpty: isEmptyHeading( block ), - }; - } - return computeOutlineHeadings( block.innerBlocks ); - } ); + return blocks + .filter( ( block ) => block.name === 'core/heading' ) + .map( ( block ) => ( { + ...block, + level: block.attributes.level, + isEmpty: isEmptyHeading( block ), + } ) ); }; const isEmptyHeading = ( heading ) => @@ -113,22 +110,31 @@ export default function DocumentOutline( { hasOutlineItemsDisabled, } ) { const { selectBlock } = useDispatch( blockEditorStore ); - const { blocks, title, isTitleSupported } = useSelect( ( select ) => { - const { getBlocks } = select( blockEditorStore ); + const { title, isTitleSupported } = useSelect( ( select ) => { const { getEditedPostAttribute } = select( editorStore ); const { getPostType } = select( coreStore ); const postType = getPostType( getEditedPostAttribute( 'type' ) ); - return { title: getEditedPostAttribute( 'title' ), - blocks: getBlocks(), isTitleSupported: postType?.supports?.title ?? false, }; } ); + const blocks = useSelect( ( select ) => { + const { getClientIdsWithDescendants, getBlock } = + select( blockEditorStore ); + const clientIds = getClientIdsWithDescendants(); + // Note: Don't modify data inside the `Array.map` callback, + // all compulations should happen in `computeOutlineHeadings`. + return clientIds.map( ( id ) => getBlock( id ) ); + } ); const prevHeadingLevelRef = useRef( 1 ); - const headings = computeOutlineHeadings( blocks ); + const headings = useMemo( + () => computeOutlineHeadings( blocks ), + [ blocks ] + ); + if ( headings.length < 1 ) { return (
From a02bf960c99e0f68ca165fc5f56e553c1b410583 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 27 Feb 2025 14:30:54 +0400 Subject: [PATCH 16/23] Fields: Avoid 'useSelect' warnings in the template component (#69344) Co-authored-by: Mamaduka --- .../src/fields/template/template-edit.tsx | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/packages/fields/src/fields/template/template-edit.tsx b/packages/fields/src/fields/template/template-edit.tsx index 1a96f5d0cab74..eef5b0734c997 100644 --- a/packages/fields/src/fields/template/template-edit.tsx +++ b/packages/fields/src/fields/template/template-edit.tsx @@ -28,6 +28,8 @@ import { getItemTitle } from '../../actions/utils'; import type { BasePost } from '../../types'; import { unlock } from '../../lock-unlock'; +const EMPTY_ARRAY: [] = []; + export const TemplateEdit = ( { data, field, @@ -39,7 +41,7 @@ export const TemplateEdit = ( { typeof data.id === 'number' ? data.id : parseInt( data.id, 10 ); const slug = data.slug; - const { availableTemplates, templates } = useSelect( + const { canSwitchTemplate, templates } = useSelect( ( select ) => { const allTemplates = select( coreStore ).getEntityRecords< WpTemplate >( @@ -49,7 +51,7 @@ export const TemplateEdit = ( { per_page: -1, post_type: postType, } - ) ?? []; + ) ?? EMPTY_ARRAY; const { getHomePage, getPostsPageId } = unlock( select( coreStore ) @@ -63,40 +65,41 @@ export const TemplateEdit = ( { return { templates: allTemplates, - availableTemplates: allowSwitchingTemplate - ? allTemplates.filter( - ( template ) => - template.is_custom && - template.slug !== data.template && - !! template.content.raw // Skip empty templates. - ) - : [], + canSwitchTemplate: allowSwitchingTemplate, }; }, - [ data.template, postId, postType ] + [ postId, postType ] ); - const templatesAsPatterns = useMemo( - () => - availableTemplates.map( ( template ) => ( { + const templatesAsPatterns = useMemo( () => { + if ( ! canSwitchTemplate ) { + return []; + } + return templates + .filter( + ( template ) => + template.is_custom && + template.slug !== data.template && + // Skip empty templates. + !! template.content.raw + ) + .map( ( template ) => ( { name: template.slug, blocks: parse( template.content.raw ), title: decodeEntities( template.title.rendered ), id: template.id, - } ) ), - [ availableTemplates ] - ); + } ) ); + }, [ canSwitchTemplate, data.template, templates ] ); const shownTemplates = useAsyncList( templatesAsPatterns ); const value = field.getValue( { item: data } ); + const foundTemplate = templates.find( + ( template ) => template.slug === value + ); const currentTemplate = useSelect( ( select ) => { - const foundTemplate = templates?.find( - ( template ) => template.slug === value - ); - if ( foundTemplate ) { return foundTemplate; } @@ -128,7 +131,7 @@ export const TemplateEdit = ( { ); } }, - [ postType, slug, templates, value ] + [ foundTemplate, postType, slug ] ); const [ showModal, setShowModal ] = useState( false ); From 47fdb90bd7c50bd321b2fe95f4b920af55c9e13c Mon Sep 17 00:00:00 2001 From: Sainath Poojary <53347682+SainathPoojary@users.noreply.github.com> Date: Thu, 27 Feb 2025 17:20:58 +0530 Subject: [PATCH 17/23] InputControl: Ensure consistent placeholder color (#69334) * InputControl: Ensure consistent placeholder color * InputControl: Add CHANGELOG entry * InputControl: Remove unnecessary line-height styles Co-authored-by: SainathPoojary Co-authored-by: afercia Co-authored-by: ciampo Co-authored-by: im3dabasia --- packages/components/CHANGELOG.md | 1 + .../src/input-control/styles/input-control-styles.tsx | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 5cdf14f89937f..31cd61305a730 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug Fixes - `TextControl`: Ensures email and url inputs have consistent LTR alignment in RTL languages ([#68561](https://github.com/WordPress/gutenberg/pull/68561)). +- `InputControl`: Ensure consistent placeholder color ([#69334](https://github.com/WordPress/gutenberg/pull/69334)). ### Enhancement diff --git a/packages/components/src/input-control/styles/input-control-styles.tsx b/packages/components/src/input-control/styles/input-control-styles.tsx index db24a5e60f137..492c4bef0f4e2 100644 --- a/packages/components/src/input-control/styles/input-control-styles.tsx +++ b/packages/components/src/input-control/styles/input-control-styles.tsx @@ -285,7 +285,15 @@ export const Input = styled.input< InputProps >` ${ customPaddings } &::-webkit-input-placeholder { - line-height: normal; + color: ${ COLORS.ui.darkGrayPlaceholder }; + } + + &::-moz-placeholder { + color: ${ COLORS.ui.darkGrayPlaceholder }; + } + + &:-ms-input-placeholder { + color: ${ COLORS.ui.darkGrayPlaceholder }; } &[type='email'], From df6f07d96941d65671bbdc97962db058123a03e2 Mon Sep 17 00:00:00 2001 From: Yogesh Bhutkar Date: Thu, 27 Feb 2025 18:01:56 +0530 Subject: [PATCH 18/23] Close patterns modal on insertion and focus on inserted pattern (#68975) Co-authored-by: yogeshbhutkar Co-authored-by: Mamaduka Co-authored-by: t-hamano Co-authored-by: afercia Co-authored-by: carolinan --- .../components/inserter/block-patterns-explorer/index.js | 5 +++-- .../inserter/block-patterns-explorer/pattern-list.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/index.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/index.js index 93a03ee200497..f224ad0d6566f 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/index.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/index.js @@ -12,7 +12,7 @@ import PatternExplorerSidebar from './pattern-explorer-sidebar'; import PatternList from './pattern-list'; import { usePatternCategories } from '../block-patterns-tab/use-pattern-categories'; -function PatternsExplorer( { initialCategory, rootClientId } ) { +function PatternsExplorer( { initialCategory, rootClientId, onModalClose } ) { const [ searchValue, setSearchValue ] = useState( '' ); const [ selectedCategory, setSelectedCategory ] = useState( initialCategory?.name @@ -34,6 +34,7 @@ function PatternsExplorer( { initialCategory, rootClientId } ) { selectedCategory={ selectedCategory } patternCategories={ patternCategories } rootClientId={ rootClientId } + onModalClose={ onModalClose } />
); @@ -46,7 +47,7 @@ function PatternsExplorerModal( { onModalClose, ...restProps } ) { onRequestClose={ onModalClose } isFullScreen > - + ); } diff --git a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js index 8e5e50500ec72..11d92d11a7beb 100644 --- a/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js +++ b/packages/block-editor/src/components/inserter/block-patterns-explorer/pattern-list.js @@ -52,6 +52,7 @@ function PatternList( { selectedCategory, patternCategories, rootClientId, + onModalClose, } ) { const container = useRef(); const debouncedSpeak = useDebounce( speak, 500 ); @@ -152,7 +153,10 @@ function PatternList( { <> { + onClickPattern( pattern, blocks ); + onModalClose(); + } } isDraggable={ false } /> From 38610b0e7e72b67eca210e47f2894621f2646557 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 27 Feb 2025 21:33:45 +0900 Subject: [PATCH 19/23] Site Editor: Fix space on the left or right of the menu in mobile view (#69327) Co-authored-by: t-hamano Co-authored-by: vcanales Co-authored-by: Mamaduka Co-authored-by: afercia Co-authored-by: rinkalpagdar --- packages/edit-site/src/components/layout/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index caf7dd78da4b3..31699b91eb26e 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -68,6 +68,10 @@ .edit-site-sidebar__screen-wrapper { padding: 0; } + + .edit-site-sidebar-navigation-screen__main { + padding: 0 $grid-unit-15; + } } .edit-site-layout__canvas-container { From 50d457edb233642bfcefebb1975a637dc3aae33c Mon Sep 17 00:00:00 2001 From: tomoki shimomura Date: Thu, 27 Feb 2025 21:44:14 +0900 Subject: [PATCH 20/23] Format Library: Text-color popover width to fit sidebar (#68881) Co-authored-by: shimotmk Co-authored-by: Mamaduka --- packages/format-library/src/text-color/style.scss | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/format-library/src/text-color/style.scss b/packages/format-library/src/text-color/style.scss index 439af6db38d0c..05f448d88d77b 100644 --- a/packages/format-library/src/text-color/style.scss +++ b/packages/format-library/src/text-color/style.scss @@ -1,6 +1,13 @@ +// Must equal $color-palette-circle-size from: +// @wordpress/components/src/circular-option-picker/style.scss +$swatch-size: 28px; +$swatch-gap: 12px; +$panelPadding: $grid-unit-20; + .format-library__inline-color-popover { [role="tabpanel"] { - padding: 16px; + padding: $panelPadding; + width: ( $swatch-size * 6 ) + ( $swatch-gap * 5 ) + ( $panelPadding * 2 ); } } From d8de061a96a2bcfe18fe7248b8166786424b75a4 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Thu, 27 Feb 2025 18:33:42 +0530 Subject: [PATCH 21/23] FontSizePicker: Fix FontSizePicker Storybook control type and improve documentation (#68936) * Components: Improve FontSizePicker units documentation and fix unit filtering * Fix failing unit tests * Docs: Update FontSizePicker README.md to mention the unitless mode * FontSizePicker: Change the storybook control type to inline-check * FontSizePicker: Add entry in CHANGELOG.md * Add changelog subheading - Documentation * Move the unitless property note to value prop and reflect the same in JSDocs Co-authored-by: himanshupathak95 Co-authored-by: t-hamano Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo Co-authored-by: SainathPoojary Co-authored-by: im3dabasia Co-authored-by: slaFFik --- packages/components/CHANGELOG.md | 4 ++++ packages/components/src/font-size-picker/README.md | 2 ++ .../components/src/font-size-picker/stories/index.story.tsx | 4 ++++ packages/components/src/font-size-picker/types.ts | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 31cd61305a730..67daeb143049a 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Documentation + +- `FontSizePicker`: Fix Storybook units control type to use `inline-check` and improve documentation clarifying unitless mode in `README.md` ([#68936](https://github.com/WordPress/gutenberg/pull/68936)). + ### Bug Fixes - `TextControl`: Ensures email and url inputs have consistent LTR alignment in RTL languages ([#68561](https://github.com/WordPress/gutenberg/pull/68561)). diff --git a/packages/components/src/font-size-picker/README.md b/packages/components/src/font-size-picker/README.md index 39d916c0c7b21..8c5cd1444aa69 100644 --- a/packages/components/src/font-size-picker/README.md +++ b/packages/components/src/font-size-picker/README.md @@ -99,6 +99,8 @@ Available units for custom font size selection. The current font size value. +**Note**: For the `units` property to work, the current font size value must be specified as strings with units (e.g., `'12px'` instead of `12`). When the font size is provided as a number, the component operates in "unitless mode" where the `units` property has no effect. + - Required: No ### `withReset`: `boolean` diff --git a/packages/components/src/font-size-picker/stories/index.story.tsx b/packages/components/src/font-size-picker/stories/index.story.tsx index f6502fcfd537c..59af0f5cfe60d 100644 --- a/packages/components/src/font-size-picker/stories/index.story.tsx +++ b/packages/components/src/font-size-picker/stories/index.story.tsx @@ -18,6 +18,10 @@ const meta: Meta< typeof FontSizePicker > = { component: FontSizePicker, argTypes: { value: { control: false }, + units: { + control: 'inline-check', + options: [ 'px', 'em', 'rem', 'vw', 'vh' ], + }, }, parameters: { actions: { argTypesRegex: '^on.*' }, diff --git a/packages/components/src/font-size-picker/types.ts b/packages/components/src/font-size-picker/types.ts index 2296e96856788..04964e05d45d5 100644 --- a/packages/components/src/font-size-picker/types.ts +++ b/packages/components/src/font-size-picker/types.ts @@ -34,6 +34,10 @@ export type FontSizePickerProps = { units?: string[]; /** * The current font size value. + * + * Note: For the `units` property to work, the current font size value must be specified + * as strings with units (e.g., '12px' instead of 12). When the font size is provided + * as a number, the component operates in "unitless mode" where the `units` property has no effect. */ value?: number | string; /** From 079996b742a2e58c0e4f6df4a04a33dea48d1c29 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 27 Feb 2025 18:06:05 +0400 Subject: [PATCH 22/23] Editor: Revert bulk editing support for post actions (#69341) Co-authored-by: Mamaduka Co-authored-by: t-hamano --- .../src/components/post-actions/index.js | 56 +++++++------------ .../src/components/post-card-panel/index.js | 12 ++-- 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/packages/editor/src/components/post-actions/index.js b/packages/editor/src/components/post-actions/index.js index d6adf6c072166..219fb19e5eb83 100644 --- a/packages/editor/src/components/post-actions/index.js +++ b/packages/editor/src/components/post-actions/index.js @@ -20,57 +20,39 @@ import { usePostActions } from './actions'; const { Menu, kebabCase } = unlock( componentsPrivateApis ); -function useEditedEntityRecordsWithPermissions( postType, postIds ) { - const { items, permissions } = useSelect( +export default function PostActions( { postType, postId, onActionPerformed } ) { + const [ activeModalAction, setActiveModalAction ] = useState( null ); + + const { item, permissions } = useSelect( ( select ) => { const { getEditedEntityRecord, getEntityRecordPermissions } = unlock( select( coreStore ) ); return { - items: postIds.map( ( postId ) => - getEditedEntityRecord( 'postType', postType, postId ) - ), - permissions: postIds.map( ( postId ) => - getEntityRecordPermissions( 'postType', postType, postId ) + item: getEditedEntityRecord( 'postType', postType, postId ), + permissions: getEntityRecordPermissions( + 'postType', + postType, + postId ), }; }, - [ postIds, postType ] + [ postId, postType ] ); - - return useMemo( () => { - return items.map( ( item, index ) => ( { + const itemWithPermissions = useMemo( () => { + return { ...item, - permissions: permissions[ index ], - } ) ); - }, [ items, permissions ] ); -} - -export default function PostActions( { postType, postId, onActionPerformed } ) { - const [ activeModalAction, setActiveModalAction ] = useState( null ); - const _postIds = useMemo( () => { - if ( Array.isArray( postId ) ) { - return postId; - } - return postId ? [ postId ] : []; - }, [ postId ] ); - - const itemsWithPermissions = useEditedEntityRecordsWithPermissions( - postType, - _postIds - ); + permissions, + }; + }, [ item, permissions ] ); const allActions = usePostActions( { postType, onActionPerformed } ); const actions = useMemo( () => { return allActions.filter( ( action ) => { return ( - ( ! action.isEligible || - itemsWithPermissions.some( ( itemWithPermissions ) => - action.isEligible( itemWithPermissions ) - ) ) && - ( itemsWithPermissions.length < 2 || action.supportsBulk ) + ! action.isEligible || action.isEligible( itemWithPermissions ) ); } ); - }, [ allActions, itemsWithPermissions ] ); + }, [ allActions, itemWithPermissions ] ); return ( <> @@ -90,7 +72,7 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { @@ -98,7 +80,7 @@ export default function PostActions( { postType, postId, onActionPerformed } ) { { !! activeModalAction && ( setActiveModalAction( null ) } /> ) } diff --git a/packages/editor/src/components/post-card-panel/index.js b/packages/editor/src/components/post-card-panel/index.js index 895545cb007f0..a2ed6f5adaad8 100644 --- a/packages/editor/src/components/post-card-panel/index.js +++ b/packages/editor/src/components/post-card-panel/index.js @@ -118,11 +118,13 @@ export default function PostCardPanel( { { pageTypeBadge } ) } - + { postIds.length === 1 && ( + + ) } { postIds.length > 1 && ( From 18a4c0d236b751084d406871a5ad7ab846938c40 Mon Sep 17 00:00:00 2001 From: Himanshu Pathak Date: Thu, 27 Feb 2025 19:43:46 +0530 Subject: [PATCH 23/23] Remove unnecessary opacity override for Firefox placeholders (#69312) * Remove unnecessary opacity override for Firefox placeholders * Changelog: Add entry for TextareaControl * Move changelog entry under the Enhancement section. Co-authored-by: himanshupathak95 Co-authored-by: afercia --- packages/base-styles/_mixins.scss | 1 - packages/components/CHANGELOG.md | 1 + .../src/textarea-control/styles/textarea-control-styles.ts | 2 -- packages/editor/src/components/post-text-editor/style.scss | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/base-styles/_mixins.scss b/packages/base-styles/_mixins.scss index 9f089b8d9e832..e61541f027057 100644 --- a/packages/base-styles/_mixins.scss +++ b/packages/base-styles/_mixins.scss @@ -284,7 +284,6 @@ } &::-moz-placeholder { - opacity: 1; // Necessary because Firefox reduces this from 1. color: $dark-gray-placeholder; } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 67daeb143049a..d44cd0a56964b 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -13,6 +13,7 @@ ### Enhancement +- `TextareaControl`: Fix Firefox placeholder text opacity override ([#69312](https://github.com/WordPress/gutenberg/pull/69312)). - `BorderControlDropdown`, `BorderControl`: Reset button is always visible. ([#69066](https://github.com/WordPress/gutenberg/pull/69066)). ### Internal diff --git a/packages/components/src/textarea-control/styles/textarea-control-styles.ts b/packages/components/src/textarea-control/styles/textarea-control-styles.ts index 022ce3560ea3a..84dd2da0e53c0 100644 --- a/packages/components/src/textarea-control/styles/textarea-control-styles.ts +++ b/packages/components/src/textarea-control/styles/textarea-control-styles.ts @@ -62,7 +62,6 @@ export const StyledTextarea = styled.textarea` } &::-moz-placeholder { - opacity: 1; // Necessary because Firefox reduces this from 1. color: ${ COLORS.ui.darkGrayPlaceholder }; } @@ -76,7 +75,6 @@ export const StyledTextarea = styled.textarea` } &::-moz-placeholder { - opacity: 1; // Necessary because Firefox reduces this from 1. color: ${ COLORS.ui.lightGrayPlaceholder }; } diff --git a/packages/editor/src/components/post-text-editor/style.scss b/packages/editor/src/components/post-text-editor/style.scss index 5391588d906d8..ad7b3383db2aa 100644 --- a/packages/editor/src/components/post-text-editor/style.scss +++ b/packages/editor/src/components/post-text-editor/style.scss @@ -41,8 +41,6 @@ textarea.editor-post-text-editor { &::-moz-placeholder { color: $dark-gray-placeholder; - // Override Firefox default. - opacity: 1; } &:-ms-input-placeholder {