From 9d4176ca0fafcb069190d715cbdbfaa77aa9b948 Mon Sep 17 00:00:00 2001 From: Lena Morita Date: Thu, 4 Jul 2024 19:44:19 +0900 Subject: [PATCH 1/4] ToolbarButton: Always keep focusable when disabled (#63102) * ToolbarButton: Always keep focusable when disabled * Omit `__experimentalIsFocusable` from TS types * Fixup * Add changelog * Clarify deprecation comment Co-authored-by: Marco Ciampini --------- Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo Co-authored-by: tyxla Co-authored-by: jeryj Co-authored-by: t-hamano --- packages/components/CHANGELOG.md | 1 + .../components/src/toolbar/toolbar-button/index.tsx | 8 ++++++-- .../components/src/toolbar/toolbar-button/types.ts | 10 ++++++++++ packages/components/src/toolbar/toolbar-item/index.tsx | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 70f6ebd704f74e..9d3903f70e2add 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -12,6 +12,7 @@ ### Enhancements - `ToolbarButton`: Deprecate `isDisabled` prop and merge with `disabled` ([#63101](https://github.com/WordPress/gutenberg/pull/63101)). +- `ToolbarButton`: Always keep focusable when disabled ([#63102](https://github.com/WordPress/gutenberg/pull/63102)). ### Internal diff --git a/packages/components/src/toolbar/toolbar-button/index.tsx b/packages/components/src/toolbar/toolbar-button/index.tsx index 48f385fa1abaff..a8967df75690c0 100644 --- a/packages/components/src/toolbar/toolbar-button/index.tsx +++ b/packages/components/src/toolbar/toolbar-button/index.tsx @@ -16,7 +16,7 @@ import Button from '../../button'; import ToolbarItem from '../toolbar-item'; import ToolbarContext from '../toolbar-context'; import ToolbarButtonContainer from './toolbar-button-container'; -import type { ToolbarButtonProps } from './types'; +import type { ToolbarButtonDeprecatedProps, ToolbarButtonProps } from './types'; import type { WordPressComponentProps } from '../../context'; function useDeprecatedProps( { @@ -30,7 +30,11 @@ function useDeprecatedProps( { } function UnforwardedToolbarButton( - props: WordPressComponentProps< ToolbarButtonProps, typeof Button, false >, + props: Omit< + WordPressComponentProps< ToolbarButtonProps, typeof Button, false >, + '__experimentalIsFocusable' // ToolbarButton will always be focusable even when disabled. + > & + ToolbarButtonDeprecatedProps, ref: ForwardedRef< any > ) { const { diff --git a/packages/components/src/toolbar/toolbar-button/types.ts b/packages/components/src/toolbar/toolbar-button/types.ts index bcd349c0d89363..59965e66d13472 100644 --- a/packages/components/src/toolbar/toolbar-button/types.ts +++ b/packages/components/src/toolbar/toolbar-button/types.ts @@ -37,6 +37,16 @@ export type ToolbarButtonProps = { title?: string; }; +export type ToolbarButtonDeprecatedProps = { + /** + * Whether to keep the button focusable when disabled. + * + * @deprecated ToolbarButton will always be focusable even when disabled. + * @ignore + */ + __experimentalIsFocusable?: boolean; +}; + export type ToolbarButtonContainerProps = { /** * Children to be rendered inside the button container. diff --git a/packages/components/src/toolbar/toolbar-item/index.tsx b/packages/components/src/toolbar/toolbar-item/index.tsx index 2c343eb173a27b..7f4ccb7f659cdc 100644 --- a/packages/components/src/toolbar/toolbar-item/index.tsx +++ b/packages/components/src/toolbar/toolbar-item/index.tsx @@ -50,6 +50,7 @@ function ToolbarItem( return ( Date: Thu, 4 Jul 2024 12:50:45 +0200 Subject: [PATCH 2/4] Update: Move template areas into a panel. (#62033) Co-authored-by: jorgefilipecosta Co-authored-by: jameskoster Co-authored-by: jasmussen --- .../block-quick-navigation/index.js | 49 +++++----- .../editor/src/components/sidebar/index.js | 4 +- .../src/components/sidebar/post-summary.js | 2 - .../src/components/template-areas/index.js | 94 ------------------- .../src/components/template-areas/style.scss | 22 ----- .../template-content-panel/index.js | 34 ++++++- .../editor/src/store/private-selectors.js | 25 ----- packages/editor/src/style.scss | 1 - 8 files changed, 51 insertions(+), 180 deletions(-) delete mode 100644 packages/editor/src/components/template-areas/index.js delete mode 100644 packages/editor/src/components/template-areas/style.scss diff --git a/packages/block-editor/src/components/block-quick-navigation/index.js b/packages/block-editor/src/components/block-quick-navigation/index.js index 7a0e7984b83cb7..63d0edbb868aa8 100644 --- a/packages/block-editor/src/components/block-quick-navigation/index.js +++ b/packages/block-editor/src/components/block-quick-navigation/index.js @@ -10,18 +10,16 @@ import { FlexBlock, FlexItem, } from '@wordpress/components'; -import { - __experimentalGetBlockLabel, - store as blocksStore, -} from '@wordpress/blocks'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../store'; import BlockIcon from '../block-icon'; +import useBlockDisplayInformation from '../use-block-display-information'; +import useBlockDisplayTitle from '../block-title/use-block-display-title'; -export default function BlockQuickNavigation( { clientIds } ) { +export default function BlockQuickNavigation( { clientIds, onSelect } ) { if ( ! clientIds.length ) { return null; } @@ -29,6 +27,7 @@ export default function BlockQuickNavigation( { clientIds } ) { { clientIds.map( ( clientId ) => ( @@ -37,29 +36,18 @@ export default function BlockQuickNavigation( { clientIds } ) { ); } -function BlockQuickNavigationItem( { clientId } ) { - const { name, icon, isSelected } = useSelect( +function BlockQuickNavigationItem( { clientId, onSelect } ) { + const blockInformation = useBlockDisplayInformation( clientId ); + const blockTitle = useBlockDisplayTitle( { + clientId, + context: 'list-view', + } ); + const { isSelected } = useSelect( ( select ) => { - const { - getBlockName, - getBlockAttributes, - isBlockSelected, - hasSelectedInnerBlock, - } = select( blockEditorStore ); - const { getBlockType } = select( blocksStore ); - - const blockType = getBlockType( getBlockName( clientId ) ); - const attributes = getBlockAttributes( clientId ); + const { isBlockSelected, hasSelectedInnerBlock } = + select( blockEditorStore ); return { - name: - blockType && - __experimentalGetBlockLabel( - blockType, - attributes, - 'list-view' - ), - icon: blockType?.icon, isSelected: isBlockSelected( clientId ) || hasSelectedInnerBlock( clientId, /* deep: */ true ), @@ -72,14 +60,19 @@ function BlockQuickNavigationItem( { clientId } ) { return ( diff --git a/packages/editor/src/components/sidebar/index.js b/packages/editor/src/components/sidebar/index.js index 668f8bc7b85175..dbd33459b7f0f8 100644 --- a/packages/editor/src/components/sidebar/index.js +++ b/packages/editor/src/components/sidebar/index.js @@ -112,9 +112,7 @@ const SidebarContent = ( { - { renderingMode !== 'post-only' && ( - - ) } + diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js index 676c330e708db3..a6a95d36388ba5 100644 --- a/packages/editor/src/components/sidebar/post-summary.js +++ b/packages/editor/src/components/sidebar/post-summary.js @@ -28,7 +28,6 @@ import BlogTitle from '../blog-title'; import PostsPerPage from '../posts-per-page'; import SiteDiscussion from '../site-discussion'; import { store as editorStore } from '../../store'; -import TemplateAreas from '../template-areas'; import { PrivatePostLastRevision } from '../post-last-revision'; /** @@ -84,7 +83,6 @@ export default function PostSummary( { onActionPerformed } ) { - { fills } ) } diff --git a/packages/editor/src/components/template-areas/index.js b/packages/editor/src/components/template-areas/index.js deleted file mode 100644 index 0d3bbe42d02eed..00000000000000 --- a/packages/editor/src/components/template-areas/index.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { - Button, - __experimentalHeading as Heading, -} from '@wordpress/components'; - -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -import { TEMPLATE_POST_TYPE } from '../../store/constants'; - -function TemplateAreaItem( { area, clientId } ) { - const { selectBlock, toggleBlockHighlight } = - useDispatch( blockEditorStore ); - const templatePartArea = useSelect( - ( select ) => { - const defaultAreas = - select( - editorStore - ).__experimentalGetDefaultTemplatePartAreas(); - - return defaultAreas.find( - ( defaultArea ) => defaultArea.area === area - ); - }, - [ area ] - ); - - const highlightBlock = () => toggleBlockHighlight( clientId, true ); - const cancelHighlightBlock = () => toggleBlockHighlight( clientId, false ); - - return ( - - ); -} - -export default function TemplateAreas() { - const { isTemplate, templateParts } = useSelect( ( select ) => { - const _isTemplate = - select( editorStore ).getCurrentPostType() === TEMPLATE_POST_TYPE; - - return { - isTemplate: _isTemplate, - templateParts: - _isTemplate && - unlock( - select( editorStore ) - ).getCurrentTemplateTemplateParts(), - }; - }, [] ); - - if ( ! isTemplate || ! templateParts.length ) { - return null; - } - - return ( -
- - { __( 'Areas' ) } - - -
    - { templateParts.map( ( { templatePart, block } ) => ( -
  • - -
  • - ) ) } -
-
- ); -} diff --git a/packages/editor/src/components/template-areas/style.scss b/packages/editor/src/components/template-areas/style.scss deleted file mode 100644 index 4a0dcd748c2edf..00000000000000 --- a/packages/editor/src/components/template-areas/style.scss +++ /dev/null @@ -1,22 +0,0 @@ -.editor-template-areas { - &__list { - margin: 0; - > li { - margin: 0; - } - } - - &__item { - width: 100%; - - // Override the default padding. - &.components-button.has-icon { - padding: 0; - } - } -} - -h3.components-heading.editor-template-areas__title { - font-weight: 500; - margin: 0 0 $grid-unit-10; -} diff --git a/packages/editor/src/components/template-content-panel/index.js b/packages/editor/src/components/template-content-panel/index.js index e0f131f27feb5d..14532387ecd059 100644 --- a/packages/editor/src/components/template-content-panel/index.js +++ b/packages/editor/src/components/template-content-panel/index.js @@ -1,18 +1,21 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; +import { useSelect, useDispatch } from '@wordpress/data'; import { store as blockEditorStore, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { PanelBody } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; +import { store as interfaceStore } from '@wordpress/interface'; /** * Internal dependencies */ import { unlock } from '../../lock-unlock'; +import { TEMPLATE_POST_TYPE } from '../../store/constants'; +import { store as editorStore } from '../../store'; const { BlockQuickNavigation } = unlock( blockEditorPrivateApis ); @@ -22,15 +25,36 @@ const PAGE_CONTENT_BLOCKS = [ 'core/post-title', ]; -export default function TemplateContentPanel() { - const clientIds = useSelect( ( select ) => { +const TEMPLATE_PART_BLOCK = 'core/template-part'; + +export default function TemplateContentPanel( { renderingMode } ) { + const { enableComplementaryArea } = useDispatch( interfaceStore ); + const { clientIds, postType } = useSelect( ( select ) => { const { getBlocksByName } = select( blockEditorStore ); - return getBlocksByName( PAGE_CONTENT_BLOCKS ); + const { getCurrentPostType } = select( editorStore ); + const _postType = getCurrentPostType(); + return { + postType: _postType, + clientIds: getBlocksByName( + TEMPLATE_POST_TYPE === _postType + ? TEMPLATE_PART_BLOCK + : PAGE_CONTENT_BLOCKS + ), + }; }, [] ); + if ( renderingMode === 'post-only' && postType !== TEMPLATE_POST_TYPE ) { + return null; + } + return ( - + { + enableComplementaryArea( 'core', 'edit-post/document' ); + } } + /> ); } diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index f56e1e8c9e81fb..c635cbc816f92b 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -25,8 +25,6 @@ import { getCurrentPost, __experimentalGetDefaultTemplatePartAreas, } from './selectors'; -import { TEMPLATE_PART_POST_TYPE } from './constants'; -import { getFilteredTemplatePartBlocks } from './utils/get-filtered-template-parts'; import { getEntityActions as _getEntityActions } from '../dataviews/store/private-selectors'; const EMPTY_INSERTION_POINT = { @@ -120,29 +118,6 @@ export const getPostIcon = createRegistrySelector( } ); -/** - * Returns the template parts and their blocks for the current edited template. - * - * @param {Object} state Global application state. - * @return {Array} Template parts and their blocks in an array. - */ -export const getCurrentTemplateTemplateParts = createRegistrySelector( - ( select ) => () => { - const templateParts = select( coreStore ).getEntityRecords( - 'postType', - TEMPLATE_PART_POST_TYPE, - { per_page: -1 } - ); - - const clientIds = - select( blockEditorStore ).getBlocksByName( 'core/template-part' ); - const blocks = - select( blockEditorStore ).getBlocksByClientId( clientIds ); - - return getFilteredTemplatePartBlocks( blocks, templateParts ); - } -); - /** * Returns true if there are unsaved changes to the * post's meta fields, and false otherwise. diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index a4034a8a51c733..d1af3095230f34 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -54,6 +54,5 @@ @import "./components/sidebar/style.scss"; @import "./components/site-discussion/style.scss"; @import "./components/table-of-contents/style.scss"; -@import "./components/template-areas/style.scss"; @import "./components/text-editor/style.scss"; @import "./components/visual-editor/style.scss"; From bd8a9376e10f485d640b13ab84b29dbae6cf6f70 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 4 Jul 2024 20:06:29 +0900 Subject: [PATCH 3/4] Table Block: Add toolbar button to add a caption (#47984) * Use Caption component * Fix e2e test Co-authored-by: t-hamano Co-authored-by: kevin940726 Co-authored-by: afercia Co-authored-by: Mamaduka Co-authored-by: BenjaminZekavica --- packages/block-library/src/table/edit.js | 35 +++++++--------------- test/e2e/specs/editor/blocks/table.spec.js | 9 +++--- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/packages/block-library/src/table/edit.js b/packages/block-library/src/table/edit.js index f0c3ece7908633..5510d0031ff6be 100644 --- a/packages/block-library/src/table/edit.js +++ b/packages/block-library/src/table/edit.js @@ -16,7 +16,6 @@ import { useBlockProps, __experimentalUseColorProps as useColorProps, __experimentalUseBorderProps as useBorderProps, - __experimentalGetElementClassName, } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; import { @@ -41,7 +40,6 @@ import { tableRowDelete, table, } from '@wordpress/icons'; -import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; /** * Internal dependencies @@ -57,6 +55,7 @@ import { toggleSection, isEmptyTableSection, } from './state'; +import { Caption } from '../utils/caption'; const ALIGNMENT_CONTROLS = [ { @@ -98,7 +97,7 @@ function TableEdit( { insertBlocksAfter, isSelected, } ) { - const { hasFixedLayout, caption, head, foot } = attributes; + const { hasFixedLayout, head, foot } = attributes; const [ initialRowCount, setInitialRowCount ] = useState( 2 ); const [ initialColumnCount, setInitialColumnCount ] = useState( 2 ); const [ selectedCell, setSelectedCell ] = useState(); @@ -523,27 +522,7 @@ function TableEdit( { { renderedSections } ) } - { ! isEmpty && ( - - setAttributes( { caption: value } ) - } - // Deselect the selected table cell when the caption is focused. - onFocus={ () => setSelectedCell() } - __unstableOnSplitAtEnd={ () => - insertBlocksAfter( - createBlock( getDefaultBlockName() ) - ) - } - /> - ) } - { isEmpty && ( + { isEmpty ? ( } @@ -582,6 +561,14 @@ function TableEdit( { + ) : ( + ) } ); diff --git a/test/e2e/specs/editor/blocks/table.spec.js b/test/e2e/specs/editor/blocks/table.spec.js index 1e6dfdcd76e188..92e209e88aeb17 100644 --- a/test/e2e/specs/editor/blocks/table.spec.js +++ b/test/e2e/specs/editor/blocks/table.spec.js @@ -275,10 +275,11 @@ test.describe( 'Table', () => { .locator( 'role=button[name="Create Table"i]' ) .click(); - // Click the first cell and add some text. - await editor.canvas - .locator( 'role=document[name="Block: Table"i] >> figcaption' ) - .click(); + await editor.clickBlockToolbarButton( 'Add caption' ); + const caption = editor.canvas.locator( + 'role=textbox[name="Table caption text"i]' + ); + await expect( caption ).toBeFocused(); await page.keyboard.type( 'Caption!' ); expect( await editor.getEditedPostContent() ).toMatchSnapshot(); } ); From d51d7e5327efd8cf7d0fbe87594df9f7addd8cab Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Thu, 4 Jul 2024 13:25:50 +0200 Subject: [PATCH 4/4] Fix: Permanently delete post action does not calls onActionPerformed. (#63121) Co-authored-by: jorgefilipecosta --- packages/editor/src/components/post-actions/actions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index 2f97d0aa9d0a8e..fa6456a05e2c74 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -276,7 +276,7 @@ const permanentlyDeletePostAction = { isEligible( { status } ) { return status === 'trash'; }, - async callback( posts, { registry } ) { + async callback( posts, { registry, onActionPerformed } ) { const { createSuccessNotice, createErrorNotice } = registry.dispatch( noticesStore ); const { deleteEntityRecord } = registry.dispatch( coreStore ); @@ -307,6 +307,7 @@ const permanentlyDeletePostAction = { type: 'snackbar', id: 'permanently-delete-post-action', } ); + onActionPerformed?.( posts ); } else { // If there was at lease one failure. let errorMessage;