diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 360ceef02c5754..5ba19b090d9258 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -6,6 +6,10 @@ - `LineHeightControl`: Remove deprecated `__nextHasNoMarginBottom` prop and promote to default behavior ([#64281](https://github.com/WordPress/gutenberg/pull/64281)). +### Enhancements + +- `FontFamilyControl`: Add `__nextHasNoMarginBottom` prop for opting into the new margin-free styles ([#64280](https://github.com/WordPress/gutenberg/pull/64280)). + ## 13.4.0 (2024-07-24) ## 13.3.0 (2024-07-10) diff --git a/packages/block-editor/src/components/font-family/README.md b/packages/block-editor/src/components/font-family/README.md index 5300873ab83459..6b37459fd127e7 100644 --- a/packages/block-editor/src/components/font-family/README.md +++ b/packages/block-editor/src/components/font-family/README.md @@ -24,6 +24,7 @@ const MyFontFamilyControl = () => { onChange={ ( newFontFamily ) => { setFontFamily( newFontFamily ); } } + __nextHasNoMarginBottom /> ); }; @@ -69,3 +70,10 @@ The current font family value. - Default: '' The rest of the props are passed down to the underlying `` instance. + +#### `__nextHasNoMarginBottom` + +- **Type:** `boolean` +- **Default:** `false` + +Start opting into the new margin-free styles that will become the default in a future version. diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js index 4a40a880e537cb..90a0412463b3ef 100644 --- a/packages/block-editor/src/components/font-family/index.js +++ b/packages/block-editor/src/components/font-family/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { SelectControl } from '@wordpress/components'; +import deprecated from '@wordpress/deprecated'; import { __ } from '@wordpress/i18n'; /** @@ -10,6 +11,8 @@ import { __ } from '@wordpress/i18n'; import { useSettings } from '../use-settings'; export default function FontFamilyControl( { + /** Start opting into the new margin-free styles that will become the default in a future version. */ + __nextHasNoMarginBottom = false, value = '', onChange, fontFamilies, @@ -33,8 +36,21 @@ export default function FontFamilyControl( { }; } ), ]; + + if ( ! __nextHasNoMarginBottom ) { + deprecated( + 'Bottom margin styles for wp.blockEditor.FontFamilyControl', + { + since: '6.7', + version: '7.0', + hint: 'Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version', + } + ); + } + return ( + ); + }, + args: { + fontFamilies: [ + { + fontFace: [ + { + fontFamily: 'Inter', + fontStretch: 'normal', + fontStyle: 'normal', + fontWeight: '200 900', + src: [ + 'file:./assets/fonts/inter/Inter-VariableFont_slnt,wght.ttf', + ], + }, + ], + fontFamily: '"Inter", sans-serif', + name: 'Inter', + slug: 'inter', + }, + { + fontFamily: + '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif', + name: 'System Font', + slug: 'system-font', + }, + ], + __nextHasNoMarginBottom: true, + }, +}; diff --git a/packages/block-editor/src/components/grid/use-grid-layout-sync.js b/packages/block-editor/src/components/grid/use-grid-layout-sync.js index 2cc17eed6b33bf..3e31530d4e526f 100644 --- a/packages/block-editor/src/components/grid/use-grid-layout-sync.js +++ b/packages/block-editor/src/components/grid/use-grid-layout-sync.js @@ -10,6 +10,7 @@ import { usePrevious } from '@wordpress/compose'; */ import { store as blockEditorStore } from '../../store'; import { GridRect } from './utils'; +import { setImmutably } from '../../utils/object'; export function useGridLayoutSync( { clientId: gridClientId } ) { const { gridLayout, blockOrder, selectedBlockLayout } = useSelect( @@ -26,7 +27,8 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { [ gridClientId ] ); - const { getBlockAttributes } = useSelect( blockEditorStore ); + const { getBlockAttributes, getBlockRootClientId } = + useSelect( blockEditorStore ); const { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); @@ -40,6 +42,7 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { const previousIsManualPlacement = usePrevious( gridLayout.isManualPlacement ); + const previousBlockOrder = usePrevious( blockOrder ); useEffect( () => { const updates = {}; @@ -123,6 +126,46 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { }, }; } + + // Unset grid layout attributes for blocks removed from the grid. + for ( const clientId of previousBlockOrder ?? [] ) { + if ( ! blockOrder.includes( clientId ) ) { + const rootClientId = getBlockRootClientId( clientId ); + + // Block was removed from the editor, so nothing to do. + if ( rootClientId === null ) { + continue; + } + + // Check if the block is being moved to another grid. + // If so, do nothing and let the new grid parent handle + // the attributes. + const rootAttributes = getBlockAttributes( rootClientId ); + if ( rootAttributes?.layout?.type === 'grid' ) { + continue; + } + + const attributes = getBlockAttributes( clientId ); + const { + columnStart, + rowStart, + columnSpan, + rowSpan, + ...layout + } = attributes.style?.layout ?? {}; + + if ( columnStart || rowStart || columnSpan || rowSpan ) { + const hasEmptyLayoutAttribute = + Object.keys( layout ).length === 0; + + updates[ clientId ] = setImmutably( + attributes, + [ 'style', 'layout' ], + hasEmptyLayoutAttribute ? undefined : layout + ); + } + } + } } else { // Remove all of the columnStart and rowStart values // when switching from manual to auto mode, @@ -133,12 +176,14 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { attributes.style?.layout ?? {}; // Only update attributes if columnStart or rowStart are set. if ( columnStart || rowStart ) { - updates[ clientId ] = { - style: { - ...attributes.style, - layout, - }, - }; + const hasEmptyLayoutAttribute = + Object.keys( layout ).length === 0; + + updates[ clientId ] = setImmutably( + attributes, + [ 'style', 'layout' ], + hasEmptyLayoutAttribute ? undefined : layout + ); } } } @@ -166,12 +211,14 @@ export function useGridLayoutSync( { clientId: gridClientId } ) { // Actual deps to sync: gridClientId, gridLayout, + previousBlockOrder, blockOrder, previouslySelectedBlockRect, previousIsManualPlacement, // These won't change, but the linter thinks they might: __unstableMarkNextChangeAsNotPersistent, getBlockAttributes, + getBlockRootClientId, updateBlockAttributes, ] ); } diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index 6605d2de502fe8..4faf05ba254089 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -9,7 +9,7 @@ import { __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, - privateApis as componentsPrivateApis, + CustomSelectControl, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useState, useMemo } from '@wordpress/element'; @@ -31,11 +31,6 @@ import { getPresetValueFromCustomValue, isValueSpacingPreset, } from '../utils'; -import { unlock } from '../../../lock-unlock'; - -const { CustomSelectControlV2Legacy: CustomSelectControl } = unlock( - componentsPrivateApis -); const CUSTOM_VALUE_SETTINGS = { px: { max: 300, steps: 1 }, diff --git a/packages/block-editor/src/components/use-block-drop-zone/index.js b/packages/block-editor/src/components/use-block-drop-zone/index.js index 857a132f1f9fa4..415ed5070d28da 100644 --- a/packages/block-editor/src/components/use-block-drop-zone/index.js +++ b/packages/block-editor/src/components/use-block-drop-zone/index.js @@ -301,8 +301,10 @@ export default function useBlockDropZone( { operation: 'insert', } ); - const { getBlockType } = useSelect( blocksStore ); + const { getBlockType, getBlockVariations, getGroupingBlockName } = + useSelect( blocksStore ); const { + canInsertBlockType, getBlockListSettings, getBlocks, getBlockIndex, @@ -310,6 +312,7 @@ export default function useBlockDropZone( { getBlockNamesByClientId, getAllowedBlocks, isDragging, + isGroupable, } = unlock( useSelect( blockEditorStore ) ); const { showInsertionPoint, @@ -385,21 +388,66 @@ export default function useBlockDropZone( { }; } ); + const dropTargetPosition = getDropTargetPosition( + blocksData, + { x: event.clientX, y: event.clientY }, + getBlockListSettings( targetRootClientId )?.orientation, + { + dropZoneElement, + parentBlockClientId, + parentBlockOrientation: parentBlockClientId + ? getBlockListSettings( parentBlockClientId ) + ?.orientation + : undefined, + rootBlockIndex: getBlockIndex( targetRootClientId ), + } + ); + const [ targetIndex, operation, nearestSide ] = - getDropTargetPosition( - blocksData, - { x: event.clientX, y: event.clientY }, - getBlockListSettings( targetRootClientId )?.orientation, - { - dropZoneElement, - parentBlockClientId, - parentBlockOrientation: parentBlockClientId - ? getBlockListSettings( parentBlockClientId ) - ?.orientation - : undefined, - rootBlockIndex: getBlockIndex( targetRootClientId ), - } + dropTargetPosition; + + if ( operation === 'group' ) { + const targetBlock = blocks[ targetIndex ]; + const areAllImages = [ + targetBlock.name, + ...draggedBlockNames, + ].every( ( name ) => name === 'core/image' ); + const canInsertGalleryBlock = canInsertBlockType( + 'core/gallery', + targetRootClientId ); + const areGroupableBlocks = isGroupable( [ + targetBlock.clientId, + getDraggedBlockClientIds(), + ] ); + const groupBlockVariations = getBlockVariations( + getGroupingBlockName(), + 'block' + ); + const canInsertRow = + groupBlockVariations && + groupBlockVariations.find( + ( { name } ) => name === 'group-row' + ); + + // If the dragged blocks and the target block are all images, + // check if it is creatable either a Row variation or a Gallery block. + if ( + areAllImages && + ! canInsertGalleryBlock && + ( ! areGroupableBlocks || ! canInsertRow ) + ) { + return; + } + // If the dragged blocks and the target block are not all images, + // check if it is creatable a Row variation. + if ( + ! areAllImages && + ( ! areGroupableBlocks || ! canInsertRow ) + ) { + return; + } + } registry.batch( () => { setDropTarget( { @@ -436,6 +484,10 @@ export default function useBlockDropZone( { showInsertionPoint, isDragging, startDragging, + canInsertBlockType, + getBlockVariations, + getGroupingBlockName, + isGroupable, ] ), 200 diff --git a/packages/block-editor/src/components/use-on-block-drop/index.js b/packages/block-editor/src/components/use-on-block-drop/index.js index 420cd398edfa39..75b9a44e166f5c 100644 --- a/packages/block-editor/src/components/use-on-block-drop/index.js +++ b/packages/block-editor/src/components/use-on-block-drop/index.js @@ -232,7 +232,6 @@ export default function useOnBlockDrop( getBlocksByClientId, getSettings, getBlock, - isGroupable, } = useSelect( blockEditorStore ); const { getGroupingBlockName } = useSelect( blocksStore ); const { @@ -255,17 +254,11 @@ export default function useOnBlockDrop( if ( ! Array.isArray( blocks ) ) { blocks = [ blocks ]; } - const clientIds = getBlockOrder( targetRootClientId ); const clientId = clientIds[ targetBlockIndex ]; - const blocksClientIds = blocks.map( ( block ) => block.clientId ); - const areGroupableBlocks = isGroupable( [ - ...blocksClientIds, - clientId, - ] ); if ( operation === 'replace' ) { replaceBlocks( clientId, blocks, undefined, initialPosition ); - } else if ( operation === 'group' && areGroupableBlocks ) { + } else if ( operation === 'group' ) { const targetBlock = getBlock( clientId ); if ( nearestSide === 'left' ) { blocks.push( targetBlock ); @@ -325,7 +318,6 @@ export default function useOnBlockDrop( getBlockOrder, targetRootClientId, targetBlockIndex, - isGroupable, operation, replaceBlocks, getBlock, diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 226183e04396ef..652c89fd3540e2 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Feature + +- Query Loop Block: Moves per page, offset, and pages controls into Inspector Controls. ([#58207](https://github.com/WordPress/gutenberg/pull/58207)) + ## 9.4.0 (2024-07-24) ## 9.3.0 (2024-07-10) diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 5477dc1aeebf3a..829c6395e047ef 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -721,7 +721,7 @@ function Navigation( { ); const accessibleDescriptionId = `${ clientId }-desc`; - + const isHiddenByDefault = 'always' === overlayMenu; const isManageMenusButtonDisabled = ! hasManagePermissions || ! hasResolvedNavigationMenus; @@ -760,7 +760,7 @@ function Navigation( { hasIcon={ hasIcon } icon={ icon } isResponsive={ isResponsive } - isHiddenByDefault={ 'always' === overlayMenu } + isHiddenByDefault={ isHiddenByDefault } overlayBackgroundColor={ overlayBackgroundColor } overlayTextColor={ overlayTextColor } > @@ -899,13 +899,13 @@ function Navigation( { : undefined } > - { isLoading && ( + { isLoading && ! isHiddenByDefault && (
) } - { ! isLoading && ( + { ( ! isLoading || isHiddenByDefault ) && ( <> { !! postType && ( @@ -253,6 +269,47 @@ export default function QueryInspectorControls( props ) { /> ) } + { ! inherit && showDisplayPanel && ( + { + setQuery( { + offset: 0, + pages: 0, + } ); + } } + dropdownMenuProps={ dropdownMenuProps } + > + perPage > 0 } + > + + + offset > 0 } + onDeselect={ () => setQuery( { offset: 0 } ) } + > + + + pages > 0 } + onDeselect={ () => setQuery( { pages: 0 } ) } + > + + + + ) } { ! inherit && showFiltersPanel && ( { + return ( + { + if ( + isNaN( newOffset ) || + newOffset < MIN_OFFSET || + newOffset > MAX_OFFSET + ) { + return; + } + onChange( { offset: newOffset } ); + } } + /> + ); +}; + +export default OffsetControl; diff --git a/packages/block-library/src/query/edit/inspector-controls/order-control.js b/packages/block-library/src/query/edit/inspector-controls/order-control.js index 2f6fa0e589d473..d50d3349bcbafd 100644 --- a/packages/block-library/src/query/edit/inspector-controls/order-control.js +++ b/packages/block-library/src/query/edit/inspector-controls/order-control.js @@ -27,7 +27,6 @@ const orderOptions = [ function OrderControl( { order, orderBy, onChange } ) { return ( { + return ( + { + if ( isNaN( newPages ) || newPages < 0 ) { + return; + } + onChange( { pages: newPages } ); + } } + help={ __( + 'Limit the pages you want to show, even if the query has more results. To show all pages use 0 (zero).' + ) } + /> + ); +}; + +export default PagesControl; diff --git a/packages/block-library/src/query/edit/inspector-controls/per-page-control.js b/packages/block-library/src/query/edit/inspector-controls/per-page-control.js new file mode 100644 index 00000000000000..3e0dfbf50b70bd --- /dev/null +++ b/packages/block-library/src/query/edit/inspector-controls/per-page-control.js @@ -0,0 +1,33 @@ +/** + * WordPress dependencies + */ +import { RangeControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +const MIN_POSTS_PER_PAGE = 1; +const MAX_POSTS_PER_PAGE = 100; + +const PerPageControl = ( { perPage, offset = 0, onChange } ) => { + return ( + { + if ( + isNaN( newPerPage ) || + newPerPage < MIN_POSTS_PER_PAGE || + newPerPage > MAX_POSTS_PER_PAGE + ) { + return; + } + onChange( { perPage: newPerPage, offset } ); + } } + value={ parseInt( perPage, 10 ) } + /> + ); +}; + +export default PerPageControl; diff --git a/packages/block-library/src/query/edit/query-toolbar.js b/packages/block-library/src/query/edit/query-toolbar.js index ff670d7c001a6b..cc2d62a54d529f 100644 --- a/packages/block-library/src/query/edit/query-toolbar.js +++ b/packages/block-library/src/query/edit/query-toolbar.js @@ -1,14 +1,8 @@ /** * WordPress dependencies */ -import { - ToolbarGroup, - Dropdown, - ToolbarButton, - __experimentalNumberControl as NumberControl, -} from '@wordpress/components'; +import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { settings } from '@wordpress/icons'; /** * Internal dependencies @@ -16,8 +10,6 @@ import { settings } from '@wordpress/icons'; import { usePatterns } from '../utils'; export default function QueryToolbar( { - attributes: { query }, - setQuery, openPatternSelectionModal, name, clientId, @@ -26,87 +18,6 @@ export default function QueryToolbar( { return ( <> - { ! query.inherit && ( - - ( - - ) } - renderContent={ () => ( - <> - { - if ( - isNaN( value ) || - value < 1 || - value > 100 - ) { - return; - } - setQuery( { - perPage: value, - } ); - } } - step="1" - value={ query.perPage } - isDragEnabled={ false } - /> - { - if ( - isNaN( value ) || - value < 0 || - value > 100 - ) { - return; - } - setQuery( { offset: value } ); - } } - step="1" - value={ query.offset } - isDragEnabled={ false } - /> - { - if ( isNaN( value ) || value < 0 ) { - return; - } - setQuery( { pages: value } ); - } } - step="1" - value={ query.pages } - isDragEnabled={ false } - help={ __( - 'Limit the pages you want to show, even if the query has more results. To show all pages use 0 (zero).' - ) } - /> - - ) } - /> - - ) } { hasPatterns && ( diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index ac74ac2aeb6eb4..b7e47ec542d1e9 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -687,7 +687,7 @@ export default function LogoEdit( { variant="primary" label={ __( 'Choose logo' ) } showTooltip - tooltipPosition="bottom center" + tooltipPosition="middle right" onClick={ () => { open(); } } diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 570b7ac308c5fe..a71b5a0ddef35f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `ColorPalette`: Remove extra bottom margin when `CircularOptionPicker` is unneeded ([#63961](https://github.com/WordPress/gutenberg/pull/63961)). - `CustomSelectControl`: Restore `describedBy` functionality ([#63957](https://github.com/WordPress/gutenberg/pull/63957)). +- `Button`: Improve the aria-disabled focus style ([#62480](https://github.com/WordPress/gutenberg/pull/62480)). - `Modal`: Fix the dismissal logic for React development mode ([#64132](https://github.com/WordPress/gutenberg/pull/64132)). ### Enhancements diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss index 3541699a08eefd..fcbd363e17c7dd 100644 --- a/packages/components/src/button/style.scss +++ b/packages/components/src/button/style.scss @@ -30,16 +30,10 @@ } &[aria-expanded="true"], - &:hover { + &:hover:not(:disabled, [aria-disabled="true"]) { color: $components-color-accent; } - // Unset some hovers, instead of adding :not specificity. - &:disabled:hover, - &[aria-disabled="true"]:hover { - color: initial; - } - // Focus. // See https://github.com/WordPress/gutenberg/issues/13267 for more context on these selectors. &:focus:not(:disabled) { @@ -87,7 +81,6 @@ color: rgba($white, 0.4); background: $components-color-accent; border-color: $components-color-accent; - opacity: 1; outline: none; &:focus:enabled { @@ -132,7 +125,6 @@ color: $gray-600; background: transparent; transform: none; - opacity: 1; } } @@ -206,17 +198,22 @@ &:not(.is-primary):not(.is-secondary):not(.is-tertiary):not(.is-link) { color: $alert-red; - &:hover:not(:disabled) { + &:hover:not(:disabled, [aria-disabled="true"]) { color: darken($alert-red, 20%); } - &:focus:not(:disabled) { + &:focus { box-shadow: 0 0 0 var(--wp-admin-border-width-focus) $alert-red; } - &:active:not(:disabled) { + &:active:not(:disabled, [aria-disabled="true"]) { background: $gray-400; } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-600; + } } } @@ -244,6 +241,11 @@ &:focus { border-radius: $radius-block-ui; } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-600; + } } &:not(:disabled, [aria-disabled="true"]):active { @@ -253,7 +255,7 @@ &:disabled, &[aria-disabled="true"] { cursor: default; - opacity: 0.3; + color: $gray-600; } &.is-busy, @@ -266,7 +268,6 @@ @media (prefers-reduced-motion: reduce) { animation-duration: 0s; } - opacity: 1; background-size: 100px 100%; /* stylelint-disable -- Disable reason: This function call looks nicer when each argument is on its own line. */ background-image: linear-gradient( @@ -332,8 +333,23 @@ // Toggled style. &.is-pressed { - color: $components-color-foreground-inverted; - background: $components-color-foreground; + &, + &:hover { + color: $components-color-foreground-inverted; + &:not(:disabled, [aria-disabled="true"]) { + background: $components-color-foreground; + } + } + + &:disabled, + &[aria-disabled="true"] { + color: $gray-600; + + &:not(.is-primary):not(.is-secondary):not(.is-tertiary) { + color: $components-color-foreground-inverted; + background: $gray-600; + } + } &:focus:not(:disabled) { box-shadow: inset 0 0 0 1px $components-color-background, 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent; @@ -341,11 +357,6 @@ // Windows High Contrast mode will show this outline, but not the box-shadow. outline: 2px solid transparent; } - - &:hover:not(:disabled) { - color: $components-color-foreground-inverted; - background: $components-color-foreground; - } } svg { diff --git a/packages/e2e-tests/plugins/observe-typing.php b/packages/e2e-tests/plugins/observe-typing.php new file mode 100644 index 00000000000000..a9152bc79684c5 --- /dev/null +++ b/packages/e2e-tests/plugins/observe-typing.php @@ -0,0 +1,28 @@ + + el( + ToolbarButton, + { + onClick: onToggle, + }, + 'Open Dropdown' + ), + renderContent: () => + el( TextControl, { + label: 'Dropdown field', + value, + onChange: setValue, + __next40pxDefaultSize: true, + } ), + } ) + ), + el( 'p', {}, 'Hello Editor!' ) + ); + }, + save: () => null, + } ); +} )(); diff --git a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx index 42efb8a32850f3..2124fdc0ffa4ce 100644 --- a/packages/editor/src/dataviews/actions/permanently-delete-post.tsx +++ b/packages/editor/src/dataviews/actions/permanently-delete-post.tsx @@ -48,7 +48,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { getItemTitle( posts[ 0 ] ) ); } else { - successMessage = __( 'The posts were permanently deleted.' ); + successMessage = __( 'The items were permanently deleted.' ); } createSuccessNotice( successMessage, { type: 'snackbar', @@ -67,7 +67,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { errorMessage = typedError.reason.message; } else { errorMessage = __( - 'An error occurred while permanently deleting the post.' + 'An error occurred while permanently deleting the item.' ); } // If we were trying to permanently delete multiple posts @@ -86,13 +86,13 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { } if ( errorMessages.size === 0 ) { errorMessage = __( - 'An error occurred while permanently deleting the posts.' + '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 posts: %s' + 'An error occurred while permanently deleting the items: %s' ), [ ...errorMessages ][ 0 ] ); @@ -100,7 +100,7 @@ const permanentlyDeletePost: Action< PostWithPermissions > = { errorMessage = sprintf( /* translators: %s: a list of comma separated error messages */ __( - 'Some errors occurred while permanently deleting the posts: %s' + 'Some errors occurred while permanently deleting the items: %s' ), [ ...errorMessages ].join( ',' ) ); diff --git a/packages/editor/src/dataviews/actions/trash-post.tsx b/packages/editor/src/dataviews/actions/trash-post.tsx index a8e42c510a6cd0..537a0ebd79a8ac 100644 --- a/packages/editor/src/dataviews/actions/trash-post.tsx +++ b/packages/editor/src/dataviews/actions/trash-post.tsx @@ -23,7 +23,7 @@ import type { CoreDataError, PostWithPermissions } from '../types'; const trashPost: Action< PostWithPermissions > = { id: 'move-to-trash', - label: __( 'Move to Trash' ), + label: __( 'Move to trash' ), isPrimary: true, icon: trash, isEligible( item ) { @@ -51,15 +51,15 @@ const trashPost: Action< PostWithPermissions > = { ? sprintf( // translators: %s: The item's title. __( - 'Are you sure you want to move to trash "%s"?' + 'Are you sure you want to move "%s" to the trash?' ), getItemTitle( items[ 0 ] ) ) : sprintf( // translators: %d: The number of items (2 or more). _n( - 'Are you sure you want to move to trash %d item?', - 'Are you sure you want to move to trash %d items?', + 'Are you sure you want to move %d item to the trash ?', + 'Are you sure you want to move %d items to the trash ?', items.length ), items.length @@ -99,15 +99,15 @@ const trashPost: Action< PostWithPermissions > = { if ( promiseResult.length === 1 ) { successMessage = sprintf( /* translators: The item's title. */ - __( '"%s" moved to trash.' ), + __( '"%s" moved to the trash.' ), getItemTitle( items[ 0 ] ) ); } else { successMessage = sprintf( /* translators: The number of items. */ _n( - '%s item moved to trash.', - '%s items moved to trash.', + '%s item moved to the trash.', + '%s items moved to the trash.', items.length ), items.length @@ -130,7 +130,7 @@ const trashPost: Action< PostWithPermissions > = { typedError.reason.message; } else { errorMessage = __( - 'An error occurred while moving to trash the item.' + 'An error occurred while moving the item to the trash.' ); } // If we were trying to delete multiple items. @@ -151,13 +151,13 @@ const trashPost: Action< PostWithPermissions > = { } if ( errorMessages.size === 0 ) { errorMessage = __( - 'An error occurred while moving to trash the items.' + 'An error occurred while moving the items to the trash.' ); } else if ( errorMessages.size === 1 ) { errorMessage = sprintf( /* translators: %s: an error message */ __( - 'An error occurred while moving to trash the item: %s' + 'An error occurred while moving the item to the trash: %s' ), [ ...errorMessages ][ 0 ] ); @@ -165,7 +165,7 @@ const trashPost: Action< PostWithPermissions > = { errorMessage = sprintf( /* translators: %s: a list of comma separated error messages */ __( - 'Some errors occurred while moving to trash the items: %s' + 'Some errors occurred while moving the items to the trash: %s' ), [ ...errorMessages ].join( ',' ) ); diff --git a/packages/editor/src/store/private-actions.js b/packages/editor/src/store/private-actions.js index c5fe1c260071a6..0996d6eb8b9d32 100644 --- a/packages/editor/src/store/private-actions.js +++ b/packages/editor/src/store/private-actions.js @@ -393,10 +393,14 @@ export const removeTemplates = if ( items.length === 1 ) { // Depending on how the entity was retrieved its title might be // an object or simple string. - const title = - typeof items[ 0 ].title === 'string' - ? items[ 0 ].title - : items[ 0 ].title?.rendered; + let title; + if ( typeof items[ 0 ].title === 'string' ) { + title = items[ 0 ].title; + } else if ( typeof items[ 0 ].title?.rendered === 'string' ) { + title = items[ 0 ].title?.rendered; + } else if ( typeof items[ 0 ].title?.raw === 'string' ) { + title = items[ 0 ].title?.raw; + } successMessage = isResetting ? sprintf( /* translators: The template/part's name. */ diff --git a/test/e2e/specs/editor/various/change-detection.spec.js b/test/e2e/specs/editor/various/change-detection.spec.js index 4ac262f4c1348d..30b2287a8d9439 100644 --- a/test/e2e/specs/editor/various/change-detection.spec.js +++ b/test/e2e/specs/editor/various/change-detection.spec.js @@ -416,7 +416,7 @@ test.describe( 'Change detection', () => { .click(); await page .getByRole( 'menu' ) - .getByRole( 'menuitem', { name: 'Move to Trash' } ) + .getByRole( 'menuitem', { name: 'Move to trash' } ) .click(); await page .getByRole( 'dialog' ) diff --git a/test/e2e/specs/editor/various/is-typing.spec.js b/test/e2e/specs/editor/various/is-typing.spec.js index 10ac90d1084127..da4492a89bef34 100644 --- a/test/e2e/specs/editor/various/is-typing.spec.js +++ b/test/e2e/specs/editor/various/is-typing.spec.js @@ -4,10 +4,18 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); test.describe( 'isTyping', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activatePlugin( 'gutenberg-test-observe-typing' ); + } ); + test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); } ); + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deactivatePlugin( 'gutenberg-test-observe-typing' ); + } ); + test( 'should hide the toolbar when typing', async ( { editor, page } ) => { // Enter to reach paragraph block. await page.keyboard.press( 'Enter' ); @@ -42,33 +50,23 @@ test.describe( 'isTyping', () => { page, } ) => { // Add a block with a dropdown in the toolbar that contains an input. - await editor.insertBlock( { name: 'core/query' } ); - - await editor.canvas - .getByRole( 'document', { name: 'Block: Query Loop' } ) - .getByRole( 'button', { name: 'Start blank' } ) - .click(); - - await editor.canvas - .getByRole( 'button', { name: 'Title & Date' } ) - .click(); - - await editor.openDocumentSettingsSidebar(); - await page.getByLabel( 'Custom' ).click(); + await editor.insertBlock( { name: 'e2e-tests/observe-typing' } ); // Moving the mouse shows the toolbar. await editor.showBlockToolbar(); // Open the dropdown. - const displaySettings = page.getByRole( 'button', { - name: 'Display settings', + await page + .getByRole( 'button', { + name: 'Open Dropdown', + } ) + .click(); + + const textControl = page.getByRole( 'textbox', { + name: 'Dropdown field', } ); - await displaySettings.click(); - const itemsPerPageInput = page.getByLabel( 'Items per Page' ); - // Make sure we're where we think we are - await expect( itemsPerPageInput ).toBeFocused(); // Type inside the dropdown's input - await page.keyboard.type( '00' ); + await textControl.pressSequentially( 'Hello' ); // The input should still be visible. - await expect( itemsPerPageInput ).toBeVisible(); + await expect( textControl ).toBeVisible(); } ); } );