From 76d4652fd9f8369f70932631ba887a74b9c0c834 Mon Sep 17 00:00:00 2001 From: Eshaan Dabasiya <76681468+im3dabasia@users.noreply.github.com> Date: Fri, 20 Dec 2024 13:41:58 +0530 Subject: [PATCH 1/5] Storybook : Add TextTransformControl stories (#67365) * Add TextTransformControl stories * refactor: Removed the sample text, and extra stories and used story pattern * fix: Add options for the value prop and improve description * fix: Revert old template style code for render and updated argtypes * doc: Removed default value in props Co-authored-by: im3dabasia Co-authored-by: t-hamano --- .../text-transform-control/README.md | 5 +- .../stories/index.story.js | 69 ++++++++++++++----- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/packages/block-editor/src/components/text-transform-control/README.md b/packages/block-editor/src/components/text-transform-control/README.md index 2d40cc16ba86f8..3ed8f1da8cd6e9 100644 --- a/packages/block-editor/src/components/text-transform-control/README.md +++ b/packages/block-editor/src/components/text-transform-control/README.md @@ -1,7 +1,7 @@ # TextTransformControl The `TextTransformControl` component is responsible for rendering a control element that allows users to select and apply text transformation options to blocks or elements in the Gutenberg editor. It provides an intuitive interface for changing the text appearance by applying different transformations such as `none`, `uppercase`, `lowercase`, `capitalize`. - + ![TextTransformConrol Element in Inspector Control](https://raw.githubusercontent.com/WordPress/gutenberg/HEAD/docs/assets/text-transform-component.png?raw=true) ## Development guidelines @@ -28,7 +28,6 @@ const MyTextTransformControlComponent = () => ( ### `value` - **Type:** `String` -- **Default:** `none` - **Options:** `none`, `uppercase`, `lowercase`, `capitalize` The current value of the Text Transform setting. You may only choose from the `Options` listed above. @@ -37,4 +36,4 @@ The current value of the Text Transform setting. You may only choose from the `O - **Type:** `Function` -A callback function invoked when the Text Transform value is changed via an interaction with any of the buttons. Called with the Text Transform value (`none`, `uppercase`, `lowercase`, `capitalize`) as the only argument. \ No newline at end of file +A callback function invoked when the Text Transform value is changed via an interaction with any of the buttons. Called with the Text Transform value (`none`, `uppercase`, `lowercase`, `capitalize`) as the only argument. diff --git a/packages/block-editor/src/components/text-transform-control/stories/index.story.js b/packages/block-editor/src/components/text-transform-control/stories/index.story.js index 96dd8ed479dc4e..77dc550368da19 100644 --- a/packages/block-editor/src/components/text-transform-control/stories/index.story.js +++ b/packages/block-editor/src/components/text-transform-control/stories/index.story.js @@ -8,26 +8,63 @@ import { useState } from '@wordpress/element'; */ import TextTransformControl from '../'; -export default { +const meta = { title: 'BlockEditor/TextTransformControl', component: TextTransformControl, + parameters: { + docs: { + canvas: { sourceState: 'shown' }, + description: { + component: + 'Control to facilitate text transformation selections.', + }, + }, + }, argTypes: { - onChange: { action: 'onChange' }, + onChange: { + action: 'onChange', + control: { + type: null, + }, + description: 'Handles change in text transform selection.', + table: { + type: { + summary: 'function', + }, + }, + }, + className: { + control: { type: 'text' }, + description: 'Class name to add to the control.', + table: { + type: { summary: 'string' }, + }, + }, + value: { + control: { type: null }, + description: 'Currently selected text transform.', + table: { + type: { summary: 'string' }, + }, + }, }, }; -const Template = ( { onChange, ...args } ) => { - const [ value, setValue ] = useState(); - return ( - { - onChange( ...changeArgs ); - setValue( ...changeArgs ); - } } - value={ value } - /> - ); -}; +export default meta; + +export const Default = { + render: function Template( { onChange, ...args } ) { + const [ value, setValue ] = useState(); -export const Default = Template.bind( {} ); + return ( + { + onChange( ...changeArgs ); + setValue( ...changeArgs ); + } } + value={ value } + /> + ); + }, +}; From 9cb002ed3da642acf0826f63adb620537f3fc54b Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:51:50 +1000 Subject: [PATCH 2/5] Section Styles: Update block style variation docs (#68169) Co-authored-by: aaronrobertshaw Co-authored-by: ramonjd --- .../themes/global-settings-and-styles.md | 101 +++++++++++++++++- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/docs/how-to-guides/themes/global-settings-and-styles.md b/docs/how-to-guides/themes/global-settings-and-styles.md index f71bd67bfaf2ec..205a3ee862ce6b 100644 --- a/docs/how-to-guides/themes/global-settings-and-styles.md +++ b/docs/how-to-guides/themes/global-settings-and-styles.md @@ -1053,16 +1053,16 @@ Pseudo selectors `:hover`, `:focus`, `:visited`, `:active`, `:link`, `:any-link` #### Variations -A block can have a "style variation", as defined per the [block.json specification](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#styles-optional). Theme authors can define the style attributes for an existing style variation using the theme.json file. Styles for unregistered style variations will be ignored. +A block can have a "style variation," as defined in the [block.json specification](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/#styles-optional). Theme authors can define the style attributes for an existing style variation using the `theme.json` file. Styles for unregistered style variations will be ignored. -Note that variations are a "block concept", they only exist bound to blocks. The `theme.json` specification respects that distinction by only allowing `variations` at the block-level but not at the top-level. It's also worth highlighting that only variations defined in the `block.json` file of the block are considered "registered": so far, the style variations added via `register_block_style` or in the client are ignored, see [this issue](https://github.com/WordPress/gutenberg/issues/49602) for more information. +Note that variations are a "block concept"—they only exist when bound to blocks. The `theme.json` specification respects this distinction by only allowing `variations` at the block level, not the top level. It’s also worth highlighting that only variations defined in the `block.json` file of the block or via `register_block_style` on the server are considered "registered" for `theme.json` styling purposes. For example, this is how to provide styles for the existing `plain` variation for the `core/quote` block: ```json { "version": 3, - "styles":{ + "styles": { "blocks": { "core/quote": { "variations": { @@ -1078,7 +1078,7 @@ For example, this is how to provide styles for the existing `plain` variation fo } ``` -The resulting CSS output is this: +The resulting CSS output is: ```css .wp-block-quote.is-style-plain { @@ -1086,6 +1086,99 @@ The resulting CSS output is this: } ``` +It is also possible for multiple block types to share the same variation styles. There are two recommended ways to define such shared styles: + +1. `theme.json` partial files +2. programmatically, using `register_block_style` + +##### Variation Theme.json Partials + +Like theme style variation partials, those for block style variations reside within a theme's `/styles` directory. However, they are differentiated from theme style variations by the introduction of a top-level property called `blockTypes`. The `blockTypes` property is an array of block types for which the block style variation has been registered. + +Additionally, a `slug` property is available to provide consistency between the different sources that may define block style variations and to decouple the `slug` from the translatable `title` property. + +The following is an example of a `theme.json` partial that defines styles for the "Variation A" block style for the Group, Columns, and Media & Text block types: + +```json +{ + "$schema": "https://schemas.wp.org/trunk/theme.json", + "version": 3, + "title": "Variation A", + "slug": "variation-a", + "blockTypes": [ "core/group", "core/columns", "core/media-text" ], + "styles": { + "color": { + "background": "#eed8d3", + "text": "#201819" + }, + "elements": { + "heading": { + "color": { + "text": "#201819" + } + } + }, + "blocks": { + "core/group": { + "color": { + "background": "#825f58", + "text": "#eed8d3" + }, + "elements": { + "heading": { + "color": { + "text": "#eed8d3" + } + } + } + } + } + } +} +``` + +##### Programmatically Registering Variation Styles + +As an alternative to `theme.json` partials, you can register variation styles at the same time as registering the variation itself through `register_block_style`. This is done by registering the block style for an array of block types while also passing a "style object" within the `style_data` option. + +The example below registers a "Green" variation for the Group and Columns blocks. Note that the style object passed via `style_data` follows the same shape as the `styles` property of a `theme.json` partial. + +```php +register_block_style( + array( 'core/group', 'core/columns' ), + array( + 'name' => 'green', + 'label' => __( 'Green' ), + 'style_data' => array( + 'color' => array( + 'background' => '#4f6f52', + 'text' => '#d2e3c8', + ), + 'blocks' => array( + 'core/group' => array( + 'color' => array( + 'background' => '#739072', + 'text' => '#e3eedd', + ), + ), + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => '#ead196', + ), + ':hover' => array( + 'color' => array( + 'text' => '#ebd9b4', + ), + ), + ), + ), + ), + ) +); +``` + ### customTemplates
Supported in WordPress from version 5.9.
From 854b84db032768e3d7932fe006a09b8824fa9404 Mon Sep 17 00:00:00 2001 From: Rishit Gupta Date: Fri, 20 Dec 2024 14:36:38 +0530 Subject: [PATCH 3/5] Fix: Inserter category tabs: avoid unnecessary aria-label (#68160) Co-authored-by: Rishit30G Co-authored-by: Mamaduka Co-authored-by: afercia --- .../block-editor/src/components/inserter/category-tabs/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/inserter/category-tabs/index.js b/packages/block-editor/src/components/inserter/category-tabs/index.js index ff0a130f1a8271..2f70ea58f2532a 100644 --- a/packages/block-editor/src/components/inserter/category-tabs/index.js +++ b/packages/block-editor/src/components/inserter/category-tabs/index.js @@ -64,7 +64,6 @@ function CategoryTabs( { Date: Fri, 20 Dec 2024 14:58:54 +0530 Subject: [PATCH 4/5] Query Total block: Reduce concatenation in the output text (#68150) Co-authored-by: sarthaknagoshe2002 Co-authored-by: swissspidy --- .../block-library/src/query-total/index.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/block-library/src/query-total/index.php b/packages/block-library/src/query-total/index.php index 5a8ab76b5d1ef4..c78d0498f634f1 100644 --- a/packages/block-library/src/query-total/index.php +++ b/packages/block-library/src/query-total/index.php @@ -43,16 +43,16 @@ function render_block_core_query_total( $attributes, $content, $block ) { $range_text = sprintf( /* translators: 1: Start index of posts, 2: Total number of posts */ __( 'Displaying %1$s of %2$s' ), - '' . $start . '', - '' . $max_rows . '' + $start, + $max_rows ); } else { $range_text = sprintf( /* translators: 1: Start index of posts, 2: End index of posts, 3: Total number of posts */ __( 'Displaying %1$s – %2$s of %3$s' ), - '' . $start . '', - '' . $end . '', - '' . $max_rows . '' + $start, + $end, + $max_rows ); } @@ -61,10 +61,11 @@ function render_block_core_query_total( $attributes, $content, $block ) { case 'total-results': default: - $output = sprintf( - '

%d %s

', - $max_rows, - _n( 'result found', 'results found', $max_rows ) + // translators: %d: number of results. + $total_text = sprintf( _n( '%d result found', '%d results found', $max_rows ), $max_rows ); + $output = sprintf( + '

%s

', + $total_text ); break; } From 94df94101b05a7884f1fd783321f0b3cde6501e5 Mon Sep 17 00:00:00 2001 From: Karthick M <97787966+karthick-murugan@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:32:15 +0530 Subject: [PATCH 5/5] Add confirm dialog before Permanently delete (#67824) Co-authored-by: karthick-murugan Co-authored-by: ntsekouras Co-authored-by: Mamaduka Co-authored-by: annezazu Co-authored-by: ammar-Mohamed-elz3eeem Co-authored-by: jameskoster Co-authored-by: afercia --- .../src/actions/permanently-delete-post.tsx | 243 +++++++++++------- 1 file changed, 157 insertions(+), 86 deletions(-) diff --git a/packages/fields/src/actions/permanently-delete-post.tsx b/packages/fields/src/actions/permanently-delete-post.tsx index 688ba5b9918df8..136fcdda9a3e68 100644 --- a/packages/fields/src/actions/permanently-delete-post.tsx +++ b/packages/fields/src/actions/permanently-delete-post.tsx @@ -2,10 +2,19 @@ * WordPress dependencies */ import { store as coreStore } from '@wordpress/core-data'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _n, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import type { Action } from '@wordpress/dataviews'; import { trash } from '@wordpress/icons'; +import { useState } from '@wordpress/element'; +import { useDispatch } from '@wordpress/data'; +import { + Button, + __experimentalText as Text, + __experimentalHStack as HStack, + __experimentalVStack as VStack, +} from '@wordpress/components'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Internal dependencies @@ -25,93 +34,155 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { const { status, permissions } = item; return status === 'trash' && permissions?.delete; }, - async callback( posts, { registry, onActionPerformed } ) { + hideModalHeader: true, + RenderModal: ( { items, closeModal, onActionPerformed } ) => { + const [ isBusy, setIsBusy ] = useState( false ); const { createSuccessNotice, createErrorNotice } = - registry.dispatch( noticesStore ); - const { deleteEntityRecord } = registry.dispatch( coreStore ); - const promiseResult = await Promise.allSettled( - posts.map( ( post ) => { - return deleteEntityRecord( - 'postType', - post.type, - post.id, - { force: true }, - { throwOnError: true } - ); - } ) + useDispatch( noticesStore ); + const { deleteEntityRecord } = useDispatch( coreStore ); + + return ( + + + { items.length > 1 + ? sprintf( + // translators: %d: number of items to delete. + _n( + 'Are you sure you want to permanently delete %d item?', + 'Are you sure you want to permanently delete %d items?', + items.length + ), + items.length + ) + : sprintf( + // translators: %s: The post's title + __( + 'Are you sure you want to permanently delete "%s"?' + ), + decodeEntities( getItemTitle( items[ 0 ] ) ) + ) } + + + + + + ); - // If all the promises were fulfilled with success. - if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) { - let successMessage; - if ( promiseResult.length === 1 ) { - successMessage = sprintf( - /* translators: The posts's title. */ - __( '"%s" permanently deleted.' ), - getItemTitle( posts[ 0 ] ) - ); - } else { - successMessage = __( 'The items were permanently deleted.' ); - } - createSuccessNotice( successMessage, { - type: 'snackbar', - id: 'permanently-delete-post-action', - } ); - onActionPerformed?.( posts ); - } else { - // If there was at lease one failure. - let errorMessage; - // If we were trying to permanently delete a single post. - if ( promiseResult.length === 1 ) { - const typedError = promiseResult[ 0 ] as { - reason?: CoreDataError; - }; - if ( typedError.reason?.message ) { - errorMessage = typedError.reason.message; - } else { - errorMessage = __( - 'An error occurred while permanently deleting the item.' - ); - } - // If we were trying to permanently delete multiple posts - } else { - const errorMessages = new Set(); - const failedPromises = promiseResult.filter( - ( { status } ) => status === 'rejected' - ); - for ( const failedPromise of failedPromises ) { - const typedError = failedPromise as { - reason?: CoreDataError; - }; - if ( typedError.reason?.message ) { - errorMessages.add( typedError.reason.message ); - } - } - if ( errorMessages.size === 0 ) { - errorMessage = __( - 'An error occurred while permanently deleting the items.' - ); - } else if ( errorMessages.size === 1 ) { - errorMessage = sprintf( - /* translators: %s: an error message */ - __( - 'An error occurred while permanently deleting the items: %s' - ), - [ ...errorMessages ][ 0 ] - ); - } else { - errorMessage = sprintf( - /* translators: %s: a list of comma separated error messages */ - __( - 'Some errors occurred while permanently deleting the items: %s' - ), - [ ...errorMessages ].join( ',' ) - ); - } - } - createErrorNotice( errorMessage, { - type: 'snackbar', - } ); - } }, };