From c35d6ff17feffb7bb508f843958dda5b3ace4b85 Mon Sep 17 00:00:00 2001 From: Chad Chadbourne <13856531+chad1008@users.noreply.github.com> Date: Wed, 14 Feb 2024 06:38:51 -0500 Subject: [PATCH 01/31] Tabs: Fix flaky unit tests (#58629) * waitFor controlled mode changes to finish rendering * add missing assertion * use `sleep()` to ensure rendering completion Co-authored-by: chad1008 Co-authored-by: ciampo Co-authored-by: tyxla Co-authored-by: diegohaz Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/src/tabs/test/index.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index ca9a01928e599c..75db47d69f9925 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor } from '@testing-library/react'; -import { press, click } from '@ariakit/test'; +import { press, click, sleep } from '@ariakit/test'; /** * WordPress dependencies @@ -1185,10 +1185,18 @@ describe( 'Tabs', () => { /> ); + // Due to the timing of the component re-rendering, we + // need to force a delay to ensure the test doesn't run + // the upcoming assertions too early. + // see https://github.com/WordPress/gutenberg/pull/58629#issuecomment-1924875249 + await sleep(); + // Tab key should focus the currently selected tab, which is Beta. await press.Tab(); - expect( await getSelectedTab() ).toHaveTextContent( - 'Beta' + await waitFor( async () => + expect( await getSelectedTab() ).toHaveTextContent( + 'Beta' + ) ); expect( await getSelectedTab() ).toHaveFocus(); @@ -1201,9 +1209,11 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, it should not automatically receive focus. + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( screen.getByRole( 'tab', { name: 'Beta' } ) ).toHaveFocus(); @@ -1247,9 +1257,11 @@ describe( 'Tabs', () => { ); // When the selected tab is changed, it should not automatically receive focus. + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( screen.getByRole( 'tab', { name: 'Beta' } ) ).toHaveFocus(); From ec329cdaa4896bd86fabfa8d8070e315a6dc39cb Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 14 Feb 2024 13:44:35 +0200 Subject: [PATCH 02/31] DataViews: Add loading/no results message in grid view (#59002) Co-authored-by: ntsekouras Co-authored-by: oandregal Co-authored-by: annezazu Co-authored-by: t-hamano --- packages/dataviews/src/view-grid.js | 64 ++++++++++++------- .../components/page-patterns/use-patterns.js | 18 ++++-- 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/packages/dataviews/src/view-grid.js b/packages/dataviews/src/view-grid.js index 14024163878d1d..44ab1822a60750 100644 --- a/packages/dataviews/src/view-grid.js +++ b/packages/dataviews/src/view-grid.js @@ -12,6 +12,7 @@ import { __experimentalVStack as VStack, Tooltip, } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; import { useAsyncList } from '@wordpress/compose'; import { useState } from '@wordpress/element'; @@ -128,6 +129,7 @@ export default function ViewGrid( { fields, view, actions, + isLoading, getItemId, deferredRendering, selection, @@ -148,29 +150,45 @@ export default function ViewGrid( { ); const shownData = useAsyncList( data, { step: 3 } ); const usedData = deferredRendering ? shownData : data; + const hasData = !! usedData?.length; return ( - - { usedData.map( ( item ) => { - return ( - - ); - } ) } - + <> + { hasData && ( + + { usedData.map( ( item ) => { + return ( + + ); + } ) } + + ) } + { ! hasData && ( +
+

{ isLoading ? __( 'Loading…' ) : __( 'No results' ) }

+
+ ) } + ); } diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index a0b82247c85a6d..b099b70b36fe1a 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -111,6 +111,7 @@ const selectTemplatePartsAsPatterns = createSelector( const selectThemePatterns = createSelector( ( select ) => { const { getSettings } = unlock( select( editSiteStore ) ); + const { getIsResolving } = select( coreStore ); const settings = getSettings(); const blockPatterns = settings.__experimentalAdditionalBlockPatterns ?? @@ -136,19 +137,23 @@ const selectThemePatterns = createSelector( __unstableSkipMigrationLogs: true, } ), } ) ); - - return { patterns, isResolving: false }; + return { patterns, isResolving: getIsResolving( 'getBlockPatterns' ) }; }, ( select ) => [ select( coreStore ).getBlockPatterns(), + select( coreStore ).getIsResolving( 'getBlockPatterns' ), unlock( select( editSiteStore ) ).getSettings(), ] ); const selectPatterns = createSelector( ( select, categoryId, syncStatus, search = '' ) => { - const { patterns: themePatterns } = selectThemePatterns( select ); - const { patterns: userPatterns } = selectUserPatterns( select ); + const { + patterns: themePatterns, + isResolving: isResolvingThemePatterns, + } = selectThemePatterns( select ); + const { patterns: userPatterns, isResolving: isResolvingUserPatterns } = + selectUserPatterns( select ); let patterns = [ ...( themePatterns || [] ), @@ -176,7 +181,10 @@ const selectPatterns = createSelector( hasCategory: ( item ) => ! item.hasOwnProperty( 'categories' ), } ); } - return { patterns, isResolving: false }; + return { + patterns, + isResolving: isResolvingThemePatterns || isResolvingUserPatterns, + }; }, ( select ) => [ selectThemePatterns( select ), From 857356c1602a42f342a61976ba67eb41284050ca Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 14 Feb 2024 04:45:21 -0700 Subject: [PATCH 03/31] Revert #55219 fix/block-settings-origins (#58951) Co-authored-by: ajlende Co-authored-by: youknowriad Co-authored-by: t-hamano Co-authored-by: MaggieCabrera Co-authored-by: getdave Co-authored-by: scruffian Co-authored-by: andrewserong Co-authored-by: matiasbenedetto Co-authored-by: carolinan Co-authored-by: justintadlock Co-authored-by: annezazu Co-authored-by: widoz Co-authored-by: colorful-tones Co-authored-by: iamtakashi Co-authored-by: juanfra Co-authored-by: hanneslsm Co-authored-by: richtabor --- .../components/global-styles/border-panel.js | 10 +++--- .../global-styles/typography-panel.js | 18 +++++++---- packages/block-editor/src/hooks/utils.js | 32 ++++++++++++++----- .../src/store/get-block-settings.js | 19 ++++++++--- packages/blocks/src/api/constants.js | 6 ++-- packages/blocks/src/api/index.js | 2 +- 6 files changed, 60 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/border-panel.js b/packages/block-editor/src/components/global-styles/border-panel.js index 0dee6040c87052..960c19289157a3 100644 --- a/packages/block-editor/src/components/global-styles/border-panel.js +++ b/packages/block-editor/src/components/global-styles/border-panel.js @@ -19,7 +19,7 @@ import { __ } from '@wordpress/i18n'; import BorderRadiusControl from '../border-radius-control'; import { useColorsPerOrigin } from './hooks'; import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils'; -import { mergeOrigins } from '../../store/get-block-settings'; +import { overrideOrigins } from '../../store/get-block-settings'; import { setImmutably } from '../../utils/object'; import { getBorderPanelLabel } from '../../hooks/border'; import { ShadowPopover } from './shadow-panel-components'; @@ -154,12 +154,12 @@ export default function BorderPanel( { // Shadow const shadow = decodeValue( inheritedValue?.shadow ); - const shadowPresets = settings?.shadow?.presets; - const mergedShadowPresets = shadowPresets - ? mergeOrigins( shadowPresets ) + const shadowPresets = settings?.shadow?.presets ?? {}; + const overriddenShadowPresets = shadowPresets + ? overrideOrigins( shadowPresets ) : []; const setShadow = ( newValue ) => { - const slug = mergedShadowPresets?.find( + const slug = overriddenShadowPresets?.find( ( { shadow: shadowName } ) => shadowName === newValue )?.slug; diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index e689d84c83c981..6b09b146f9ea17 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -13,7 +13,11 @@ import { useCallback } from '@wordpress/element'; /** * Internal dependencies */ -import { mergeOrigins, hasMergedOrigins } from '../../store/get-block-settings'; +import { + mergeOrigins, + overrideOrigins, + hasOriginValue, +} from '../../store/get-block-settings'; import FontFamilyControl from '../font-family'; import FontAppearanceControl from '../font-appearance-control'; import LineHeightControl from '../line-height-control'; @@ -53,13 +57,13 @@ export function useHasTypographyPanel( settings ) { function useHasFontSizeControl( settings ) { return ( - hasMergedOrigins( settings?.typography?.fontSizes ) || + hasOriginValue( settings?.typography?.fontSizes ) || settings?.typography?.customFontSize ); } function useHasFontFamilyControl( settings ) { - return hasMergedOrigins( settings?.typography?.fontFamilies ); + return hasOriginValue( settings?.typography?.fontFamilies ); } function useHasLineHeightControl( settings ) { @@ -101,10 +105,10 @@ function useHasTextColumnsControl( settings ) { } function getUniqueFontSizesBySlug( settings ) { - const fontSizes = settings?.typography?.fontSizes; - const mergedFontSizes = fontSizes ? mergeOrigins( fontSizes ) : []; + const fontSizes = settings?.typography?.fontSizes ?? {}; + const overriddenFontSizes = fontSizes ? overrideOrigins( fontSizes ) : []; const uniqueSizes = []; - for ( const currentSize of mergedFontSizes ) { + for ( const currentSize of overriddenFontSizes ) { if ( ! uniqueSizes.some( ( { slug } ) => slug === currentSize.slug ) ) { uniqueSizes.push( currentSize ); } @@ -162,7 +166,7 @@ export default function TypographyPanel( { // Font Family const hasFontFamilyEnabled = useHasFontFamilyControl( settings ); - const fontFamilies = settings?.typography?.fontFamilies; + const fontFamilies = settings?.typography?.fontFamilies ?? {}; const mergedFontFamilies = fontFamilies ? mergeOrigins( fontFamilies ) : []; const fontFamily = decodeValue( inheritedValue?.typography?.fontFamily ); const setFontFamily = ( newValue ) => { diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 2f7a8f3a81f19d..fbe84514c3e53c 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -176,8 +176,12 @@ export function useBlockSettings( name, parentLayout ) { const [ backgroundImage, backgroundSize, - fontFamilies, - fontSizes, + customFontFamilies, + defaultFontFamilies, + themeFontFamilies, + customFontSizes, + defaultFontSizes, + themeFontSizes, customFontSize, fontStyle, fontWeight, @@ -223,8 +227,12 @@ export function useBlockSettings( name, parentLayout ) { ] = useSettings( 'background.backgroundImage', 'background.backgroundSize', - 'typography.fontFamilies', - 'typography.fontSizes', + 'typography.fontFamilies.custom', + 'typography.fontFamilies.default', + 'typography.fontFamilies.theme', + 'typography.fontSizes.custom', + 'typography.fontSizes.default', + 'typography.fontSizes.theme', 'typography.customFontSize', 'typography.fontStyle', 'typography.fontWeight', @@ -305,10 +313,14 @@ export function useBlockSettings( name, parentLayout ) { }, typography: { fontFamilies: { - custom: fontFamilies, + custom: customFontFamilies, + default: defaultFontFamilies, + theme: themeFontFamilies, }, fontSizes: { - custom: fontSizes, + custom: customFontSizes, + default: defaultFontSizes, + theme: themeFontSizes, }, customFontSize, fontStyle, @@ -346,8 +358,12 @@ export function useBlockSettings( name, parentLayout ) { }, [ backgroundImage, backgroundSize, - fontFamilies, - fontSizes, + customFontFamilies, + defaultFontFamilies, + themeFontFamilies, + customFontSizes, + defaultFontSizes, + themeFontSizes, customFontSize, fontStyle, fontWeight, diff --git a/packages/block-editor/src/store/get-block-settings.js b/packages/block-editor/src/store/get-block-settings.js index 598754a3497184..1bffebf931e818 100644 --- a/packages/block-editor/src/store/get-block-settings.js +++ b/packages/block-editor/src/store/get-block-settings.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { - __EXPERIMENTAL_PATHS_WITH_MERGE as PATHS_WITH_MERGE, + __EXPERIMENTAL_PATHS_WITH_OVERRIDE as PATHS_WITH_OVERRIDE, hasBlockSupport, } from '@wordpress/blocks'; import { applyFilters } from '@wordpress/hooks'; @@ -111,6 +111,17 @@ export function mergeOrigins( value ) { } const mergeCache = new WeakMap(); +/** + * For settings like `color.palette`, which have a value that is an object + * with `default`, `theme`, `custom`, with field values that are arrays of + * items, returns the one with the highest priority among these three arrays. + * @param {Object} value Object to extract from + * @return {Array} Array of items extracted from the three origins + */ +export function overrideOrigins( value ) { + return value.custom ?? value.theme ?? value.default; +} + /** * For settings like `color.palette`, which have a value that is an object * with `default`, `theme`, `custom`, with field values that are arrays of @@ -119,7 +130,7 @@ const mergeCache = new WeakMap(); * @param {Object} value Object to check * @return {boolean} Whether the object has values in any of the three origins */ -export function hasMergedOrigins( value ) { +export function hasOriginValue( value ) { return [ 'default', 'theme', 'custom' ].some( ( key ) => value?.[ key ]?.length ); @@ -203,8 +214,8 @@ export function getBlockSettings( state, clientId, ...paths ) { // Return if the setting was found in either the block instance or the store. if ( result !== undefined ) { - if ( PATHS_WITH_MERGE[ normalizedPath ] ) { - return mergeOrigins( result ); + if ( PATHS_WITH_OVERRIDE[ normalizedPath ] ) { + return overrideOrigins( result ); } return result; } diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 8af2d0940c8fcc..99de83353166c7 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -271,11 +271,13 @@ export const __EXPERIMENTAL_ELEMENTS = { cite: 'cite', }; -export const __EXPERIMENTAL_PATHS_WITH_MERGE = { +// These paths may have three origins, custom, theme, and default, +// and are expected to override other origins with custom, theme, +// and default priority. +export const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = { 'color.duotone': true, 'color.gradients': true, 'color.palette': true, - 'typography.fontFamilies': true, 'typography.fontSizes': true, 'spacing.spacingSizes': true, }; diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index 2ddeb3a60f0abb..aa72979818c9c7 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -162,5 +162,5 @@ export { default as node } from './node'; export { __EXPERIMENTAL_STYLE_PROPERTY, __EXPERIMENTAL_ELEMENTS, - __EXPERIMENTAL_PATHS_WITH_MERGE, + __EXPERIMENTAL_PATHS_WITH_OVERRIDE, } from './constants'; From 21e01677fe21acd9ea9baa8c850a8784e717e15b Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 14 Feb 2024 15:53:34 +0400 Subject: [PATCH 04/31] Site Editor: Don't memoize the canvas container title (#59000) Co-authored-by: Mamaduka Co-authored-by: tyxla --- .../src/components/editor-canvas-container/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index a6dc8b05409e22..09ae95989695d8 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { Children, cloneElement, useState, useMemo } from '@wordpress/element'; +import { Children, cloneElement, useState } from '@wordpress/element'; import { Button, privateApis as componentsPrivateApis, @@ -82,10 +82,6 @@ function EditorCanvasContainer( { const focusOnMountRef = useFocusOnMount( 'firstElement' ); const sectionFocusReturnRef = useFocusReturn(); - const title = useMemo( - () => getEditorCanvasContainerTitle( editorCanvasContainerView ), - [ editorCanvasContainerView ] - ); function onCloseContainer() { setIsListViewOpened( showListViewByDefault ); @@ -119,6 +115,7 @@ function EditorCanvasContainer( { return null; } + const title = getEditorCanvasContainerTitle( editorCanvasContainerView ); const shouldShowCloseButton = onClose || closeButtonLabel; return ( From 99c7e35f4257af7fa7b141d9d181dcc62442e05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 14 Feb 2024 12:54:16 +0100 Subject: [PATCH 05/31] DataViews: update docs (#58847) Co-authored-by: oandregal --- packages/dataviews/README.md | 267 ++++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 111 deletions(-) diff --git a/packages/dataviews/README.md b/packages/dataviews/README.md index e476546c514cef..bbc2271db6573c 100644 --- a/packages/dataviews/README.md +++ b/packages/dataviews/README.md @@ -12,85 +12,147 @@ npm install @wordpress/dataviews --save ## Usage -```js - item.id } - isLoading={ isLoadingData } - supportedLayouts={ [ 'table' ] } - deferredRendering={ true } - onSelectionChange={ ( items ) => { /* ... */ } } -/> +```jsx +const Example = () => { + + // Declare data, fields, etc. + + return ( + + ); +} ``` -## Data +## Properties + +### `data`: `Object[]` The dataset to work with, represented as a one-dimensional array. Example: ```js -[ - { id: 1, title: "Title", ... }, - { ... } +const data = [ + { + id: 1, + title: "Title", + author: "Admin", + date: "2012-04-23T18:25:43.511Z" + }, + { /* ... */ } ] ``` -By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one. See "Other props" section. +By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one. -## Pagination Info +### `fields`: `Object[]` -- `totalItems`: the total number of items in the datasets. -- `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user. +The fields describe the visible items for each record in the dataset. -## View +Example: + +```js +const fields = [ + { + id: 'title', + header: 'Title', + getValue: ({ item }) => item.title, + enableHiding: false, + }, + { + id: 'date', + header: 'Date', + getValue: ( { item } ) => item.date, + render: ( { item } ) => { + return ( + + ); + } + }, + { + id: 'author', + header: __( 'Author' ), + getValue: ( { item } ) => item.author, + render: ( { item } ) => { + return ( + { item.author } + ); + }, + type: 'enumeration', + elements: [ + { value: 1, label: 'Admin' } + { value: 2, label: 'User' } + ] + enableSorting: false + } +] +``` + +Each field is an object with the following properties: + +- `id`: identifier for the field. Unique. +- `header`: the field's name to be shown in the UI. +- `getValue`: function that returns the value of the field. +- `render`: function that renders the field. Optional, `getValue` will be used if `render` is not defined. +- `elements`: the set of valid values for the field's value. +- `type`: the type of the field. Used to generate the proper filters. Only `enumeration` available at the moment. See "Field types". +- `enableSorting`: whether the data can be sorted by the given field. True by default. +- `enableHiding`: whether the field can be hidden. True by default. +- `filterBy`: configuration for the filters. + - `operators`: the list of operators supported by the field. + - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. + +### `view`: `object` The view object configures how the dataset is visible to the user. Example: ```js -{ +const view = { type: 'table', - perPage: 5, - page: 1, - sort: { - field: 'date', - direction: 'desc', - }, search: '', filters: [ { field: 'author', operator: 'in', value: 2 }, { field: 'status', operator: 'in', value: 'publish,draft' } ], + page: 1, + perPage: 5, + sort: { + field: 'date', + direction: 'desc', + }, hiddenFields: [ 'date', 'featured-image' ], layout: {}, } ``` -- `type`: view type, one of `table`, `grid`, `list`. See "View types". -- `perPage`: number of records to show per page. -- `page`: the page that is visible. -- `sort.field`: field used for sorting the dataset. -- `sort.direction`: the direction to use for sorting, one of `asc` or `desc`. +Properties: + +- `type`: view type, one of `table`, `grid`, `list`. See "Layout types". - `search`: the text search applied to the dataset. - `filters`: the filters applied to the dataset. Each item describes: - `field`: which field this filter is bound to. - `operator`: which type of filter it is. One of `in`, `notIn`. See "Operator types". - `value`: the actual value selected by the user. +- `perPage`: number of records to show per page. +- `page`: the page that is visible. +- `sort`: + - `field`: the field used for sorting the dataset. + - `direction`: the direction to use for sorting, one of `asc` or `desc`. - `hiddenFields`: the `id` of the fields that are hidden in the UI. - `layout`: config that is specific to a particular layout type. - `mediaField`: used by the `grid` and `list` layouts. The `id` of the field to be used for rendering each card's media. - - `primaryField`: used by the `grid` and `list` layouts. The `id` of the field to be highlighted in each card/list item. + - `primaryField`: used by the `table`, `grid` and `list` layouts. The `id` of the field to be highlighted in each row/card/item. -### onChangeView: syncing view and data +### `onChangeView`: `function` The view is a representation of the visible state of the dataset: what type of layout is used to display it (table, grid, etc.), how the dataset is filtered, how it is sorted or paginated. @@ -147,65 +209,17 @@ function MyCustomPageTable() { data={ records } view={ view } onChangeView={ setView } - "..." + // ... /> ); } ``` -## Fields - -The fields describe the visible items for each record in the dataset. - -Example: - -```js -[ - { - id: 'date', - header: __( 'Date' ), - getValue: ( { item } ) => item.date, - render: ( { item } ) => { - return ( - - ); - }, - enableHiding: false - }, - { - id: 'author', - header: __( 'Author' ), - getValue: ( { item } ) => item.author, - render: ( { item } ) => { - return ( - { item.author } - ); - }, - type: 'enumeration', - elements: [ - { value: 1, label: 'Admin' } - { value: 2, label: 'User' } - ] - enableSorting: false - } -] -``` - -- `id`: identifier for the field. Unique. -- `header`: the field's name to be shown in the UI. -- `getValue`: function that returns the value of the field. -- `render`: function that renders the field. -- `elements`: the set of valid values for the field's value. -- `type`: the type of the field. Used to generate the proper filters. Only `enumeration` available at the moment. See "Field types". -- `enableSorting`: whether the data can be sorted by the given field. True by default. -- `enableHiding`: whether the field can be hidden. True by default. -- `filterBy`: configuration for the filters. - - `operators`: the list of operators supported by the field. - - `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter. +### `actions`: `Object[]` -## Actions +Collection of operations that can be performed upon each record. -Array of operations that can be performed upon each record. Each action is an object with the following properties: +Each action is an object with the following properties: - `id`: string, required. Unique identifier of the action. For example, `move-to-trash`. - `label`: string, required. User facing description of the action. For example, `Move to Trash`. @@ -217,28 +231,59 @@ Array of operations that can be performed upon each record. Each action is an ob - `RenderModal`: ReactElement, optional. If an action requires that some UI be rendered in a modal, it can provide a component which takes as props the record as `item` and a `closeModal` function. When this prop is provided, the `callback` property is ignored. - `hideModalHeader`: boolean, optional. This property is used in combination with `RenderModal` and controls the visibility of the modal's header. If the action renders a modal and doesn't hide the header, the action's label is going to be used in the modal's header. +### `paginationInfo`: `Object` + +- `totalItems`: the total number of items in the datasets. +- `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user. + +### `search`: `boolean` + +Whether the search input is enabled. `true` by default. + +### `searchLabel`: `string` + +What text to show in the search input. "Search" by default. + +### `getItemId`: `function` + +Function that receives an item and returns an unique identifier for it. By default, it uses the `id` of the item as unique identifier. If it's not, the consumer should provide their own. + +### `isLoading`: `boolean` + +Whether the data is loading. `false` by default. + +### `supportedLayouts`: `String[]` + +Array of layouts supported. By default, all are: `table`, `grid`, `list`. + +### `deferredRendering`: `boolean` + +Whether the items should be rendered asynchronously. Useful when there's a field that takes a lot of time (e.g.: previews). `false` by default. + +### `onSelectionChange`: `function` + +Callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. + +### `onDetailsChange`: `function` + +Callback that signals the user triggered the details for one of more items, and takes them as paremeter. So far, only the `list` view implements it. + ## Types -- Layout types: - - `table`: the view uses a table layout. - - `grid`: the view uses a grid layout. - - `list`: the view uses a list layout. -- Field types: - - `enumeration`: the field value should be taken and can be filtered from a closed list of elements. -- Operator types: - - `in`: operator to be used in filters for fields of type `enumeration`. - - `notIn`: operator to be used in filters for fields of type `enumeration`. - -## Other properties - -- `search`: whether the search input is enabled. `true` by default. -- `searchLabel`: what text to show in the search input. "Filter list" by default. -- `getItemId`: function that receives an item and returns an unique identifier for it. By default, it uses the `id` of the item as unique identifier. If it's not, the consumer should provide their own. -- `isLoading`: whether the data is loading. `false` by default. -- `supportedLayouts`: array of layouts supported. By default, all are: `table`, `grid`, `list`. -- `deferredRendering`: whether the items should be rendered asynchronously. Useful when there's a field that takes a lot of time (e.g.: previews). `false` by default. -- `onSelectionChange`: callback that signals the user selected one of more items, and takes them as parameter. So far, only the `list` view implements it. -- `onDetailsChange`: callback that signals the user triggered the details for one of more items, and takes them as paremeter. So far, only the `list` view implements it. +### Layouts + +- `table`: the view uses a table layout. +- `grid`: the view uses a grid layout. +- `list`: the view uses a list layout. + +### Fields + +- `enumeration`: the field value should be taken and can be filtered from a closed list of elements. + +### Operators + +- `in`: operator to be used in filters for fields of type `enumeration`. +- `notIn`: operator to be used in filters for fields of type `enumeration`. ## Contributing to this package From 6a7f83c58ae3411b04ca8bbeed06c1beebd76b90 Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:16:36 +0100 Subject: [PATCH 06/31] Block editor: pass patterns selector as setting (#58661) Co-authored-by: ellatrix Co-authored-by: jsnajdr Co-authored-by: Mamaduka --- packages/block-editor/src/private-apis.js | 2 ++ packages/block-editor/src/store/index.js | 2 -- .../block-editor/src/store/private-keys.js | 1 + .../src/store/private-selectors.js | 11 +++----- packages/block-editor/src/store/reducer.js | 10 ------- packages/block-editor/src/store/resolvers.js | 17 ------------ packages/block-editor/src/store/selectors.js | 12 ++++----- packages/block-editor/src/store/utils.js | 9 +++++-- packages/core-data/src/private-selectors.ts | 27 +++++++++++++++++++ .../provider/use-block-editor-settings.js | 18 +++++-------- 10 files changed, 53 insertions(+), 56 deletions(-) create mode 100644 packages/block-editor/src/store/private-keys.js delete mode 100644 packages/block-editor/src/store/resolvers.js diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 0ba05e88a0f9b1..220aa5f4127270 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -26,6 +26,7 @@ import { usesContextKey } from './components/rich-text/format-edit'; import { ExperimentalBlockCanvas } from './components/block-canvas'; import { getDuotoneFilter } from './components/duotone/utils'; import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; +import { selectBlockPatternsKey } from './store/private-keys'; /** * Private @wordpress/block-editor APIs. @@ -56,4 +57,5 @@ lock( privateApis, { useReusableBlocksRenameHint, usesContextKey, useFlashEditableBlocks, + selectBlockPatternsKey, } ); diff --git a/packages/block-editor/src/store/index.js b/packages/block-editor/src/store/index.js index 10e16a0779cd63..0bcc00cb5f6ae8 100644 --- a/packages/block-editor/src/store/index.js +++ b/packages/block-editor/src/store/index.js @@ -10,7 +10,6 @@ import reducer from './reducer'; import * as selectors from './selectors'; import * as privateActions from './private-actions'; import * as privateSelectors from './private-selectors'; -import * as resolvers from './resolvers'; import * as actions from './actions'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; @@ -23,7 +22,6 @@ import { unlock } from '../lock-unlock'; export const storeConfig = { reducer, selectors, - resolvers, actions, }; diff --git a/packages/block-editor/src/store/private-keys.js b/packages/block-editor/src/store/private-keys.js new file mode 100644 index 00000000000000..8bfa4bb68297f8 --- /dev/null +++ b/packages/block-editor/src/store/private-keys.js @@ -0,0 +1 @@ +export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' ); diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 4700e50f739f45..c885e43ba75208 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -22,6 +22,7 @@ import { checkAllowListRecursive, getAllPatternsDependants } from './utils'; import { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils'; import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; +import { selectBlockPatternsKey } from './private-keys'; export { getBlockSettings } from './get-block-settings'; @@ -250,10 +251,6 @@ export const getInserterMediaCategories = createSelector( ] ); -export function getFetchedPatterns( state ) { - return state.blockPatterns; -} - /** * Returns whether there is at least one allowed pattern for inner blocks children. * This is useful for deferring the parsing of all patterns until needed. @@ -285,7 +282,7 @@ export const hasAllowedPatterns = createRegistrySelector( ( select ) => } ); }, ( state, rootClientId ) => [ - getAllPatternsDependants( state ), + getAllPatternsDependants( select )( state ), state.settings.allowedBlockTypes, state.settings.templateLock, state.blockListSettings[ rootClientId ], @@ -325,12 +322,12 @@ export const getAllPatterns = createRegistrySelector( ( select ) => return [ ...userPatterns, ...__experimentalBlockPatterns, - ...unlock( select( STORE_NAME ) ).getFetchedPatterns(), + ...( state.settings[ selectBlockPatternsKey ]?.( select ) ?? [] ), ].filter( ( x, index, arr ) => index === arr.findIndex( ( y ) => x.name === y.name ) ); - }, getAllPatternsDependants ) + }, getAllPatternsDependants( select ) ) ); /** diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 0be421b757bce1..1b535e51950164 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -2064,15 +2064,6 @@ function blockBindingsSources( state = {}, action ) { return state; } -function blockPatterns( state = [], action ) { - switch ( action.type ) { - case 'RECEIVE_BLOCK_PATTERNS': - return action.patterns; - } - - return state; -} - const combinedReducers = combineReducers( { blocks, isDragging, @@ -2105,7 +2096,6 @@ const combinedReducers = combineReducers( { openedBlockSettingsMenu, registeredInserterMediaCategories, blockBindingsSources, - blockPatterns, } ); function withAutomaticChangeReset( reducer ) { diff --git a/packages/block-editor/src/store/resolvers.js b/packages/block-editor/src/store/resolvers.js deleted file mode 100644 index 40c51d241ac676..00000000000000 --- a/packages/block-editor/src/store/resolvers.js +++ /dev/null @@ -1,17 +0,0 @@ -export const getFetchedPatterns = - () => - async ( { dispatch, select } ) => { - const { __experimentalFetchBlockPatterns } = select.getSettings(); - if ( ! __experimentalFetchBlockPatterns ) { - return []; - } - const patterns = await __experimentalFetchBlockPatterns(); - dispatch( { type: 'RECEIVE_BLOCK_PATTERNS', patterns } ); - }; - -getFetchedPatterns.shouldInvalidate = ( action ) => { - return ( - action.type === 'UPDATE_SETTINGS' && - !! action.settings.__experimentalFetchBlockPatterns - ); -}; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3475e2b5351c80..87d22e3e4727d7 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2299,12 +2299,12 @@ export const __experimentalGetParsedPattern = createRegistrySelector( __unstableSkipMigrationLogs: true, } ), }; - }, getAllPatternsDependants ) + }, getAllPatternsDependants( select ) ) ); -const getAllowedPatternsDependants = ( state, rootClientId ) => { +const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => { return [ - ...getAllPatternsDependants( state ), + ...getAllPatternsDependants( select )( state ), state.settings.allowedBlockTypes, state.settings.templateLock, state.blockListSettings[ rootClientId ], @@ -2345,7 +2345,7 @@ export const __experimentalGetAllowedPatterns = createRegistrySelector( ); return patternsAllowed; - }, getAllowedPatternsDependants ); + }, getAllowedPatternsDependants( select ) ); } ); @@ -2384,7 +2384,7 @@ export const getPatternsByBlockTypes = createRegistrySelector( ( select ) => return filteredPatterns; }, ( state, blockNames, rootClientId ) => - getAllowedPatternsDependants( state, rootClientId ) + getAllowedPatternsDependants( select )( state, rootClientId ) ) ); @@ -2458,7 +2458,7 @@ export const __experimentalGetPatternTransformItems = createRegistrySelector( ); }, ( state, blocks, rootClientId ) => - getAllowedPatternsDependants( state, rootClientId ) + getAllowedPatternsDependants( select )( state, rootClientId ) ) ); diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index 6cde56da1b55a7..4d9d114946c1fd 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -1,3 +1,8 @@ +/** + * Internal dependencies + */ +import { selectBlockPatternsKey } from './private-keys'; + export const checkAllowList = ( list, item, defaultResult = null ) => { if ( typeof list === 'boolean' ) { return list; @@ -40,12 +45,12 @@ export const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => { return true; }; -export const getAllPatternsDependants = ( state ) => { +export const getAllPatternsDependants = ( select ) => ( state ) => { return [ state.settings.__experimentalBlockPatterns, state.settings.__experimentalUserPatternCategories, state.settings.__experimentalReusableBlocks, - state.settings.__experimentalFetchBlockPatterns, + state.settings[ selectBlockPatternsKey ]?.( select ), state.blockPatterns, ]; }; diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 94aa00e1c8de45..85dc4e3be7203c 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -1,7 +1,18 @@ +/** + * External dependencies + */ +import createSelector from 'rememo'; + +/** + * WordPress dependencies + */ +import { createRegistrySelector } from '@wordpress/data'; + /** * Internal dependencies */ import type { State } from './selectors'; +import { STORE_NAME } from './name'; type EntityRecordKey = string | number; @@ -28,3 +39,19 @@ export function getNavigationFallbackId( ): EntityRecordKey | undefined { return state.navigationFallbackId; } + +export const getBlockPatternsForPostType = createRegistrySelector( + ( select: any ) => + createSelector( + ( state, postType ) => + select( STORE_NAME ) + .getBlockPatterns() + .filter( + ( { postTypes } ) => + ! postTypes || + ( Array.isArray( postTypes ) && + postTypes.includes( postType ) ) + ), + () => [ select( STORE_NAME ).getBlockPatterns() ] + ) +); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 577ec977ecb947..c7540645328f7c 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -7,12 +7,12 @@ import { store as coreStore, __experimentalFetchLinkSuggestions as fetchLinkSuggestions, __experimentalFetchUrlData as fetchUrlData, - fetchBlockPatterns, } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; import { useViewportMatch } from '@wordpress/compose'; import { store as blocksStore } from '@wordpress/blocks'; +import { privateApis } from '@wordpress/block-editor'; /** * Internal dependencies @@ -20,6 +20,7 @@ import { store as blocksStore } from '@wordpress/blocks'; import inserterMediaCategories from '../media-categories'; import { mediaUpload } from '../../utils'; import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; const EMPTY_BLOCKS_LIST = []; @@ -244,17 +245,10 @@ function useBlockEditorSettings( settings, postType, postId ) { keepCaretInsideBlock, mediaUpload: hasUploadPermissions ? mediaUpload : undefined, __experimentalBlockPatterns: blockPatterns, - __experimentalFetchBlockPatterns: async () => { - return ( await fetchBlockPatterns() ).filter( - ( { postTypes } ) => { - return ( - ! postTypes || - ( Array.isArray( postTypes ) && - postTypes.includes( postType ) ) - ); - } - ); - }, + [ unlock( privateApis ).selectBlockPatternsKey ]: ( select ) => + unlock( select( coreStore ) ).getBlockPatternsForPostType( + postType + ), __experimentalReusableBlocks: reusableBlocks, __experimentalBlockPatternCategories: blockPatternCategories, __experimentalUserPatternCategories: userPatternCategories, From 61aa8f5785ee5374fbc9d7f5adc2b6d5be1336ef Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Wed, 14 Feb 2024 14:23:24 +0200 Subject: [PATCH 07/31] Components: Try fixing some flaky `Composite` and `Tabs` tests (#58968) * Components: Try fixing some flaky Composite and Tabs tests * Add extra sleep() to make less flaky Co-authored-by: tyxla Co-authored-by: mirka <0mirka00@git.wordpress.org> --- packages/components/src/composite/legacy/test/index.tsx | 5 +++-- packages/components/src/tabs/test/index.tsx | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index ee6654f9fd3698..49b1915a6a14fb 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { queryByAttribute, render, screen } from '@testing-library/react'; -import { press, waitFor } from '@ariakit/test'; +import { press, sleep, waitFor } from '@ariakit/test'; /** * Internal dependencies @@ -274,8 +274,9 @@ describe.each( [ renderAndValidate( ); const { item2 } = getOneDimensionalItems(); + await sleep(); await press.Tab(); - expect( item2 ).toHaveFocus(); + await waitFor( () => expect( item2 ).toHaveFocus() ); } ); } ); diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 75db47d69f9925..7262a53702c31d 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -1319,10 +1319,13 @@ describe( 'Tabs', () => { expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); // Tab key should focus the currently selected tab, which is Beta. + await sleep(); await press.Tab(); - expect( - await screen.findByRole( 'tab', { name: 'Beta' } ) - ).toHaveFocus(); + await waitFor( async () => + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus() + ); // Arrow key should move focus but not automatically change the selected tab. await press.ArrowRight(); From abdde7a6c5ce7f58e3c924b6d3e3ca25005ccd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:33:59 +0100 Subject: [PATCH 08/31] DataViews: fix storybook (#58842) --- packages/dataviews/src/stories/index.story.js | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/dataviews/src/stories/index.story.js b/packages/dataviews/src/stories/index.story.js index e0bea0c92c2b21..e7fbfbbe554b01 100644 --- a/packages/dataviews/src/stories/index.story.js +++ b/packages/dataviews/src/stories/index.story.js @@ -6,9 +6,9 @@ import { useState, useMemo, useCallback } from '@wordpress/element'; /** * Internal dependencies */ -import { DataViews, LAYOUT_GRID, LAYOUT_TABLE } from '../index'; - +import { DataViews } from '../index'; import { DEFAULT_VIEW, actions, data } from './fixtures'; +import { LAYOUT_GRID, LAYOUT_TABLE } from '../constants'; const meta = { title: 'DataViews (Experimental)/DataViews', @@ -17,7 +17,9 @@ const meta = { export default meta; const defaultConfigPerViewType = { - [ LAYOUT_TABLE ]: {}, + [ LAYOUT_TABLE ]: { + primaryField: 'title', + }, [ LAYOUT_GRID ]: { mediaField: 'image', primaryField: 'title', @@ -100,23 +102,19 @@ export const Default = ( props ) => { }; }, [ view ] ); const onChangeView = useCallback( - ( viewUpdater ) => { - let updatedView = - typeof viewUpdater === 'function' - ? viewUpdater( view ) - : viewUpdater; - if ( updatedView.type !== view.type ) { - updatedView = { - ...updatedView, + ( newView ) => { + if ( newView.type !== view.type ) { + newView = { + ...newView, layout: { - ...defaultConfigPerViewType[ updatedView.type ], + ...defaultConfigPerViewType[ newView.type ], }, }; } - setView( updatedView ); + setView( newView ); }, - [ view, setView ] + [ view.type, setView ] ); return ( { }; Default.args = { actions, - getItemId: ( item ) => item.id, - isLoading: false, supportedLayouts: [ LAYOUT_TABLE, LAYOUT_GRID ], }; From a1719b779cdb7e4accbd45c96406fb5caf8e5560 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 14 Feb 2024 15:06:09 +0000 Subject: [PATCH 09/31] Bump plugin version to 17.7.0 --- gutenberg.php | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gutenberg.php b/gutenberg.php index b86c9381c1a323..c9edbb32024c8c 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.3 * Requires PHP: 7.0 - * Version: 17.7.0-rc.1 + * Version: 17.7.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index 15002da92150ff..d2f56e9fc60c72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "17.7.0-rc.1", + "version": "17.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "17.7.0-rc.1", + "version": "17.7.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 190173d15ccadb..d662caeb1f2bb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "17.7.0-rc.1", + "version": "17.7.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", From 7acb269d6b68ce75e79052820134515362dd5817 Mon Sep 17 00:00:00 2001 From: Gutenberg Repository Automation Date: Wed, 14 Feb 2024 15:35:19 +0000 Subject: [PATCH 10/31] Update Changelog for 17.7.0 --- changelog.txt | 604 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 604 insertions(+) diff --git a/changelog.txt b/changelog.txt index c11c4246a60bdb..9505059dd3b706 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,609 @@ == Changelog == += 17.7.0 = + +## Changelog + + +### Enhancements + +- Improve translators comments for wp.date.setSettings in compat file. ([58488](https://github.com/WordPress/gutenberg/pull/58488)) +- Interactive Template: Use viewScriptModule. ([58211](https://github.com/WordPress/gutenberg/pull/58211)) + +#### Components + +- Adding `constrainTabbing` prop to `useDialog` hook. ([57962](https://github.com/WordPress/gutenberg/pull/57962)) +- Allow limiting the number of maximum visible Snackbars. ([58559](https://github.com/WordPress/gutenberg/pull/58559)) +- ConfirmDialog: Add `__next40pxDefaultSize` to buttons. ([58421](https://github.com/WordPress/gutenberg/pull/58421)) +- Expand theming support in COLORS. ([58097](https://github.com/WordPress/gutenberg/pull/58097)) +- FocalPointPicker: Apply modern styling. ([58459](https://github.com/WordPress/gutenberg/pull/58459)) +- Implement Tabs in widget editor settings. ([57886](https://github.com/WordPress/gutenberg/pull/57886)) +- Implement `Tabs` in site-editor settings. ([56959](https://github.com/WordPress/gutenberg/pull/56959)) +- Implementing `useCompositeState` with Ariakit. ([57304](https://github.com/WordPress/gutenberg/pull/57304)) +- InputBase: Add `isBorderless` prop. ([58750](https://github.com/WordPress/gutenberg/pull/58750)) +- Replace `TabPanel` with `Tabs` in the editor Document Overview sidebar. ([57082](https://github.com/WordPress/gutenberg/pull/57082)) +- SearchControl: Refactor to use InputControl internally. ([56524](https://github.com/WordPress/gutenberg/pull/56524)) +- Show borders for disabled secondary buttons. ([58606](https://github.com/WordPress/gutenberg/pull/58606)) + +#### Data Views + +- Add outline to template preview in table layout. ([58738](https://github.com/WordPress/gutenberg/pull/58738)) +- Add: Delete bulk action to patterns. ([58747](https://github.com/WordPress/gutenberg/pull/58747)) +- Add: Selection and bulk actions to grid view. ([58144](https://github.com/WordPress/gutenberg/pull/58144)) +- DataViews: Add primary filter API. ([58427](https://github.com/WordPress/gutenberg/pull/58427)) +- DataViews: In patterns page, show sync status filter by default. ([58367](https://github.com/WordPress/gutenberg/pull/58367)) +- DataViews: Redesign of filters. ([58569](https://github.com/WordPress/gutenberg/pull/58569)) +- Remove min-width style on table cells. ([58204](https://github.com/WordPress/gutenberg/pull/58204)) +- Update 'Rows per page' view option label to account for Grid layout. ([58457](https://github.com/WordPress/gutenberg/pull/58457)) +- Update dataviews search input placeholder. ([58742](https://github.com/WordPress/gutenberg/pull/58742)) +- Update spacing around title in grid layout. ([58739](https://github.com/WordPress/gutenberg/pull/58739)) + +#### Interactivity API + +- Add `block supports` for `clientNavigation` and `interactive` properties on `block.json` schema. ([58132](https://github.com/WordPress/gutenberg/pull/58132)) +- Image block: Refactor and remove `data-wp-body`. ([58835](https://github.com/WordPress/gutenberg/pull/58835)) +- Interactivity Router: Fix initial page cache. ([58496](https://github.com/WordPress/gutenberg/pull/58496)) +- Interactivity Router: Move ARIA live region and loading bar to the Interactivity Router. ([58377](https://github.com/WordPress/gutenberg/pull/58377)) +- Limit the exported APIs. ([58864](https://github.com/WordPress/gutenberg/pull/58864)) +- Mark all core block stores as private. ([58722](https://github.com/WordPress/gutenberg/pull/58722)) +- Server Directive Processor for `data-wp-each`. ([58498](https://github.com/WordPress/gutenberg/pull/58498)) +- Support setting a namespace using a string in `data-wp-interactive`. ([58743](https://github.com/WordPress/gutenberg/pull/58743)) +- Allow global configs for namespaces. ([58749](https://github.com/WordPress/gutenberg/pull/58749)) + +#### Block Library + +- Follow up on the Post navigation link taxonomy filters. ([57949](https://github.com/WordPress/gutenberg/pull/57949)) +- Home Link: Render Home text if there is no attribute label present. ([58387](https://github.com/WordPress/gutenberg/pull/58387)) +- Organize gallery controls. ([58407](https://github.com/WordPress/gutenberg/pull/58407)) +- Pattern: Use the '__experimentalLabel' method to get a title. ([58646](https://github.com/WordPress/gutenberg/pull/58646)) +- Social Icons: Update Patreon icon. ([56951](https://github.com/WordPress/gutenberg/pull/56951)) +- Try: Disable text selection for post content placeholder block. ([58169](https://github.com/WordPress/gutenberg/pull/58169)) +- Update pattern block copy in light of pattern overrides. ([58231](https://github.com/WordPress/gutenberg/pull/58231)) +- Add shadow support for column, columns and image. ([57982](https://github.com/WordPress/gutenberg/pull/57982)) + +#### Global Styles + +- Add style engine support for nested at-rules. ([58867](https://github.com/WordPress/gutenberg/pull/58867)) +- Move Shadow controls to Border panel. ([58466](https://github.com/WordPress/gutenberg/pull/58466)) +- Shadow: Update shadow support to allow explicit skipping of serialization. ([58306](https://github.com/WordPress/gutenberg/pull/58306)) +- Try: Remove shadow preset overflow. ([58663](https://github.com/WordPress/gutenberg/pull/58663)) +- Update return values from getGlobalStylesChanges(). ([58707](https://github.com/WordPress/gutenberg/pull/58707)) +- Add support for transform and letter spacing controls in Global Styles > Typography > Elements. ([58142](https://github.com/WordPress/gutenberg/pull/58142)) + +#### Block Editor + +- Drag and drop: Allow dragging from inserter or desktop to template parts. ([58589](https://github.com/WordPress/gutenberg/pull/58589)) +- Drag and drop: Allow dropping within template parts. ([58423](https://github.com/WordPress/gutenberg/pull/58423)) +- Implement "Add block" UI for Nav block Link UI. ([57756](https://github.com/WordPress/gutenberg/pull/57756)) +- Implementing new UX for invoking rich text Link UI. ([57986](https://github.com/WordPress/gutenberg/pull/57986)) +- Remove open in new tab from link preview. ([58744](https://github.com/WordPress/gutenberg/pull/58744)) +- Use consistent labels, remove additional settings, and copySmall icon LinkControl. ([58183](https://github.com/WordPress/gutenberg/pull/58183)) + +#### Site Editor + +- Apply 40px across summary panel. ([58730](https://github.com/WordPress/gutenberg/pull/58730)) +- Apply custom scroll style to fixed header block toolbar. ([57444](https://github.com/WordPress/gutenberg/pull/57444)) +- Improve SiteIcon display and transition. ([58472](https://github.com/WordPress/gutenberg/pull/58472)) +- Only show 'Back' button when user came from an editor canvas. ([58710](https://github.com/WordPress/gutenberg/pull/58710)) +- Update "focus mode" to consistently use the Document Bar's Back button. ([58528](https://github.com/WordPress/gutenberg/pull/58528)) + +#### Patterns + +- Add a confirmation dialog when a user tries to delete a synced pattern with overrides. ([58796](https://github.com/WordPress/gutenberg/pull/58796)) +- Add the block name to the pattern content data. ([58715](https://github.com/WordPress/gutenberg/pull/58715)) +- Flash editable block outlines instead of always showing them. ([58159](https://github.com/WordPress/gutenberg/pull/58159)) + +#### Design Tools + +- Background image support: Add background position controls. ([58592](https://github.com/WordPress/gutenberg/pull/58592)) +- Tweak metrics and labels for background size controls. ([58854](https://github.com/WordPress/gutenberg/pull/58854)) + +#### Post Editor + +- Editor: Limit visible Snackbars from the consumers. ([58598](https://github.com/WordPress/gutenberg/pull/58598)) +- Save entities panel: Update styles. ([58706](https://github.com/WordPress/gutenberg/pull/58706)) + +#### Font Library + +- Add sanitize from schema util. ([58571](https://github.com/WordPress/gutenberg/pull/58571)) +- Font Collections: Update registration function signature and add caching. ([58363](https://github.com/WordPress/gutenberg/pull/58363)) +- Font Library: Show 'Add fonts' button when there are no fonts installed. ([58580](https://github.com/WordPress/gutenberg/pull/58580)) + +#### Inspector Controls + +- Tweak FocalPointPicker inspector controls. ([58448](https://github.com/WordPress/gutenberg/pull/58448)) +- Tweak Media & Text inspector controls. ([58447](https://github.com/WordPress/gutenberg/pull/58447)) + +#### Custom Fields + +- Block Bindings: Ensure to pass bound attributes. ([58844](https://github.com/WordPress/gutenberg/pull/58844)) + +#### Commands + +- Try debouncing search for post-type navigation. ([58810](https://github.com/WordPress/gutenberg/pull/58810)) + +#### Document Settings + +- Tweak revisions panel for improved scanning. ([58751](https://github.com/WordPress/gutenberg/pull/58751)) + +#### Synced Patterns + +- Support button's link settings for Pattern Overrides. ([58587](https://github.com/WordPress/gutenberg/pull/58587)) + +#### Block API + +- Block Hooks: Set ignoredHookedBlocks metada attr upon insertion. ([58553](https://github.com/WordPress/gutenberg/pull/58553)) + +#### List View + +- Add keyboard clipboard events for cut, copy, paste. ([57838](https://github.com/WordPress/gutenberg/pull/57838)) + + +### New APIs + +#### Block API + +- Blocks: Add handling for block.json viewScriptModule. ([58731](https://github.com/WordPress/gutenberg/pull/58731)) + + +### Bug Fixes + +- Core data: useEntityBlockEditor: Fix parsed blocks cache. ([58841](https://github.com/WordPress/gutenberg/pull/58841)) +- Footnotes: Fix anchor order replacing. ([58791](https://github.com/WordPress/gutenberg/pull/58791)) + +#### Block Editor + +- Block Switcher: Use consistent labels. ([58240](https://github.com/WordPress/gutenberg/pull/58240)) +- Don't move focus within the toolbar if it is already focused. ([58570](https://github.com/WordPress/gutenberg/pull/58570)) +- Don't show Link preview when no selection. ([58771](https://github.com/WordPress/gutenberg/pull/58771)) +- Fix Link UI popover anchor in rich text. ([58282](https://github.com/WordPress/gutenberg/pull/58282)) +- Fix empty link preview after creating link from empty selection. ([58863](https://github.com/WordPress/gutenberg/pull/58863)) +- Hide the 'Content' panel for locked blocks when there's no content. ([58259](https://github.com/WordPress/gutenberg/pull/58259)) +- ImageURLInputUI: Fix focus loss when settings are changed. ([58647](https://github.com/WordPress/gutenberg/pull/58647)) +- Link UI: Polish lightbox pieces. ([58666](https://github.com/WordPress/gutenberg/pull/58666)) +- Media Replace Flow: Vertically align the URL. ([58621](https://github.com/WordPress/gutenberg/pull/58621)) +- MediaReplaceFlow: Restore popover width. ([58597](https://github.com/WordPress/gutenberg/pull/58597)) +- Rich Text: Only apply focus to elements, not selection. ([58745](https://github.com/WordPress/gutenberg/pull/58745)) +- Rich text: Preserve white space should strip \r. ([58805](https://github.com/WordPress/gutenberg/pull/58805)) +- Settings may be undefined. ([58658](https://github.com/WordPress/gutenberg/pull/58658)) +- useOnBlockDrop: Fix the Gallery block check. ([58711](https://github.com/WordPress/gutenberg/pull/58711)) + +#### Components + +- Add a timezone offset value for display purposes. ([56682](https://github.com/WordPress/gutenberg/pull/56682)) +- Fix Placeholder component padding when body text font size is changed. ([58323](https://github.com/WordPress/gutenberg/pull/58323)) +- Fix URLPopover preview overflow. ([58741](https://github.com/WordPress/gutenberg/pull/58741)) +- Fix the Snackbar auto-dismissal timers. ([58604](https://github.com/WordPress/gutenberg/pull/58604)) +- Popover: Add `box-sizing` reset style. ([58871](https://github.com/WordPress/gutenberg/pull/58871)) +- Set post editor sidebar tabs to manual activation. ([58041](https://github.com/WordPress/gutenberg/pull/58041)) +- Tabs: Delay `activeId` updates until focus can be properly detected. ([58625](https://github.com/WordPress/gutenberg/pull/58625)) +- Tabs: Fix infinite loop in useEffect. ([58861](https://github.com/WordPress/gutenberg/pull/58861)) +- Tabs: Improve Controlled Mode Focus Handling. ([57696](https://github.com/WordPress/gutenberg/pull/57696)) +- Try: Fix lightbox URL popover position. ([58600](https://github.com/WordPress/gutenberg/pull/58600)) + +#### Block Library + +- Fix [#54352](https://github.com/WordPress/gutenberg/issues/54352) prevents php 8.1 fatal when template parts are not found in non-debug environments. ([54354](https://github.com/WordPress/gutenberg/pull/54354)) +- Fix Query pagination not working in template parts and patterns. ([58602](https://github.com/WordPress/gutenberg/pull/58602)) +- Fix URL escaping for array parameters in Navigation links. ([58068](https://github.com/WordPress/gutenberg/pull/58068)) +- Fix missing data in email submissions. ([55691](https://github.com/WordPress/gutenberg/pull/55691)) +- Fix: Removing footnotes from the allowed blocks does not remove footnotes. ([58855](https://github.com/WordPress/gutenberg/pull/58855)) +- Navigation Link: Use get_block_type_variations to register variations. ([58389](https://github.com/WordPress/gutenberg/pull/58389)) +- Prevent usage of `gutenberg_url` in block-library. ([58242](https://github.com/WordPress/gutenberg/pull/58242)) +- Template Part: Reflect name updates without saving changes. ([58644](https://github.com/WordPress/gutenberg/pull/58644)) +- Try: Make gallery randomization work when nested. ([58733](https://github.com/WordPress/gutenberg/pull/58733)) + +#### Data Views + +- DataViews: Fix applied default layout props. ([58400](https://github.com/WordPress/gutenberg/pull/58400)) +- DataViews: Fix nested buttons and placeholder text in list layout. ([58304](https://github.com/WordPress/gutenberg/pull/58304)) +- DataViews: Fix some small issues with featured image. ([58371](https://github.com/WordPress/gutenberg/pull/58371)) +- DataViews: Make it possible to toggle Author field in templates and template parts. ([58609](https://github.com/WordPress/gutenberg/pull/58609)) +- DataViews: Remove test artifact (status filter was set as primary). ([58682](https://github.com/WordPress/gutenberg/pull/58682)) +- DataViews: Use chips for filter summary. ([58816](https://github.com/WordPress/gutenberg/pull/58816)) +- Fix double scrollbar in grid layout. ([58536](https://github.com/WordPress/gutenberg/pull/58536)) +- Fix: Dataviews selection on patterns grid view. ([58726](https://github.com/WordPress/gutenberg/pull/58726)) + +#### Site Editor + +- Add context for the All translatable string and enforce l10n best practices. ([58196](https://github.com/WordPress/gutenberg/pull/58196)) +- Break long URL in page sidebar. ([58763](https://github.com/WordPress/gutenberg/pull/58763)) +- Editor: Fix block context defined for template parts. ([58807](https://github.com/WordPress/gutenberg/pull/58807)) +- Fix line-height in block card. ([58246](https://github.com/WordPress/gutenberg/pull/58246)) +- Hide export button if non-block-based theme. ([58346](https://github.com/WordPress/gutenberg/pull/58346)) +- Mobile site editor header toolbar button bugfix. ([58852](https://github.com/WordPress/gutenberg/pull/58852)) + +#### Post Editor + +- Editor: Don't hide authors' Combobox if the current author is missing. ([58719](https://github.com/WordPress/gutenberg/pull/58719)) +- Fix permalink input field text overflow ellipsis for Firefox. ([57310](https://github.com/WordPress/gutenberg/pull/57310)) +- Fix the position and size of the Options menu,. ([57515](https://github.com/WordPress/gutenberg/pull/57515)) +- Fix: Use old template panel if user doesn’t have access to view templates. ([58485](https://github.com/WordPress/gutenberg/pull/58485)) +- Template editing: Update fullscreen WP back functionality. ([58534](https://github.com/WordPress/gutenberg/pull/58534)) + +#### Interactivity API + +- Add `supports.interactivity` to the Query block. ([58316](https://github.com/WordPress/gutenberg/pull/58316)) +- Fix state intialization for asynchronous private stores. ([58754](https://github.com/WordPress/gutenberg/pull/58754)) +- Remove non-default suffix data wp context processing. ([58664](https://github.com/WordPress/gutenberg/pull/58664)) +- Use compat versions of HTML APIs. ([58846](https://github.com/WordPress/gutenberg/pull/58846)) + +#### Global Styles + +- Block Styles: Fix block style variation selector generation. ([58051](https://github.com/WordPress/gutenberg/pull/58051)) +- Fix Global styles text settings bleeding into placeholder component. ([58303](https://github.com/WordPress/gutenberg/pull/58303)) +- Global styles revisions: Fix is-selected rules from affecting other areas of the editor. ([58228](https://github.com/WordPress/gutenberg/pull/58228)) +- Site Editor: Prevent classic theme from accessing global style menu. ([58345](https://github.com/WordPress/gutenberg/pull/58345)) + +#### List View + +- Fix error when switching between template preview modes. ([58533](https://github.com/WordPress/gutenberg/pull/58533)) +- Navigation Submenu Block: Make block name affect list view. ([58296](https://github.com/WordPress/gutenberg/pull/58296)) +- Template Part: Fix site editor error when loading with list view set to always display. ([58868](https://github.com/WordPress/gutenberg/pull/58868)) + +#### Font Library + +- Avoid mutating fontface data. ([58473](https://github.com/WordPress/gutenberg/pull/58473)) +- Avoid running init functions when font library is available in core. ([58793](https://github.com/WordPress/gutenberg/pull/58793)) +- Fix size of demo text. ([58849](https://github.com/WordPress/gutenberg/pull/58849)) + +#### Typography + +- Fix font library modal dialog translatable strings. ([58256](https://github.com/WordPress/gutenberg/pull/58256)) +- Font Library: Change referenced tab name on Google Fonts confirmation dialog. ([58584](https://github.com/WordPress/gutenberg/pull/58584)) +- Font size: Allow for custom font size handling. ([58422](https://github.com/WordPress/gutenberg/pull/58422)) + +#### Script Modules API + +- Add import map polyfill. ([58263](https://github.com/WordPress/gutenberg/pull/58263)) +- Import Maps: Only emit CDATA wrappers for inline scripts for JavaScript. ([58818](https://github.com/WordPress/gutenberg/pull/58818)) + +#### Extensibility + +- Fix broken list markup in navigation block when 3rd party blocks are used as decendants of navigation block. ([55551](https://github.com/WordPress/gutenberg/pull/55551)) +- Navigation block: Check Block Hooks API callback hasn't already been added. ([58772](https://github.com/WordPress/gutenberg/pull/58772)) + +#### Synced Patterns + +- Disable overriding links of images inside pattern instances. ([58660](https://github.com/WordPress/gutenberg/pull/58660)) +- Fix nested pattern overrides and disable editing inner pattern. ([58541](https://github.com/WordPress/gutenberg/pull/58541)) + +#### Inspector Controls + +- Add missing PanelBody title for the columns block inspector. ([58452](https://github.com/WordPress/gutenberg/pull/58452)) +- Add spacing between input controls with custom values. ([58410](https://github.com/WordPress/gutenberg/pull/58410)) + +#### Custom Fields + +- Block Bindings: Update bindings registry with latest changes. ([58843](https://github.com/WordPress/gutenberg/pull/58843)) + +#### History + +- Columns: Batch vertical alignment updates. ([58801](https://github.com/WordPress/gutenberg/pull/58801)) + +#### Document Settings + +- Editor: Ensure the current author is included in the dropdown. ([58716](https://github.com/WordPress/gutenberg/pull/58716)) + +#### Rich Text + +- Add aria-readonly attribute to Rich Text component. ([58687](https://github.com/WordPress/gutenberg/pull/58687)) + +#### Navigation Menus + +- Navigation: Update the fallback block list to avoid a PHP Warning. ([58588](https://github.com/WordPress/gutenberg/pull/58588)) + +#### Patterns + +- Update the bindings attribs of blocks added during experimental phase. ([58483](https://github.com/WordPress/gutenberg/pull/58483)) + +#### Distraction Free + +- Add default restoration of UI when exiting distraction free mode. ([58455](https://github.com/WordPress/gutenberg/pull/58455)) + + +### Accessibility + +- Escape as Select/Edit mode Toggle. ([58637](https://github.com/WordPress/gutenberg/pull/58637)) +- Global styles revisions: Update text color contrast. ([58340](https://github.com/WordPress/gutenberg/pull/58340)) + +#### Components + +- CustomSelect: Disable `virtualFocus` to fix issue for screenreaders. ([58585](https://github.com/WordPress/gutenberg/pull/58585)) +- Font Library modal: Try to improve checkbox labelling. ([58339](https://github.com/WordPress/gutenberg/pull/58339)) +- PaletteEdit: Fix palette item accessibility. ([58214](https://github.com/WordPress/gutenberg/pull/58214)) + +#### Font Library + +- Buttons position and accessibility. ([58212](https://github.com/WordPress/gutenberg/pull/58212)) +- Fix focus loss when update/install button is pressed. ([58364](https://github.com/WordPress/gutenberg/pull/58364)) +- Removed and elements from Font Library Modal. ([58221](https://github.com/WordPress/gutenberg/pull/58221)) + +#### Block Library + +- Fix image link preset suggestions arrow key navigation. ([58615](https://github.com/WordPress/gutenberg/pull/58615)) + +#### CSS & Styling + +- Font Library: Fix font preview vertical alignment and respect reduce motion preference. ([58451](https://github.com/WordPress/gutenberg/pull/58451)) + +#### Widgets Editor + +- Widget Editor: Don't disable the Save button. ([58365](https://github.com/WordPress/gutenberg/pull/58365)) + +#### Typography + +- Fix fonts modal dialog buttons accessibility. ([58309](https://github.com/WordPress/gutenberg/pull/58309)) + +#### Commands + +- Fix labeling of the command palette. ([56718](https://github.com/WordPress/gutenberg/pull/56718)) + + +### Performance + +- Block editor: Optimise getGlobalBlockCount/getClientIdsWithDescendants. ([58356](https://github.com/WordPress/gutenberg/pull/58356)) +- Block editor: Prevent isSubtreeDisabled call if not needed. ([58349](https://github.com/WordPress/gutenberg/pull/58349)) +- Block editor: Reduce appender sync! subscriptions. ([58556](https://github.com/WordPress/gutenberg/pull/58556)) +- Block editor: selectors: Avoid has() or double get() on Maps. ([58372](https://github.com/WordPress/gutenberg/pull/58372)) +- Block preview: Prevent recalculating editor styles if additional styles is empty. ([58244](https://github.com/WordPress/gutenberg/pull/58244)) +- Image block: Remove a block editor store sub. ([57232](https://github.com/WordPress/gutenberg/pull/57232)) +- Inner blocks: Don't re-render list when controlled blocks change. ([58575](https://github.com/WordPress/gutenberg/pull/58575)) +- InnerBlocks: Fix continuous re-rendering on inner blocks change. ([58348](https://github.com/WordPress/gutenberg/pull/58348)) +- Navigation: Fix performance regression. ([58513](https://github.com/WordPress/gutenberg/pull/58513)) +- Post template: Don't fetch taxonomies if not needed. ([58245](https://github.com/WordPress/gutenberg/pull/58245)) +- Site editor: Add pattern/template load performance test with TT4. ([58734](https://github.com/WordPress/gutenberg/pull/58734)) +- Site editor: Avoid double post content parse (alternative). ([58146](https://github.com/WordPress/gutenberg/pull/58146)) +- Unmemoize Block component selectors. ([58355](https://github.com/WordPress/gutenberg/pull/58355)) +- core-data: Memoize `getEntitiesConfig` selector. ([58393](https://github.com/WordPress/gutenberg/pull/58393)) +- getBlockSettings: Avoid memoized selector with clientId. ([58405](https://github.com/WordPress/gutenberg/pull/58405)) +- useSettings: Extract selector. ([58354](https://github.com/WordPress/gutenberg/pull/58354)) + +#### Font Library + +- Font Collections: Lazy load json configuration for better performance. ([58530](https://github.com/WordPress/gutenberg/pull/58530)) + +#### List View + +- Unmemo recursive getEnabledClientIdsTree. ([58525](https://github.com/WordPress/gutenberg/pull/58525)) + +#### Block Editor + +- Optimize the 'useBlockDisplayTitle' hook. ([58250](https://github.com/WordPress/gutenberg/pull/58250)) + +#### Interactivity API + +- Break up long hydration task in interactivity init. ([58227](https://github.com/WordPress/gutenberg/pull/58227)) + + +### Experiments + +#### Data Views + +- Update styling details in list item layout. ([58397](https://github.com/WordPress/gutenberg/pull/58397)) + +#### Synced Patterns + +- Add a control per block to reset pattern overrides. ([57907](https://github.com/WordPress/gutenberg/pull/57907)) + + +### Documentation + +- Add video embed documentation and grammar fixes in the Block Editor Handbook. ([58029](https://github.com/WordPress/gutenberg/pull/58029)) +- Block API: Add `viewStyle` property support to `block.json`. ([55492](https://github.com/WordPress/gutenberg/pull/55492)) +- CheckboxControl: Add custom label example to Storybook. ([58438](https://github.com/WordPress/gutenberg/pull/58438)) +- Docs: Copy and formatting edits for the "Markup representation of a block" guide. ([58688](https://github.com/WordPress/gutenberg/pull/58688)) +- Docs: Copy and formatting edits for the "Registration of a block" guide. ([58709](https://github.com/WordPress/gutenberg/pull/58709)) +- Docs: Copy and formatting edits for the "Static or Dynamic rendering" guide. ([58681](https://github.com/WordPress/gutenberg/pull/58681)) +- Docs: Copy and formatting edits for the "The block in the Editor" guide. ([58697](https://github.com/WordPress/gutenberg/pull/58697)) +- Docs: Copy and formatting edits for the "The block wrapper" guide. ([58704](https://github.com/WordPress/gutenberg/pull/58704)) +- Docs: Copy and formatting edits for the "Working with Javascript for the Block Editor" guide. ([58651](https://github.com/WordPress/gutenberg/pull/58651)) +- Docs: Copy and formatting edits for the "block.json" guide. ([58732](https://github.com/WordPress/gutenberg/pull/58732)) +- Docs: Copy edits and list formatting for main Block Editor Handbook readme. ([58652](https://github.com/WordPress/gutenberg/pull/58652)) +- Docs: Fix list formatting and some grammar in the Entities explanation doc. ([58655](https://github.com/WordPress/gutenberg/pull/58655)) +- Docs: Fix list markup in the Fundamentals of Block Development section. ([58226](https://github.com/WordPress/gutenberg/pull/58226)) +- Docs: Fix mistake in viewScriptModule documentation. ([58815](https://github.com/WordPress/gutenberg/pull/58815)) +- Docs: Formatting and copy edits for the File structure of a block guide. ([58635](https://github.com/WordPress/gutenberg/pull/58635)) +- Docs: Minor copy edits for the Block Development Environment page. ([58614](https://github.com/WordPress/gutenberg/pull/58614)) +- Docs: Remove duplicate content and update links. ([58358](https://github.com/WordPress/gutenberg/pull/58358)) +- Docs: Update link to the correct Fundamentals doc. ([58352](https://github.com/WordPress/gutenberg/pull/58352)) +- Docs: Update list formatting and descriptions in the Fundamentals of Block Development doc. ([58630](https://github.com/WordPress/gutenberg/pull/58630)) +- Docs: Update the Getting Started readme in the Block Editor Handbook. ([58624](https://github.com/WordPress/gutenberg/pull/58624)) +- Reference Gutenberg in PHP documentation from main documentation. ([58453](https://github.com/WordPress/gutenberg/pull/58453)) +- Removed extra parenthesis from document. ([58662](https://github.com/WordPress/gutenberg/pull/58662)) +- Restructure the FAQs to work with the new TOC design in the Block Editor Handbook. ([58351](https://github.com/WordPress/gutenberg/pull/58351)) +- Storybook: Add badges to private components. ([58123](https://github.com/WordPress/gutenberg/pull/58123)) +- Update documentation to avoid recommending early return PHP "anti-pattern". ([58454](https://github.com/WordPress/gutenberg/pull/58454)) +- Update to rename reusable blocks. ([58633](https://github.com/WordPress/gutenberg/pull/58633)) +- Update versions-in-wordpress.md. ([58545](https://github.com/WordPress/gutenberg/pull/58545)) +- fix: InnerBlocks schema description in block.json. ([58649](https://github.com/WordPress/gutenberg/pull/58649)) + + +### Code Quality + +- Avoid running pattern overrides migration in WordPress core. ([58487](https://github.com/WordPress/gutenberg/pull/58487)) +- Build: Add package build shebang and sync comments. ([58264](https://github.com/WordPress/gutenberg/pull/58264)) +- Date: Merge 6.4 and 6.5 compat files. ([58479](https://github.com/WordPress/gutenberg/pull/58479)) +- DefaultBlockAppender: Refactor to hooks. ([58809](https://github.com/WordPress/gutenberg/pull/58809)) +- Docs: Clarify the non-contextual post types. ([58836](https://github.com/WordPress/gutenberg/pull/58836)) +- Layout block supports use `str_contains`. ([58251](https://github.com/WordPress/gutenberg/pull/58251)) +- Move Nav Link PHPUnit tests to blocks directory. ([58460](https://github.com/WordPress/gutenberg/pull/58460)) + +#### Font Library + +- Address feedback from wordpress-develop#6027. ([58691](https://github.com/WordPress/gutenberg/pull/58691)) +- Fix font library unit tests nit-picks [round 2]. ([58612](https://github.com/WordPress/gutenberg/pull/58612)) +- Font Collections: Standardizes docblock comments. ([58654](https://github.com/WordPress/gutenberg/pull/58654)) +- Font Library Address Outstanding Feedback from WP 6.4 review. ([58675](https://github.com/WordPress/gutenberg/pull/58675)) +- Move Fonts Library to compat dir for 6.5. ([58608](https://github.com/WordPress/gutenberg/pull/58608)) +- Remove font family and font face preview keys from theme.json schema. ([58395](https://github.com/WordPress/gutenberg/pull/58395)) +- Remove old and unused component and css. ([58449](https://github.com/WordPress/gutenberg/pull/58449)) +- Remove slug from collection schema to accommodate the changes on the wp_register_font_collection function signature. ([58623](https://github.com/WordPress/gutenberg/pull/58623)) +- Remove tests from classes that were already merged in core. ([58752](https://github.com/WordPress/gutenberg/pull/58752)) +- Remove tests from font library rest controllers already merged into core. ([58778](https://github.com/WordPress/gutenberg/pull/58778)) +- Return null if a font collection is not registered. ([58735](https://github.com/WordPress/gutenberg/pull/58735)) +- Simplify font collection schema. ([58574](https://github.com/WordPress/gutenberg/pull/58574)) +- Update Font Library REST API code to align with Core standards. ([58619](https://github.com/WordPress/gutenberg/pull/58619)) +- Update Font Library non-REST API code to align with Core standards. ([58607](https://github.com/WordPress/gutenberg/pull/58607)) +- Update font collection json schema. ([58413](https://github.com/WordPress/gutenberg/pull/58413)) +- Update fonts collection data URL for Gutenberg 17.7. ([58746](https://github.com/WordPress/gutenberg/pull/58746)) +- Use Button's API to disable footer buttons. ([58529](https://github.com/WordPress/gutenberg/pull/58529)) +- [Font Library] Update PHPUnit tests per Core coding standards and practices. ([58502](https://github.com/WordPress/gutenberg/pull/58502)) + +#### Components + +- Add eslint rule for theme var regressions. ([58130](https://github.com/WordPress/gutenberg/pull/58130)) +- Add stylelint rule for theme var regressions. ([58098](https://github.com/WordPress/gutenberg/pull/58098)) +- AnglePickerControl: Hard deprecate bottom margin. ([58700](https://github.com/WordPress/gutenberg/pull/58700)) +- CustomGradientPicker: Hard deprecate outer margins. ([58699](https://github.com/WordPress/gutenberg/pull/58699)) +- FontSizePicker: Hard deprecate bottom margin. ([58702](https://github.com/WordPress/gutenberg/pull/58702)) +- GradientPicker: Hard deprecate outer margins. ([58701](https://github.com/WordPress/gutenberg/pull/58701)) +- Remove deprecation warnings for `__next36pxDefaultSize`. ([58703](https://github.com/WordPress/gutenberg/pull/58703)) + +#### Block Library + +- Interactivity API - Blocks: Move interactivity registration to render. ([58678](https://github.com/WordPress/gutenberg/pull/58678)) +- Navigation: Move the Navigation block rendering tests to the blocks directory. ([58247](https://github.com/WordPress/gutenberg/pull/58247)) +- Navigation: Remove use of Gutenberg_Navigation_Fallback class. ([58369](https://github.com/WordPress/gutenberg/pull/58369)) +- Paragraph: Update comment block. ([58419](https://github.com/WordPress/gutenberg/pull/58419)) +- Rename variation build methods. ([58538](https://github.com/WordPress/gutenberg/pull/58538)) +- Template Part: Derive 'hasInnerBlocks' inside selector. ([58680](https://github.com/WordPress/gutenberg/pull/58680)) + +#### Block Editor + +- Block Switcher: Don't use the 'useBlockDisplayInformation' hook. ([58562](https://github.com/WordPress/gutenberg/pull/58562)) +- BlockSelectionButton: Don't use the 'useBlockDisplayInformation' hook. ([58640](https://github.com/WordPress/gutenberg/pull/58640)) +- Link Control: Simplify the sprintf. ([58831](https://github.com/WordPress/gutenberg/pull/58831)) +- RichTextData: Use a private property. ([58557](https://github.com/WordPress/gutenberg/pull/58557)) + +#### Post Editor + +- Editor Settings: Rename the getPostLinkProps setting. ([58416](https://github.com/WordPress/gutenberg/pull/58416)) +- Editor: Reuse data query in the post author components. ([58760](https://github.com/WordPress/gutenberg/pull/58760)) +- Editor: Use hooks instead of HoCs in the post-taxonomies components. ([58446](https://github.com/WordPress/gutenberg/pull/58446)) +- Fix: Refactor pre publish panel to use function component instead of class. ([58441](https://github.com/WordPress/gutenberg/pull/58441)) + +#### Custom Fields + +- Block Bindings: Remove unneeded 'setAttributes' override. ([58806](https://github.com/WordPress/gutenberg/pull/58806)) + +#### Patterns + +- Pattern overrides: Update overrides attribute data structure and rename it to `content`. ([58596](https://github.com/WordPress/gutenberg/pull/58596)) + + +### Tools + +- Add BlockJsonDependenciesPlugin to modules build. ([57927](https://github.com/WordPress/gutenberg/pull/57927)) +- DEWP: Fix script module import field. ([58770](https://github.com/WordPress/gutenberg/pull/58770)) +- Introduce a Props Bot workflow. ([58576](https://github.com/WordPress/gutenberg/pull/58576)) +- More refinements to Props Bot run conditions. ([58617](https://github.com/WordPress/gutenberg/pull/58617)) +- Refine when Props Bot runs. ([58616](https://github.com/WordPress/gutenberg/pull/58616)) +- Remove noahtallen from .wp-env codeowners. ([58283](https://github.com/WordPress/gutenberg/pull/58283)) +- Scripts: Add viewScriptModule block.json support. ([58203](https://github.com/WordPress/gutenberg/pull/58203)) + +#### Testing + +- "Multiple use" block validation logic improvement [with Playwright]. ([57576](https://github.com/WordPress/gutenberg/pull/57576)) +- Block Bindings: Add block bindings end-to-end tests. ([58550](https://github.com/WordPress/gutenberg/pull/58550)) +- Block Bindings: Add tests for the frontend and polish the existing ones. ([58676](https://github.com/WordPress/gutenberg/pull/58676)) +- Block Bindings: Improve the code of the block bindings tests. ([58785](https://github.com/WordPress/gutenberg/pull/58785)) +- Button: Add focusable disabled variant to vizreg Storybook. ([58634](https://github.com/WordPress/gutenberg/pull/58634)) +- CustomSelect: Add tests for new features. ([58583](https://github.com/WordPress/gutenberg/pull/58583)) +- Fix flaky test of data-wp-on-window directive. ([58642](https://github.com/WordPress/gutenberg/pull/58642)) +- Flaky Test: Fix "directives inside islands should not be hydrated twice". ([58516](https://github.com/WordPress/gutenberg/pull/58516)) +- Interactivity API: Fix flaky test in `data-wp-on-document`. ([58668](https://github.com/WordPress/gutenberg/pull/58668)) +- Migrate remaining 'inserting blocks' end-to-end tests to Playwright. ([58108](https://github.com/WordPress/gutenberg/pull/58108)) +- Migrate remaining 'pattern block' end-to-end tests to Playwright. ([58486](https://github.com/WordPress/gutenberg/pull/58486)) +- SearchControl: Add unit tests. ([58693](https://github.com/WordPress/gutenberg/pull/58693)) +- Try fixing flaky 'inserting blocks' end-to-end tests. ([58848](https://github.com/WordPress/gutenberg/pull/58848)) +- Try fixing flaky Paragraph block end-to-end test. ([58208](https://github.com/WordPress/gutenberg/pull/58208)) +- Use toBeDisabled instead of aria-disabled check. ([58694](https://github.com/WordPress/gutenberg/pull/58694)) +- e2e: Add a test to confirm that the focus moves from the post title to the paragraph using the enter key. ([58872](https://github.com/WordPress/gutenberg/pull/58872)) +- end-to-end Utils: Ensure deleteAllUsers does not delete current user. ([58320](https://github.com/WordPress/gutenberg/pull/58320)) + +#### Build Tooling + +- Add missing Interactivity API label to changelog script. ([58879](https://github.com/WordPress/gutenberg/pull/58879)) +- Enable dynamic import transform for React Native tests. ([58546](https://github.com/WordPress/gutenberg/pull/58546)) +- Fix: Remove mention of weekly meeting from first time contributor PR label. ([58547](https://github.com/WordPress/gutenberg/pull/58547)) +- Interactivity API: Move Core implementation to compat 6.5 folder. ([58829](https://github.com/WordPress/gutenberg/pull/58829)) +- Remove phpunit tests for features backported to Core. ([58776](https://github.com/WordPress/gutenberg/pull/58776)) +- Update Performance tests base branch. ([58890](https://github.com/WordPress/gutenberg/pull/58890)) +- Workflows: Add 'Technical Prototype' to the type-related labels list. ([58163](https://github.com/WordPress/gutenberg/pull/58163)) + + +### Security + +#### Font Library + +- Sanitize font collection data. ([58636](https://github.com/WordPress/gutenberg/pull/58636)) + +#### REST API + +- Font Library REST API: Sanitize font family and font face settings. ([58590](https://github.com/WordPress/gutenberg/pull/58590)) + + +### Various + +- Script loader 6.4 compat: Check for init hook completion. ([58406](https://github.com/WordPress/gutenberg/pull/58406)) + +#### Font Library + +- Code style and code quality feedback from core 6.5 review. ([58736](https://github.com/WordPress/gutenberg/pull/58736)) +- Move getAllowedMimeTypes to FontUtils. ([58667](https://github.com/WordPress/gutenberg/pull/58667)) +- Refactor as a singleton. ([58669](https://github.com/WordPress/gutenberg/pull/58669)) + +#### Components + +- Removing Reakit `Composite` implementation. ([58620](https://github.com/WordPress/gutenberg/pull/58620)) +- Removing Reakit as a dependency. ([58631](https://github.com/WordPress/gutenberg/pull/58631)) +- Update the Snackbar warning message. ([58591](https://github.com/WordPress/gutenberg/pull/58591)) + +#### Global Styles + +- Always output core block global styles after base global styles. ([58761](https://github.com/WordPress/gutenberg/pull/58761)) +- Backport theme.json tests from Core. ([58476](https://github.com/WordPress/gutenberg/pull/58476)) + +#### Block Library + +- Reduce label and fix capitalization for image block upload label. ([58677](https://github.com/WordPress/gutenberg/pull/58677)) +- Separator: Remove border-bottom property. ([55725](https://github.com/WordPress/gutenberg/pull/55725)) + +#### Patterns + +- Update pattern copy to Synced instead of Fully Synced. ([58876](https://github.com/WordPress/gutenberg/pull/58876)) + +#### Block API + +- ViewScriptModule: 6.5 compatibility changes. ([58832](https://github.com/WordPress/gutenberg/pull/58832)) + +#### Custom Fields + +- Block Bindings: Backport block bindings refactor from WordPress core. ([58683](https://github.com/WordPress/gutenberg/pull/58683)) + +#### Inspector Controls + +- Change cover block's "Media settings" label to "Settings". ([58463](https://github.com/WordPress/gutenberg/pull/58463)) + +## First time contributors + +The following PRs were merged by first time contributors: + +- @at-benni: Update versions-in-wordpress.md. ([58545](https://github.com/WordPress/gutenberg/pull/58545)) +- @krupal-panchal: Removed extra parenthesis from document. ([58662](https://github.com/WordPress/gutenberg/pull/58662)) +- @shreyash3087: fix: InnerBlocks schema description in block.json. ([58649](https://github.com/WordPress/gutenberg/pull/58649)) + + +## Contributors + +The following contributors merged PRs in this release: + +@aaronrobertshaw @afercia @ajlende @andrewhayward @andrewserong @annezazu @anton-vlasenko @antonis @aristath @artemiomorales @at-benni @brookewp @c4rl0sbr4v0 @carolinan @chad1008 @ciampo @creativecoder @DAreRodz @dcalhoun @dd32 @derekblank @desrosj @draganescu @ellatrix @fabiankaegy @fai-sal @fluiddot @gaambo @getdave @glendaviesnz @hellofromtonya @ironprogrammer @jameskoster @jasmussen @jeherve @jeryj @jorgefilipecosta @jsnajdr @kevin940726 @krupal-panchal @luisherranz @madhusudhand @MaggieCabrera @Mamaduka @matiasbenedetto @mikachan @mirka @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ockham @pbking @ramonjd @retrofox @richtabor @SantosGuillamot @scruffian @shreyash3087 @sirreal @t-hamano @talldan @tellthemachines @tjcafferkey @tomjn @tyxla @vcanales @westonruter @WunderBart @youknowriad + + + + = 17.6.6 = ## Changelog From ba496e6232f577bed6de2c4e2f2fe403a9e1a17d Mon Sep 17 00:00:00 2001 From: Juan Aldasoro Date: Wed, 14 Feb 2024 16:38:21 +0100 Subject: [PATCH 11/31] Editor: Limit spotlight mode to the editor. (#58817) * Limit spotlight mode to the editor. * Revert "Limit spotlight mode to the editor." This reverts commit b8d47545cdeb86efdcecd767bd80293eb6e9d0ec. * Disable "Spotlight mode" for block previews. * Revert non-required changes. --- .../block-editor/src/components/block-preview/index.js | 7 ++++++- packages/edit-site/src/components/style-book/index.js | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index 0fb7f55b9955d2..245d0ee4348b2e 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -54,7 +54,11 @@ export function BlockPreview( { [] ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + focusMode: false, // Disable "Spotlight mode". + __unstableIsPreviewMode: true, + } ), [ originalSettings ] ); const renderedBlocks = useMemo( @@ -117,6 +121,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { () => ( { ...originalSettings, styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles. + focusMode: false, // Disable "Spotlight mode". __unstableIsPreviewMode: true, } ), [ originalSettings ] diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 7ecfdc3506cf8a..b8e18533f5879a 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -425,7 +425,11 @@ const Example = ( { id, title, blocks, isSelected, onClick } ) => { [] ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + focusMode: false, // Disable "Spotlight mode". + __unstableIsPreviewMode: true, + } ), [ originalSettings ] ); From 282202918372f43766dd2b50911b9f4974f5e9a7 Mon Sep 17 00:00:00 2001 From: Colin Stewart <79332690+costdev@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:04:03 +0000 Subject: [PATCH 12/31] Font Library: PHP 8.1.12 check for woff/woff2 mime types (#59015) Fixes a bug where fonts could not be installed in PHP 8.1.0 through 8.1.11 due to incorrect MIME type assignment. While `WP_Font_Utils::get_allowed_font_mime_types()` conditionally sets the MIME type for woff and woff2, it incorrectly checks against PHP 8.1.0. The MIME type change did not occur until PHP 8.1.12. References: * PHP-src: finfo returns wrong mime type for woff/woff2 files * PHP 8.1.12 changelog * Tests: Adjust the expected mime type for WOFF fonts on PHP 8.1.12+. Co-authored-by: costdev Co-authored-by: hellofromtonya Co-authored-by: huzaifaalmesbah Co-authored-by: kafleg --- lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php index 23c95d633fb47b..0954aac4a6219c 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php @@ -233,8 +233,8 @@ public static function get_allowed_font_mime_types() { return array( 'otf' => 'application/vnd.ms-opentype', 'ttf' => PHP_VERSION_ID >= 70400 ? 'font/sfnt' : $php_7_ttf_mime_type, - 'woff' => PHP_VERSION_ID >= 80100 ? 'font/woff' : 'application/font-woff', - 'woff2' => PHP_VERSION_ID >= 80100 ? 'font/woff2' : 'application/font-woff2', + 'woff' => PHP_VERSION_ID >= 80112 ? 'font/woff' : 'application/font-woff', + 'woff2' => PHP_VERSION_ID >= 80112 ? 'font/woff2' : 'application/font-woff2', ); } } From 6d3e24a792f627a2e4367632ec799ce3abafa447 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+c4rl0sbr4v0@users.noreply.github.com> Date: Wed, 14 Feb 2024 18:00:28 +0100 Subject: [PATCH 13/31] Interactivity API: Update docs guide with new `wp-interactivity` directive implementation. (#59018) * Update doc guide with new wp-interactivity string * Better rephrasing Co-authored-by: c4rl0sbr4v0 Co-authored-by: SantosGuillamot --- .../interactivity/docs/2-api-reference.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/interactivity/docs/2-api-reference.md b/packages/interactivity/docs/2-api-reference.md index bae15e9a7fcf2f..285b9ea152a412 100644 --- a/packages/interactivity/docs/2-api-reference.md +++ b/packages/interactivity/docs/2-api-reference.md @@ -47,7 +47,7 @@ _Example of directives used in the HTML markup_ ```html
@@ -69,14 +69,25 @@ Directives can also be injected dynamically using the [HTML Tag Processor](https ### List of Directives -With directives, we can directly manage behavior related to things such as side effects, state, event handlers, attributes or content. +With directives, we can directly manage interactions related to things such as side effects, state, event handlers, attributes or content. #### `wp-interactive` -The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store). It includes a namespace to reference a specific store. +The `wp-interactive` directive "activates" the interactivity for the DOM element and its children through the Interactivity API (directives and store). The directive includes a namespace to reference a specific store, that can be set as a `string` or an `object`. ```html +
+

I'm interactive now, >and I can use directives!

+
+

I'm also interactive, and I can also use directives!

+
+
+```html +
+
From 2d7a1de35a0552309db5887a1d30c15f2a808500 Mon Sep 17 00:00:00 2001 From: Lena Morita Date: Thu, 15 Feb 2024 02:14:42 +0900 Subject: [PATCH 14/31] CustomSelectControl: Hard deprecate constrained width (#58974) * CustomSelectControl: Hard deprecate constrained width * Remove prop from consumers * Update changelog Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: tyxla --- .../components/date-format-picker/index.js | 1 - .../font-appearance-control/index.js | 1 - .../input-controls/spacing-input-control.js | 1 - packages/block-editor/src/hooks/position.js | 1 - packages/components/CHANGELOG.md | 4 +++ .../src/custom-select-control/README.md | 10 ------- .../src/custom-select-control/index.js | 25 ++--------------- .../stories/index.story.js | 1 - .../src/custom-select-control/styles.ts | 28 ------------------- .../src/custom-select-control/test/index.js | 1 - .../font-size-picker-select.tsx | 1 - 11 files changed, 7 insertions(+), 67 deletions(-) delete mode 100644 packages/components/src/custom-select-control/styles.ts diff --git a/packages/block-editor/src/components/date-format-picker/index.js b/packages/block-editor/src/components/date-format-picker/index.js index 7a2ed46b4a9b04..8c35b025bfccf6 100644 --- a/packages/block-editor/src/components/date-format-picker/index.js +++ b/packages/block-editor/src/components/date-format-picker/index.js @@ -117,7 +117,6 @@ function NonDefaultControls( { format, onChange } ) { return ( onChange( selectedItem.style ) } - __nextUnconstrainedWidth /> ) ); 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 c2b6ae30de7ac9..f0b0d28e70c0fd 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 @@ -297,7 +297,6 @@ export default function SpacingInputControl( { options={ options } label={ ariaLabel } hideLabelFromVision={ true } - __nextUnconstrainedWidth={ true } size={ '__unstable-large' } onMouseOver={ onMouseOver } onMouseOut={ onMouseOut } diff --git a/packages/block-editor/src/hooks/position.js b/packages/block-editor/src/hooks/position.js index 5017cb34fc18bd..e1e26d54aa2420 100644 --- a/packages/block-editor/src/hooks/position.js +++ b/packages/block-editor/src/hooks/position.js @@ -288,7 +288,6 @@ export function PositionPanelPure( { help={ stickyHelpText } > setFontSize( selectedItem ) } @@ -53,7 +52,6 @@ function MyControlledCustomSelectControl() { const [ fontSize, setFontSize ] = useState( options[ 0 ] ); return ( setFontSize( selectedItem ) } @@ -114,14 +112,6 @@ Can be used to externally control the value of the control, like in the `MyContr - Type: `Object` - Required: No -#### __nextUnconstrainedWidth - -Start opting into the unconstrained width style that will become the default in a future version, currently scheduled to be WordPress 6.4. (The prop can be safely removed once this happens.) - -- Type: `Boolean` -- Required: No -- Default: `false` - #### onMouseOver A handler for onMouseOver events. diff --git a/packages/components/src/custom-select-control/index.js b/packages/components/src/custom-select-control/index.js index eb3cf5ba0676e0..5805e18b98dd41 100644 --- a/packages/components/src/custom-select-control/index.js +++ b/packages/components/src/custom-select-control/index.js @@ -11,7 +11,6 @@ import classnames from 'classnames'; import { Icon, check } from '@wordpress/icons'; import { __, sprintf } from '@wordpress/i18n'; import { useCallback, useState } from '@wordpress/element'; -import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -19,9 +18,9 @@ import deprecated from '@wordpress/deprecated'; import { VisuallyHidden } from '../visually-hidden'; import { Select as SelectControlSelect } from '../select-control/styles/select-control-styles'; import SelectControlChevronDown from '../select-control/chevron-down'; -import { InputBaseWithBackCompatMinWidth } from './styles'; import { StyledLabel } from '../base-control/styles/base-control-styles'; import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props'; +import InputBase from '../input-control/input-base'; const itemToString = ( item ) => item?.name; // This is needed so that in Windows, where @@ -67,8 +66,6 @@ export default function CustomSelectControl( props ) { const { /** Start opting into the larger default height that will become the default size in a future version. */ __next40pxDefaultSize = false, - /** Start opting into the unconstrained width that will become the default in a future version. */ - __nextUnconstrainedWidth = false, className, hideLabelFromVision, label, @@ -116,17 +113,6 @@ export default function CustomSelectControl( props ) { onBlur?.( e ); } - if ( ! __nextUnconstrainedWidth ) { - deprecated( - 'Constrained width styles for wp.components.CustomSelectControl', - { - since: '6.1', - version: '6.4', - hint: 'Set the `__nextUnconstrainedWidth` prop to true to start opting into the new styles, which will become the default in a future version', - } - ); - } - function getDescribedBy() { if ( describedBy ) { return describedBy; @@ -180,14 +166,9 @@ export default function CustomSelectControl( props ) { { label } ) } - } > @@ -215,7 +196,7 @@ export default function CustomSelectControl( props ) { ) } - + { /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */ }
    { isOpen && diff --git a/packages/components/src/custom-select-control/stories/index.story.js b/packages/components/src/custom-select-control/stories/index.story.js index d8fea5c7baa003..ecfa3b06392ae9 100644 --- a/packages/components/src/custom-select-control/stories/index.story.js +++ b/packages/components/src/custom-select-control/stories/index.story.js @@ -20,7 +20,6 @@ export default { export const Default = CustomSelectControl.bind( {} ); Default.args = { - __nextUnconstrainedWidth: true, label: 'Label', options: [ { diff --git a/packages/components/src/custom-select-control/styles.ts b/packages/components/src/custom-select-control/styles.ts deleted file mode 100644 index e16b5d0b7bdd7a..00000000000000 --- a/packages/components/src/custom-select-control/styles.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * External dependencies - */ -import { css } from '@emotion/react'; -import styled from '@emotion/styled'; - -/** - * Internal dependencies - */ -import InputBase from '../input-control/input-base'; -import { Container as InputControlContainer } from '../input-control/styles/input-control-styles'; - -type BackCompatMinWidthProps = { - __nextUnconstrainedWidth: boolean; -}; - -const backCompatMinWidth = ( props: BackCompatMinWidthProps ) => - ! props.__nextUnconstrainedWidth - ? css` - ${ InputControlContainer } { - min-width: 130px; - } - ` - : ''; - -export const InputBaseWithBackCompatMinWidth = styled( InputBase )` - ${ backCompatMinWidth } -`; diff --git a/packages/components/src/custom-select-control/test/index.js b/packages/components/src/custom-select-control/test/index.js index 52bb841a4f953e..a4c61d0cdcecd9 100644 --- a/packages/components/src/custom-select-control/test/index.js +++ b/packages/components/src/custom-select-control/test/index.js @@ -46,7 +46,6 @@ const props = { }, }, ], - __nextUnconstrainedWidth: true, }; const ControlledCustomSelectControl = ( { options } ) => { diff --git a/packages/components/src/font-size-picker/font-size-picker-select.tsx b/packages/components/src/font-size-picker/font-size-picker-select.tsx index 32438cfab81153..c5dca6bdb37a04 100644 --- a/packages/components/src/font-size-picker/font-size-picker-select.tsx +++ b/packages/components/src/font-size-picker/font-size-picker-select.tsx @@ -69,7 +69,6 @@ const FontSizePickerSelect = ( props: FontSizePickerSelectProps ) => { return ( Date: Wed, 14 Feb 2024 14:10:56 -0500 Subject: [PATCH 15/31] Remove repository specific Code of Conduct. (#59027) This removes the repository specific `CODE_OF_CONDUCT.md` file in favor of the newly added version maintained as the organization's default within the WordPress/.github repository. While this file will not be included in `git clone`s, this change enables more consistent messaging for the community code of conduct, and allows the file to be updated in one location for all repositories under the WordPress organization. Co-authored-by: desrosj Co-authored-by: alexstine Co-authored-by: angelasjin --- .github/SUPPORT.md | 2 +- CODE_OF_CONDUCT.md | 11 ----------- CONTRIBUTING.md | 2 +- README.md | 2 +- 4 files changed, 3 insertions(+), 14 deletions(-) delete mode 100644 CODE_OF_CONDUCT.md diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index cc6b8e4d613513..ce1a0a1acffa54 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -5,7 +5,7 @@ Welcome to Gutenberg, a WordPress project. We hope you join us in creating the f * Please see the [Contributing Guidelines](https://github.com/WordPress/gutenberg/blob/HEAD/CONTRIBUTING.md) for additional information on how to contribute. -* As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://github.com/WordPress/gutenberg/blob/HEAD/CODE_OF_CONDUCT.md). +* As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/). * Join us on Slack for real-time communication, it is where maintainers coordinate around the project. To get started using Slack, see: https://make.wordpress.org/chat/ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index f9afa872a60842..00000000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,11 +0,0 @@ -This project comes under the WordPress [Etiquette](https://wordpress.org/about/etiquette/): - -In the WordPress open source project, we realize that our biggest asset is the community that we foster. The project, as a whole, follows these basic philosophical principles from The Cathedral and The Bazaar. - -- Contributions to the WordPress open source project are for the benefit of the WordPress community as a whole, not specific businesses or individuals. All actions taken as a contributor should be made with the best interests of the community in mind. -- Participation in the WordPress open source project is open to all who wish to join, regardless of ability, skill, financial status, or any other criteria. -- The WordPress open source project is a volunteer-run community. Even in cases where contributors are sponsored by companies, that time is donated for the benefit of the entire open source community. -- Any member of the community can donate their time and contribute to the project in any form including design, code, documentation, community building, etc. For more information, go to make.wordpress.org. -- The WordPress open source community cares about diversity. We strive to maintain a welcoming environment where everyone can feel included, by keeping communication free of discrimination, incitement to violence, promotion of hate, and unwelcoming behavior. - -The team involved will block any user who causes any breach in this. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd137ea37201c9..8eb4b77dbfcca9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ To learn all about contributing to the Gutenberg project, see the [Contributor G ## Guidelines -- As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](/CODE_OF_CONDUCT.md). +- As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/). - Contributors should review the [overall process and best practices for pull requests](https://github.com/WordPress/gutenberg/blob/trunk/docs/contributors/repository-management.md#pull-requests), adhering to WordPress' [JavaScript coding standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/) and [accessibility coding standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/accessibility/). diff --git a/README.md b/README.md index d5b299baadc7f8..33f76716470751 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ To get up and running quickly with **code contribution** see [Getting Started Wi In whichever way you wish to contribute please be sure to read the [Contributing Guidelines](https://github.com/WordPress/gutenberg/blob/HEAD/CONTRIBUTING.md) first. -As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://github.com/WordPress/gutenberg/blob/HEAD/CODE_OF_CONDUCT.md). +As with all WordPress projects, we want to ensure a welcoming environment for everyone. With that in mind, all contributors are expected to follow our [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/). ## Get Involved From 0a82d9f1388cd743ede76fb97c618c8295a9165c Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 14 Feb 2024 17:16:30 -0300 Subject: [PATCH 16/31] Font Library: fixes installed font families not rendering in the editor or frontend. (#59019) * Improves the sanitize_font_family function to output CSS valid font-family values according to CSS spec * add font-family css specific sanitization for fontFamily properties of the fonts from font collections * use _wp_to_kebab_case to format the font slug property of fonts from font collections * format comment * improving fontFontFamily and add formatFontFaceName functions to ensure that CSS properties are valid * load font face in both iframe and document * use the wordpress function to generate slugs for font files uploads * lint variable names * add exception for firefox in the font face name formatting * format php * improve php check * format php * replace firefox by gecko to cover all gecko engine browsers Co-authored-by: Juan Aldasoro <252415+juanfra@users.noreply.github.com> * remove not needed repeated call * using firefox and fxios to detect firefox browser user agent --------- Co-authored-by: Juan Aldasoro <252415+juanfra@users.noreply.github.com> Co-authored-by: matiasbenedetto Co-authored-by: juanfra Co-authored-by: arthur791004 Co-authored-by: richtabor Co-authored-by: pbking Co-authored-by: getdave Co-authored-by: okmttdhr Co-authored-by: nith53 --- .../fonts/class-wp-font-collection.php | 6 +- .../fonts/class-wp-font-utils.php | 61 +++++++++---- .../font-library-modal/context.js | 2 +- .../font-library-modal/utils/index.js | 4 +- .../utils/make-families-from-faces.js | 14 ++- .../utils/preview-styles.js | 87 +++++++++++++++---- .../utils/test/preview-styles.spec.js | 55 ++++++++++-- 7 files changed, 184 insertions(+), 45 deletions(-) diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php index 4a01f748d16e42..cd402a8e545003 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php @@ -221,8 +221,10 @@ private static function get_sanitization_schema() { array( 'font_family_settings' => array( 'name' => 'sanitize_text_field', - 'slug' => 'sanitize_title', - 'fontFamily' => 'sanitize_text_field', + 'slug' => static function ( $value ) { + return _wp_to_kebab_case( sanitize_title( $value ) ); + }, + 'fontFamily' => 'WP_Font_Utils::sanitize_font_family', 'preview' => 'sanitize_url', 'fontFace' => array( array( diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php index 0954aac4a6219c..7af1b0af002f55 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php @@ -20,11 +20,41 @@ * @access private */ class WP_Font_Utils { + + /** + * Adds surrounding quotes to font family names that contain special characters. + * + * It follows the recommendations from the CSS Fonts Module Level 4. + * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop + * + * @since 6.5.0 + * @access private + * + * @see sanitize_font_family() + * + * @param string $item A font family name. + * @return string The font family name with surrounding quotes if necessary. + */ + private static function maybe_add_quotes( $item ) { + // Match any non alphabetic characters (a-zA-Z), dashes -, or parenthesis (). + $regex = '/[^a-zA-Z\-()]+/'; + $item = trim( $item ); + if ( preg_match( $regex, $item ) ) { + // Removes leading and trailing quotes. + $item = preg_replace( '/^["\']|["\']$/', '', $item ); + return "\"$item\""; + } + return $item; + } + /** * Sanitizes and formats font family names. * * - Applies `sanitize_text_field` - * - Adds surrounding quotes to names that contain spaces and are not already quoted + * - Adds surrounding quotes to names that special + * + * It follows the recommendations from the CSS Fonts Module Level 4. + * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop * * @since 6.5.0 * @access private @@ -39,26 +69,19 @@ public static function sanitize_font_family( $font_family ) { return ''; } - $font_family = sanitize_text_field( $font_family ); - $font_families = explode( ',', $font_family ); - $wrapped_font_families = array_map( - function ( $family ) { - $trimmed = trim( $family ); - if ( ! empty( $trimmed ) && str_contains( $trimmed, ' ' ) && ! str_contains( $trimmed, "'" ) && ! str_contains( $trimmed, '"' ) ) { - return '"' . $trimmed . '"'; + $output = trim( sanitize_text_field( $font_family ) ); + $formatted_items = array(); + if ( str_contains( $output, ',' ) ) { + $items = explode( ',', $output ); + foreach ( $items as $item ) { + $formatted_item = self::maybe_add_quotes( $item ); + if ( ! empty( $formatted_item ) ) { + $formatted_items[] = $formatted_item; } - return $trimmed; - }, - $font_families - ); - - if ( count( $wrapped_font_families ) === 1 ) { - $font_family = $wrapped_font_families[0]; - } else { - $font_family = implode( ', ', $wrapped_font_families ); + } + return implode( ', ', $formatted_items ); } - - return $font_family; + return self::maybe_add_quotes( $output ); } /** diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/context.js b/packages/edit-site/src/components/global-styles/font-library-modal/context.js index 04eabb149f5f4e..35276b0ad8b2b4 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/context.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/context.js @@ -392,7 +392,7 @@ function FontLibraryProvider( { children } ) { loadFontFaceInBrowser( face, getDisplaySrcFromFontFace( face.src ), - 'iframe' + 'all' ); } ); } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js index d0a53a4acea4f8..011f09b12a841f 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js @@ -9,7 +9,7 @@ import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { FONT_WEIGHTS, FONT_STYLES } from './constants'; import { unlock } from '../../../../lock-unlock'; import { fetchInstallFontFace } from '../resolvers'; -import { formatFontFamily } from './preview-styles'; +import { formatFontFaceName } from './preview-styles'; /** * Browser dependencies @@ -99,7 +99,7 @@ export async function loadFontFaceInBrowser( fontFace, source, addTo = 'all' ) { } const newFont = new window.FontFace( - formatFontFamily( fontFace.fontFamily ), + formatFontFaceName( fontFace.fontFamily ), dataSource, { style: fontFace.fontStyle, diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/utils/make-families-from-faces.js b/packages/edit-site/src/components/global-styles/font-library-modal/utils/make-families-from-faces.js index cbc995bedefd45..7cdbf405c0b5bc 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/utils/make-families-from-faces.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/utils/make-families-from-faces.js @@ -1,10 +1,22 @@ +/** + * WordPress dependencies + */ +import { privateApis as componentsPrivateApis } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { unlock } from '../../../../lock-unlock'; + +const { kebabCase } = unlock( componentsPrivateApis ); + export default function makeFamiliesFromFaces( fontFaces ) { const fontFamiliesObject = fontFaces.reduce( ( acc, item ) => { if ( ! acc[ item.fontFamily ] ) { acc[ item.fontFamily ] = { name: item.fontFamily, fontFamily: item.fontFamily, - slug: item.fontFamily.replace( /\s+/g, '-' ).toLowerCase(), + slug: kebabCase( item.fontFamily.toLowerCase() ), fontFace: [], }; } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/utils/preview-styles.js b/packages/edit-site/src/components/global-styles/font-library-modal/utils/preview-styles.js index 389cebde9249af..9cadc90448dfc4 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/utils/preview-styles.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/utils/preview-styles.js @@ -30,22 +30,79 @@ function extractFontWeights( fontFaces ) { return result; } +/* + * Format the font family to use in the CSS font-family property of a CSS rule. + * + * The input can be a string with the font family name or a string with multiple font family names separated by commas. + * It follows the recommendations from the CSS Fonts Module Level 4. + * https://www.w3.org/TR/css-fonts-4/#font-family-prop + * + * @param {string} input - The font family. + * @return {string} The formatted font family. + * + * Example: + * formatFontFamily( "Open Sans, Font+Name, sans-serif" ) => '"Open Sans", "Font+Name", sans-serif' + * formatFontFamily( "'Open Sans', sans-serif" ) => '"Open Sans", sans-serif' + * formatFontFamily( "DotGothic16, Slabo 27px, serif" ) => '"DotGothic16","Slabo 27px",serif' + * formatFontFamily( "Mine's, Moe's Typography" ) => `"mine's","Moe's Typography"` + */ export function formatFontFamily( input ) { - return input - .split( ',' ) - .map( ( font ) => { - font = font.trim(); // Remove any leading or trailing white spaces - // If the font doesn't start with quotes and contains a space, then wrap in quotes. - // Check that string starts with a single or double quote and not a space - if ( - ! ( font.startsWith( '"' ) || font.startsWith( "'" ) ) && - font.indexOf( ' ' ) !== -1 - ) { - return `"${ font }"`; - } - return font; // Return font as is if no transformation is needed - } ) - .join( ', ' ); + // Matchs any non alphabetic characters (a-zA-Z), dashes - , or parenthesis () + const regex = /[^a-zA-Z\-()]+/; + const output = input.trim(); + + const formatItem = ( item ) => { + item = item.trim(); + if ( item.match( regex ) ) { + // removes leading and trailing quotes. + item = item.replace( /^["']|["']$/g, '' ); + return `"${ item }"`; + } + return item; + }; + + if ( output.includes( ',' ) ) { + return output + .split( ',' ) + .map( formatItem ) + .filter( ( item ) => item !== '' ) + .join( ', ' ); + } + + return formatItem( output ); +} + +/* + * Format the font face name to use in the font-family property of a font face. + * + * The input can be a string with the font face name or a string with multiple font face names separated by commas. + * It removes the leading and trailing quotes from the font face name. + * + * @param {string} input - The font face name. + * @return {string} The formatted font face name. + * + * Example: + * formatFontFaceName("Open Sans") => "Open Sans" + * formatFontFaceName("'Open Sans', sans-serif") => "Open Sans" + * formatFontFaceName(", 'Open Sans', 'Helvetica Neue', sans-serif") => "Open Sans" + */ +export function formatFontFaceName( input ) { + let output = input.trim(); + if ( output.includes( ',' ) ) { + output = output + .split( ',' ) + // finds the first item that is not an empty string. + .find( ( item ) => item.trim() !== '' ) + .trim(); + } + // removes leading and trailing quotes. + output = output.replace( /^["']|["']$/g, '' ); + + // Firefox needs the font name to be wrapped in double quotes meanwhile other browsers don't. + if ( window.navigator.userAgent.toLowerCase().match( /firefox|fxios/i ) ) { + output = `"${ output }"`; + } + return output; } export function getFamilyPreviewStyle( family ) { diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/utils/test/preview-styles.spec.js b/packages/edit-site/src/components/global-styles/font-library-modal/utils/test/preview-styles.spec.js index 0273709502a43d..4fa18e00f2a8dd 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/utils/test/preview-styles.spec.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/utils/test/preview-styles.spec.js @@ -1,7 +1,11 @@ /** * Internal dependencies */ -import { getFamilyPreviewStyle, formatFontFamily } from '../preview-styles'; +import { + getFamilyPreviewStyle, + formatFontFamily, + formatFontFaceName, +} from '../preview-styles'; describe( 'getFamilyPreviewStyle', () => { it( 'should return default fontStyle and fontWeight if fontFace is not provided', () => { @@ -139,7 +143,7 @@ describe( 'formatFontFamily', () => { "Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', source-sans-pro, sans-serif" ) ).toBe( - "Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', source-sans-pro, sans-serif" + 'Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif' ); } ); @@ -153,9 +157,50 @@ describe( 'formatFontFamily', () => { ); } ); - it( 'should wrap only those font names with spaces which are not already quoted', () => { - expect( formatFontFamily( 'Baloo Bhai 2, Arial' ) ).toBe( - '"Baloo Bhai 2", Arial' + it( 'should wrap names with special characters in quotes', () => { + expect( + formatFontFamily( + 'Font+Name, Font*Name, _Font_Name_, generic(kai), sans-serif' + ) + ).toBe( + '"Font+Name", "Font*Name", "_Font_Name_", generic(kai), sans-serif' + ); + } ); + + it( 'should fix empty wrong formatted font family', () => { + expect( formatFontFamily( ', Abril Fatface,Times,serif' ) ).toBe( + '"Abril Fatface", Times, serif' + ); + } ); +} ); + +describe( 'formatFontFaceName', () => { + it( 'should remove leading and trailing quotes', () => { + expect( formatFontFaceName( '"Open Sans"' ) ).toBe( 'Open Sans' ); + } ); + + it( 'should remove leading and trailing quotes from multiple font face names', () => { + expect( + formatFontFaceName( "'Open Sans', 'Helvetica Neue', sans-serif" ) + ).toBe( 'Open Sans' ); + } ); + + it( 'should remove leading and trailing quotes even from names with spaces and special characters', () => { + expect( formatFontFaceName( "'Font+Name 24', sans-serif" ) ).toBe( + 'Font+Name 24' ); } ); + + it( 'should ouput the font face name with quotes on Firefox', () => { + const mockUserAgent = + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0'; + + // Mock the userAgent for this test + Object.defineProperty( window.navigator, 'userAgent', { + value: mockUserAgent, + configurable: true, + } ); + + expect( formatFontFaceName( 'Open Sans' ) ).toBe( '"Open Sans"' ); + } ); } ); From dffac590ccd10c7fd53bf4d5db1efa7a5f7dc1f0 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 15 Feb 2024 09:39:56 +0900 Subject: [PATCH 17/31] Font Libary: Add missing translation functions (#58104) Co-authored-by: t-hamano Co-authored-by: creativecoder Co-authored-by: matiasbenedetto --- .../font-library-modal/google-fonts-confirm-dialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js b/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js index 67140fbe4d0d93..dde6dc87c858ac 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js @@ -24,7 +24,7 @@ function GoogleFontsConfirmDialog() {
    - Connect to Google Fonts + { __( 'Connect to Google Fonts' ) } { __( From 626f7c7b186ca2ed9b426edd8da9158769a79dea Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:41:01 +1100 Subject: [PATCH 18/31] Background image support: Fix issue with background position if keyboard entry happens before mouse interaction (#59050) Co-authored-by: andrewserong Co-authored-by: tellthemachines --- packages/block-editor/src/hooks/background.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 80b6090eca2190..1564d9ea9a81ca 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -374,11 +374,14 @@ function backgroundSizeHelpText( value ) { } export const coordsToBackgroundPosition = ( value ) => { - if ( ! value || isNaN( value.x ) || isNaN( value.y ) ) { + if ( ! value || ( isNaN( value.x ) && isNaN( value.y ) ) ) { return undefined; } - return `${ value.x * 100 }% ${ value.y * 100 }%`; + const x = isNaN( value.x ) ? 0.5 : value.x; + const y = isNaN( value.y ) ? 0.5 : value.y; + + return `${ x * 100 }% ${ y * 100 }%`; }; export const backgroundPositionToCoords = ( value ) => { From ac607f4c1c30d975c4519ecca6db3a2b8bcb3c76 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 15 Feb 2024 16:46:09 +1100 Subject: [PATCH 19/31] Backports from Core, the changes in https://github.com/WordPress/wordpress-develop/pull/6108 (#59049) This is required to sync with https://github.com/WordPress/wordpress-develop/pull/5655 Co-authored-by: ramonjd Co-authored-by: andrewserong --- ...global-styles-revisions-controller-6-5.php | 9 ++++ ...lobal-styles-revisions-controller-test.php | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php b/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php index e7b2ac85f6e525..74fa31d53199e0 100644 --- a/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php +++ b/lib/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php @@ -69,6 +69,15 @@ public function get_item( $request ) { return $revision; } + if ( (int) $parent->ID !== (int) $revision->post_parent ) { + return new WP_Error( + 'rest_revision_parent_id_mismatch', + /* translators: %d: A post id. */ + sprintf( __( 'The revision does not belong to the specified parent with id of "%d"' ), $parent->ID ), + array( 'status' => 404 ) + ); + } + $response = $this->prepare_item_for_response( $revision, $request ); return rest_ensure_response( $response ); } diff --git a/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php b/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php index 2ae53f9338389e..30780c50f18635 100644 --- a/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php +++ b/phpunit/class-gutenberg-rest-global-styles-revisions-controller-test.php @@ -19,6 +19,11 @@ class Gutenberg_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_RES */ protected static $global_styles_id; + /** + * @var int + */ + protected static $global_styles_id_2; + /** * @var array */ @@ -56,6 +61,20 @@ public static function wpSetupBeforeClass( $factory ) { ) ); + // This creates another global styles post for the current theme. + self::$global_styles_id_2 = $factory->post->create( + array( + 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', + 'post_status' => 'publish', + 'post_title' => __( 'Custom Styles', 'default' ), + 'post_type' => 'wp_global_styles', + 'post_name' => 'wp-global-styles-tt1-blocks-revisions-2', + 'tax_input' => array( + 'wp_theme' => 'tt1-blocks', + ), + ) + ); + // Update post to create a new revisions. $new_styles_post = array( 'ID' => self::$global_styles_id, @@ -189,6 +208,36 @@ public function test_register_routes() { ); } + /** + * @ticket 59810 + * + * @covers WP_REST_Global_Styles_Controller::get_items + */ + public function test_get_item_valid_parent_id() { + wp_set_current_user( self::$admin_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/' . $this->revision_1_id ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertSame( self::$global_styles_id, $data['parent'], "The returned revision's id should match the parent id." ); + $this->check_get_revision_response( $data, $this->revision_1 ); + } + + /** + * @ticket 59810 + * + * @covers WP_REST_Global_Styles_Controller::get_items + */ + public function test_get_item_invalid_parent_id() { + wp_set_current_user( self::$admin_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id_2 . '/revisions/' . $this->revision_1_id ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_revision_parent_id_mismatch', $response, 404 ); + + $expected_message = 'The revision does not belong to the specified parent with id of "' . self::$global_styles_id_2 . '"'; + $this->assertSame( $expected_message, $response->as_error()->get_error_messages()[0], 'The message must contain the correct parent ID.' ); + } + /** * Utility function to check the items in WP_REST_Global_Styles_Controller::get_items * against the expected values. From a988b90e855211f9094a1c2abe3218bb6ea8d61c Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 15 Feb 2024 19:49:43 +1300 Subject: [PATCH 20/31] Patterns: Check we are not within a pattern instance before running block deletion rules (#59044) * Check we are not within a pattern instance before running block deletion rules on overridden blocks * Make comment more explanatory Co-authored-by: glendaviesnz Co-authored-by: talldan --- packages/block-editor/src/store/private-actions.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/block-editor/src/store/private-actions.js b/packages/block-editor/src/store/private-actions.js index d1db598c8c8e65..ae0a06152fb933 100644 --- a/packages/block-editor/src/store/private-actions.js +++ b/packages/block-editor/src/store/private-actions.js @@ -140,6 +140,15 @@ export const privateRemoveBlocks = } if ( rules[ 'bindings/core/pattern-overrides' ] ) { + const parentPatternBlocks = + select.getBlockParentsByBlockName( + clientId, + 'core/block' + ); + // We only need to run this check when editing the original pattern, not pattern instances. + if ( parentPatternBlocks?.length > 0 ) { + continue; + } const blockAttributes = select.getBlockAttributes( clientId ); if ( From e3f3c3d80b0bb792d0056428a38d1cd68fdddc96 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 15 Feb 2024 12:22:44 +0400 Subject: [PATCH 21/31] Relocate 'ErrorBoundary' component unit test folders (#59031) Co-authored-by: Mamaduka Co-authored-by: draganescu --- .../{ => error-boundary}/test/error-boundary.js | 12 +++++++----- .../{ => error-boundary}/test/error-boundary.js | 12 +++++++----- .../{ => error-boundary}/test/error-boundary.js | 12 +++++++----- 3 files changed, 21 insertions(+), 15 deletions(-) rename packages/customize-widgets/src/components/{ => error-boundary}/test/error-boundary.js (94%) rename packages/edit-site/src/components/{ => error-boundary}/test/error-boundary.js (94%) rename packages/edit-widgets/src/components/{ => error-boundary}/test/error-boundary.js (94%) diff --git a/packages/customize-widgets/src/components/test/error-boundary.js b/packages/customize-widgets/src/components/error-boundary/test/error-boundary.js similarity index 94% rename from packages/customize-widgets/src/components/test/error-boundary.js rename to packages/customize-widgets/src/components/error-boundary/test/error-boundary.js index 7b9977e10f1315..27ec4c80419676 100644 --- a/packages/customize-widgets/src/components/test/error-boundary.js +++ b/packages/customize-widgets/src/components/error-boundary/test/error-boundary.js @@ -1,15 +1,17 @@ +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + /** * WordPress dependencies */ import * as wpHooks from '@wordpress/hooks'; + /** * Internal dependencies */ -import ErrorBoundary from '../error-boundary'; -/** - * External dependencies - */ -import { render } from '@testing-library/react'; +import ErrorBoundary from '../index'; const theError = new Error( 'Kaboom' ); diff --git a/packages/edit-site/src/components/test/error-boundary.js b/packages/edit-site/src/components/error-boundary/test/error-boundary.js similarity index 94% rename from packages/edit-site/src/components/test/error-boundary.js rename to packages/edit-site/src/components/error-boundary/test/error-boundary.js index 7b9977e10f1315..27ec4c80419676 100644 --- a/packages/edit-site/src/components/test/error-boundary.js +++ b/packages/edit-site/src/components/error-boundary/test/error-boundary.js @@ -1,15 +1,17 @@ +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + /** * WordPress dependencies */ import * as wpHooks from '@wordpress/hooks'; + /** * Internal dependencies */ -import ErrorBoundary from '../error-boundary'; -/** - * External dependencies - */ -import { render } from '@testing-library/react'; +import ErrorBoundary from '../index'; const theError = new Error( 'Kaboom' ); diff --git a/packages/edit-widgets/src/components/test/error-boundary.js b/packages/edit-widgets/src/components/error-boundary/test/error-boundary.js similarity index 94% rename from packages/edit-widgets/src/components/test/error-boundary.js rename to packages/edit-widgets/src/components/error-boundary/test/error-boundary.js index 7b9977e10f1315..27ec4c80419676 100644 --- a/packages/edit-widgets/src/components/test/error-boundary.js +++ b/packages/edit-widgets/src/components/error-boundary/test/error-boundary.js @@ -1,15 +1,17 @@ +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + /** * WordPress dependencies */ import * as wpHooks from '@wordpress/hooks'; + /** * Internal dependencies */ -import ErrorBoundary from '../error-boundary'; -/** - * External dependencies - */ -import { render } from '@testing-library/react'; +import ErrorBoundary from '../index'; const theError = new Error( 'Kaboom' ); From 3242ca9e80b587ce52f9217133fc6b729565e64b Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 15 Feb 2024 10:46:13 +0100 Subject: [PATCH 22/31] Editor: Do not open list view by default on mobile (#59016) Co-authored-by: youknowriad Co-authored-by: ntsekouras Co-authored-by: aaronrobertshaw Co-authored-by: andrewserong Co-authored-by: t-hamano --- packages/edit-post/src/index.js | 3 +++ packages/edit-site/src/store/private-actions.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index a46a0c7592c689..7875ae1a3f443b 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -49,6 +49,7 @@ export function initializeEditor( settings, initialEdits ) { + const isMediumOrBigger = window.matchMedia( '(min-width: 782px)' ).matches; const target = document.getElementById( id ); const root = createRoot( target ); @@ -76,7 +77,9 @@ export function initializeEditor( // Check if the block list view should be open by default. // If `distractionFree` mode is enabled, the block list view should not be open. + // This behavior is disabled for small viewports. if ( + isMediumOrBigger && select( preferencesStore ).get( 'core', 'showListViewByDefault' ) && ! select( preferencesStore ).get( 'core', 'distractionFree' ) ) { diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js index 930e89c6254102..fd23903a6a05e4 100644 --- a/packages/edit-site/src/store/private-actions.js +++ b/packages/edit-site/src/store/private-actions.js @@ -22,6 +22,8 @@ import { TEMPLATE_POST_TYPE } from '../utils/constants'; export const setCanvasMode = ( mode ) => ( { registry, dispatch } ) => { + const isMediumOrBigger = + window.matchMedia( '(min-width: 782px)' ).matches; registry.dispatch( blockEditorStore ).__unstableSetEditorMode( 'edit' ); dispatch( { type: 'SET_CANVAS_MODE', @@ -29,7 +31,9 @@ export const setCanvasMode = } ); // Check if the block list view should be open by default. // If `distractionFree` mode is enabled, the block list view should not be open. + // This behavior is disabled for small viewports. if ( + isMediumOrBigger && mode === 'edit' && registry .select( preferencesStore ) From 7853838bd1ae79b4e8939c4bfb8dc34f1ee9c631 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+c4rl0sbr4v0@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:02:03 +0100 Subject: [PATCH 23/31] Refactor to use string instead of an object (#59030) Co-authored-by: c4rl0sbr4v0 Co-authored-by: gziolo --- .../interactivity-api/class-wp-interactivity-api.php | 4 ++-- .../plugins/interactive-blocks/router-navigate/render.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php index 3bfade3aa4aa75..1fc757accf6f6b 100644 --- a/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php +++ b/lib/compat/wordpress-6.5/interactivity-api/class-wp-interactivity-api.php @@ -800,14 +800,14 @@ public function print_router_loading_and_screen_reader_markup() { echo <<
    HTML; diff --git a/packages/e2e-tests/plugins/interactive-blocks/router-navigate/render.php b/packages/e2e-tests/plugins/interactive-blocks/router-navigate/render.php index 4abcee3de2c399..0b8e6e1012d1a4 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/router-navigate/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/router-navigate/render.php @@ -18,7 +18,7 @@ ?>

    From fd75a20f511c02bc9e12a6f2331c9b06aa665b27 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Thu, 15 Feb 2024 19:43:09 +0900 Subject: [PATCH 24/31] Block JSON schema: Add `viewScriptModule` field (#59060) Co-authored-by: t-hamano Co-authored-by: c4rl0sbr4v0 --- schemas/json/block.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/schemas/json/block.json b/schemas/json/block.json index 7ac384db798ca5..299327a96a64b8 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -798,6 +798,20 @@ } ] }, + "viewScriptModule": { + "description": "Block type frontend script module definition. It will be enqueued only when viewing the content on the front of the site.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, "editorStyle": { "description": "Block type editor style definition. It will only be enqueued in the context of the editor.", "oneOf": [ From 0e9f2549eab14fd9116576db031e4388b0d4f602 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 15 Feb 2024 12:09:22 +0100 Subject: [PATCH 25/31] Editor: Hide template part and post content blocks in some site editor contexts (#58928) Co-authored-by: youknowriad Co-authored-by: aaronrobertshaw Co-authored-by: ramonjd --- packages/edit-post/src/index.js | 43 ---------- .../editor/src/components/provider/index.js | 3 + .../provider/use-hide-bocks-from-inserter.js | 81 +++++++++++++++++++ 3 files changed, 84 insertions(+), 43 deletions(-) create mode 100644 packages/editor/src/components/provider/use-hide-bocks-from-inserter.js diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 7875ae1a3f443b..5e6b40cacd44ab 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -9,7 +9,6 @@ import { import deprecated from '@wordpress/deprecated'; import { createRoot } from '@wordpress/element'; import { dispatch, select } from '@wordpress/data'; -import { addFilter } from '@wordpress/hooks'; import { store as preferencesStore } from '@wordpress/preferences'; import { registerLegacyWidgetBlock, @@ -95,48 +94,6 @@ export function initializeEditor( } ); } - /* - * Prevent adding template part in the post editor. - * Only add the filter when the post editor is initialized, not imported. - * Also only add the filter(s) after registerCoreBlocks() - * so that common filters in the block library are not overwritten. - */ - addFilter( - 'blockEditor.__unstableCanInsertBlockType', - 'removeTemplatePartsFromInserter', - ( canInsert, blockType ) => { - if ( blockType.name === 'core/template-part' ) { - return false; - } - return canInsert; - } - ); - - /* - * Prevent adding post content block (except in query block) in the post editor. - * Only add the filter when the post editor is initialized, not imported. - * Also only add the filter(s) after registerCoreBlocks() - * so that common filters in the block library are not overwritten. - */ - addFilter( - 'blockEditor.__unstableCanInsertBlockType', - 'removePostContentFromInserter', - ( - canInsert, - blockType, - rootClientId, - { getBlockParentsByBlockName } - ) => { - if ( blockType.name === 'core/post-content' ) { - return ( - getBlockParentsByBlockName( rootClientId, 'core/query' ) - .length > 0 - ); - } - return canInsert; - } - ); - // Show a console log warning if the browser is not in Standards rendering mode. const documentMode = document.compatMode === 'CSS1Compat' ? 'Standards' : 'Quirks'; diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index e1db657cd7251b..9f0d25e1576353 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -23,6 +23,7 @@ import useBlockEditorSettings from './use-block-editor-settings'; import { unlock } from '../../lock-unlock'; import DisableNonPageContentBlocks from './disable-non-page-content-blocks'; import NavigationBlockEditingMode from './navigation-block-editing-mode'; +import { useHideBlocksFromInserter } from './use-hide-bocks-from-inserter'; const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { PatternsMenuItems } = unlock( editPatternsPrivateApis ); @@ -229,6 +230,8 @@ export const ExperimentalEditorProvider = withRegistryProvider( setRenderingMode( settings.defaultRenderingMode ?? 'post-only' ); }, [ settings.defaultRenderingMode, setRenderingMode ] ); + useHideBlocksFromInserter( post.type ); + if ( ! isReady ) { return null; } diff --git a/packages/editor/src/components/provider/use-hide-bocks-from-inserter.js b/packages/editor/src/components/provider/use-hide-bocks-from-inserter.js new file mode 100644 index 00000000000000..c3f9158602f9b0 --- /dev/null +++ b/packages/editor/src/components/provider/use-hide-bocks-from-inserter.js @@ -0,0 +1,81 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { addFilter, removeFilter } from '@wordpress/hooks'; + +// These post types are "structural" block lists. +// We should be allowed to use +// the post content and template parts blocks within them. +const POST_TYPES_ALLOWING_POST_CONTENT_TEMPLATE_PART = [ + 'wp_block', + 'wp_template', + 'wp_template_part', +]; + +/** + * In some specific contexts, + * the template part and post content blocks need to be hidden. + * + * @param {string} postType Post Type + */ +export function useHideBlocksFromInserter( postType ) { + useEffect( () => { + /* + * Prevent adding template part in the editor. + */ + addFilter( + 'blockEditor.__unstableCanInsertBlockType', + 'removeTemplatePartsFromInserter', + ( canInsert, blockType ) => { + if ( + ! POST_TYPES_ALLOWING_POST_CONTENT_TEMPLATE_PART.includes( + postType + ) && + blockType.name === 'core/template-part' + ) { + return false; + } + return canInsert; + } + ); + + /* + * Prevent adding post content block (except in query block) in the editor. + */ + addFilter( + 'blockEditor.__unstableCanInsertBlockType', + 'removePostContentFromInserter', + ( + canInsert, + blockType, + rootClientId, + { getBlockParentsByBlockName } + ) => { + if ( + ! POST_TYPES_ALLOWING_POST_CONTENT_TEMPLATE_PART.includes( + postType + ) && + blockType.name === 'core/post-content' + ) { + return ( + getBlockParentsByBlockName( rootClientId, 'core/query' ) + .length > 0 + ); + } + return canInsert; + } + ); + + return () => { + removeFilter( + 'blockEditor.__unstableCanInsertBlockType', + 'removeTemplatePartsFromInserter' + ); + removeFilter( + 'blockEditor.__unstableCanInsertBlockType', + 'removePostContentFromInserter' + ); + }; + }, [ postType ] ); +} From fdfa26ac637f1ced10bef06aaa4c2ff3489cc7a6 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 15 Feb 2024 12:13:06 +0100 Subject: [PATCH 26/31] Site Editor: Fix navigation on mobile web (#59014) Co-authored-by: youknowriad Co-authored-by: t-hamano Co-authored-by: ntsekouras Co-authored-by: jameskoster Co-authored-by: colorful-tones Co-authored-by: annezazu --- .../edit-site/src/components/layout/index.js | 77 +++++++++++-------- .../edit-site/src/components/layout/router.js | 33 +++++++- .../src/components/layout/style.scss | 7 ++ .../src/components/page-patterns/style.scss | 6 ++ .../sidebar-navigation-screen-pages/index.js | 16 ++-- .../edit-site/src/components/sidebar/index.js | 10 ++- 6 files changed, 108 insertions(+), 41 deletions(-) diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js index 163d4fe6e938ff..65dfb71949a7f5 100644 --- a/packages/edit-site/src/components/layout/index.js +++ b/packages/edit-site/src/components/layout/index.js @@ -251,47 +251,64 @@ export default function Layout() { The NavigableRegion must always be rendered and not use `inert` otherwise `useNavigateRegions` will fail. */ } - - - { canvasMode === 'view' && ( - - - - ) } - - + { ( ! isMobileViewport || + ( isMobileViewport && ! areas.mobile ) ) && ( + + + { canvasMode === 'view' && ( + + + + ) } + + + ) } - { areas.content && canvasMode !== 'edit' && ( + { isMobileViewport && areas.mobile && (
    - { areas.content } + { areas.mobile }
    ) } - { areas.preview && ( + { ! isMobileViewport && + areas.content && + canvasMode !== 'edit' && ( +
    + { areas.content } +
    + ) } + + { ! isMobileViewport && areas.preview && (
    { canvasResizer } { !! canvasSize.width && ( diff --git a/packages/edit-site/src/components/layout/router.js b/packages/edit-site/src/components/layout/router.js index aeb124bf76fe5f..02f7e7b25594ae 100644 --- a/packages/edit-site/src/components/layout/router.js +++ b/packages/edit-site/src/components/layout/router.js @@ -23,13 +23,21 @@ const { useLocation } = unlock( routerPrivateApis ); export default function useLayoutAreas() { const isSiteEditorLoading = useIsSiteEditorLoading(); const { params } = useLocation(); - const { postType, postId, path, layout, isCustom } = params ?? {}; + const { postType, postId, path, layout, isCustom, canvas } = params ?? {}; + + // Note: Since "sidebar" is not yet supported here, + // returning undefined from "mobile" means show the sidebar. + // Regular page if ( path === '/page' ) { return { areas: { content: undefined, preview: , + mobile: + canvas === 'edit' ? ( + + ) : undefined, }, widths: { content: undefined, @@ -63,6 +71,10 @@ export default function useLayoutAreas() { return { areas: { preview: , + mobile: + canvas === 'edit' ? ( + + ) : undefined, }, }; } @@ -79,6 +91,11 @@ export default function useLayoutAreas() { preview: isListLayout && ( ), + mobile: ( + + ), }, widths: { content: isListLayout ? 380 : undefined, @@ -98,6 +115,11 @@ export default function useLayoutAreas() { preview: isListLayout && ( ), + mobile: ( + + ), }, widths: { content: isListLayout ? 380 : undefined, @@ -110,12 +132,19 @@ export default function useLayoutAreas() { return { areas: { content: , + mobile: , }, }; } // Fallback shows the home page preview return { - areas: { preview: }, + areas: { + preview: , + mobile: + canvas === 'edit' ? ( + + ) : undefined, + }, }; } diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss index 9be0b001ed9e25..ad33768989a81b 100644 --- a/packages/edit-site/src/components/layout/style.scss +++ b/packages/edit-site/src/components/layout/style.scss @@ -83,6 +83,12 @@ flex-direction: column; } +.edit-site-layout__mobile { + position: relative; + width: 100%; + z-index: z-index(".edit-site-layout__canvas-container"); +} + .edit-site-layout__canvas-container { position: relative; flex-grow: 1; @@ -147,6 +153,7 @@ } // This shouldn't be necessary (we should have a way to say that a skeletton is relative +.edit-site-layout__mobile .interface-interface-skeleton, .edit-site-layout__canvas .interface-interface-skeleton, .edit-site-template-pages-preview .interface-interface-skeleton { position: relative !important; diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index 2dc9326e4d29be..d4afcaea186476 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -43,6 +43,12 @@ } .edit-site-page-patterns-dataviews { + margin-top: 60px; + + @include break-medium { + margin-top: 0; + } + .page-patterns-preview-field { display: flex; flex-direction: column; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-pages/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-pages/index.js index 82fc6d0fa2412b..7641ac1fe97a0d 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-pages/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-pages/index.js @@ -14,6 +14,7 @@ import { decodeEntities } from '@wordpress/html-entities'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { layout, page, home, verse, plus } from '@wordpress/icons'; import { useSelect } from '@wordpress/data'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -42,6 +43,7 @@ const PageItem = ( { postType = 'page', postId, ...props } ) => { }; export default function SidebarNavigationScreenPages() { + const isMobileViewport = useViewportMatch( 'medium', '<' ); const { records: pages, isResolving: isLoadingPages } = useEntityRecords( 'postType', 'page', @@ -220,12 +222,14 @@ export default function SidebarNavigationScreenPages() { ) ) } - - { __( 'Manage all pages' ) } - + { ! isMobileViewport && ( + + { __( 'Manage all pages' ) } + + ) } } /> diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js index 19cd55ae6fac2d..1890d3afcf7ba0 100644 --- a/packages/edit-site/src/components/sidebar/index.js +++ b/packages/edit-site/src/components/sidebar/index.js @@ -12,6 +12,7 @@ import { __experimentalNavigatorScreen as NavigatorScreen, } from '@wordpress/components'; import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -50,6 +51,7 @@ function SidebarScreenWrapper( { className, ...props } ) { function SidebarScreens() { useSyncPathWithURL(); + const isMobileViewport = useViewportMatch( 'medium', '<' ); return ( <> @@ -77,9 +79,11 @@ function SidebarScreens() { - - - + { ! isMobileViewport && ( + + + + ) } From c32dd340bf8c371277049881c42f5e92d3586c88 Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+c4rl0sbr4v0@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:43:17 +0100 Subject: [PATCH 27/31] Fix wrong commas (#59029) Co-authored-by: c4rl0sbr4v0 Co-authored-by: gziolo --- packages/block-library/src/search/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index 5688e2871a2463..c368c2ab03dbf8 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -188,7 +188,7 @@ function render_block_core_search( $attributes ) { ) ); $form_directives = ' - data-wp-interactive=\'"core/search"\'' + data-wp-interactive="core/search"' . $form_context . 'data-wp-class--wp-block-search__searchfield-hidden="!context.isSearchInputVisible" data-wp-on--keydown="actions.handleSearchKeydown" From decaae66b0e4ca173b1bbb1ee7a059819074a918 Mon Sep 17 00:00:00 2001 From: Marin Atanasov <8436925+tyxla@users.noreply.github.com> Date: Thu, 15 Feb 2024 13:53:15 +0200 Subject: [PATCH 28/31] Components: Add sleep() before all Tab() to fix flaky tests (#59012) Co-authored-by: tyxla Co-authored-by: Mamaduka --- .../src/alignment-matrix-control/test/index.tsx | 4 +++- .../src/circular-option-picker/test/index.tsx | 5 ++++- .../src/composite/legacy/test/index.tsx | 15 +++++++++++++++ .../src/custom-select-control-v2/test/index.tsx | 11 ++++++++++- .../src/dropdown-menu-v2/test/index.tsx | 5 ++++- packages/components/src/tab-panel/test/index.tsx | 9 ++++++++- packages/components/src/tabs/test/index.tsx | 15 +++++++++++++++ .../src/toggle-group-control/test/index.tsx | 4 ++++ packages/components/src/tooltip/test/index.tsx | 5 +++++ 9 files changed, 68 insertions(+), 5 deletions(-) diff --git a/packages/components/src/alignment-matrix-control/test/index.tsx b/packages/components/src/alignment-matrix-control/test/index.tsx index a820b69b26c8ff..57c13f8c92eee0 100644 --- a/packages/components/src/alignment-matrix-control/test/index.tsx +++ b/packages/components/src/alignment-matrix-control/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor, within } from '@testing-library/react'; -import { press, click } from '@ariakit/test'; +import { press, click, sleep } from '@ariakit/test'; /** * Internal dependencies @@ -39,6 +39,7 @@ describe( 'AlignmentMatrixControl', () => { it( 'should be centered by default', async () => { await renderAndInitCompositeStore( ); + await sleep(); await press.Tab(); expect( getCell( 'center center' ) ).toHaveFocus(); @@ -109,6 +110,7 @@ describe( 'AlignmentMatrixControl', () => { ); + await sleep(); await press.Tab(); await press[ keyRef ](); diff --git a/packages/components/src/circular-option-picker/test/index.tsx b/packages/components/src/circular-option-picker/test/index.tsx index 0a168432629f8f..ab3042784eab62 100644 --- a/packages/components/src/circular-option-picker/test/index.tsx +++ b/packages/components/src/circular-option-picker/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen } from '@testing-library/react'; -import { press } from '@ariakit/test'; +import { press, sleep } from '@ariakit/test'; /** * Internal dependencies @@ -78,6 +78,7 @@ describe( 'CircularOptionPicker', () => { /> ); + await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); @@ -97,6 +98,7 @@ describe( 'CircularOptionPicker', () => { /> ); + await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); @@ -116,6 +118,7 @@ describe( 'CircularOptionPicker', () => { /> ); + await sleep(); await press.Tab(); expect( getOption( 'Option One' ) ).toHaveFocus(); await press.ArrowRight(); diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index 49b1915a6a14fb..315532a8b50869 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -178,10 +178,13 @@ describe.each( [ ); renderAndValidate( ); + await sleep(); await press.Tab(); expect( screen.getByText( 'Before' ) ).toHaveFocus(); + await sleep(); await press.Tab(); expect( screen.getByText( 'Item 1' ) ).toHaveFocus(); + await sleep(); await press.Tab(); expect( screen.getByText( 'After' ) ).toHaveFocus(); await press.ShiftTab(); @@ -210,6 +213,7 @@ describe.each( [ expect( item2 ).toBeDisabled(); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -239,6 +243,7 @@ describe.each( [ expect( item2 ).toBeEnabled(); expect( item2 ).toHaveAttribute( 'aria-disabled', 'true' ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -318,6 +323,7 @@ describe.each( [ test( 'All directions work with no orientation', async () => { const { item1, item2, item3 } = useOneDimensionalTest(); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -355,6 +361,7 @@ describe.each( [ orientation: 'horizontal', } ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -384,6 +391,7 @@ describe.each( [ orientation: 'vertical', } ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press( next ); @@ -413,6 +421,7 @@ describe.each( [ loop: true, } ); + await sleep(); await press.Tab(); expect( item1 ).toHaveFocus(); await press.ArrowDown(); @@ -435,6 +444,7 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemB2, itemC1, itemC3 } = useTwoDimensionalTest(); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowUp(); @@ -471,6 +481,7 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = useTwoDimensionalTest( { loop: true } ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( next ); @@ -495,6 +506,7 @@ describe.each( [ const { itemA1, itemA2, itemA3, itemB1, itemC1, itemC3 } = useTwoDimensionalTest( { wrap: true } ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( next ); @@ -527,6 +539,7 @@ describe.each( [ wrap: true, } ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press( previous ); @@ -542,6 +555,7 @@ describe.each( [ test( 'Focus shifts if vertical neighbour unavailable when shift enabled', async () => { const { itemA1, itemB1, itemB2, itemC1 } = useShiftTest( true ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowDown(); @@ -563,6 +577,7 @@ describe.each( [ test( 'Focus does not shift if vertical neighbour unavailable when shift not enabled', async () => { const { itemA1, itemB1, itemB2 } = useShiftTest( false ); + await sleep(); await press.Tab(); expect( itemA1 ).toHaveFocus(); await press.ArrowDown(); diff --git a/packages/components/src/custom-select-control-v2/test/index.tsx b/packages/components/src/custom-select-control-v2/test/index.tsx index cdc93205fba98e..f8d9a4ebd61959 100644 --- a/packages/components/src/custom-select-control-v2/test/index.tsx +++ b/packages/components/src/custom-select-control-v2/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen } from '@testing-library/react'; -import { click, press, type } from '@ariakit/test'; +import { click, press, sleep, type } from '@ariakit/test'; /** * WordPress dependencies @@ -106,6 +106,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -315,6 +316,7 @@ describe( 'With Legacy Props', () => { ); + await sleep(); await press.Tab(); expect( screen.getByRole( 'combobox', { @@ -336,6 +338,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -361,6 +364,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -381,6 +385,7 @@ describe( 'With Legacy Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -544,6 +549,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -572,6 +578,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); @@ -597,6 +604,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); await press.Enter(); expect( @@ -617,6 +625,7 @@ describe( 'With Default Props', () => { expanded: false, } ); + await sleep(); await press.Tab(); expect( currentSelectedItem ).toHaveFocus(); diff --git a/packages/components/src/dropdown-menu-v2/test/index.tsx b/packages/components/src/dropdown-menu-v2/test/index.tsx index f58639a545a056..10351d6cb588aa 100644 --- a/packages/components/src/dropdown-menu-v2/test/index.tsx +++ b/packages/components/src/dropdown-menu-v2/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor } from '@testing-library/react'; -import { press, click, hover, type } from '@ariakit/test'; +import { press, click, hover, sleep, type } from '@ariakit/test'; /** * WordPress dependencies @@ -123,6 +123,7 @@ describe( 'DropdownMenu', () => { } ); // Move focus on the toggle + await sleep(); await press.Tab(); expect( toggleButton ).toHaveFocus(); @@ -153,6 +154,7 @@ describe( 'DropdownMenu', () => { } ); // Move focus on the toggle + await sleep(); await press.Tab(); expect( toggleButton ).toHaveFocus(); @@ -908,6 +910,7 @@ describe( 'DropdownMenu', () => { // The outer button can be focused by pressing tab. Doing so will cause // the DropdownMenu to close. + await sleep(); await press.Tab(); expect( outerButton ).toBeInTheDocument(); expect( screen.queryByRole( 'menu' ) ).not.toBeInTheDocument(); diff --git a/packages/components/src/tab-panel/test/index.tsx b/packages/components/src/tab-panel/test/index.tsx index 28dd1a81e9e84f..65827040f1e34c 100644 --- a/packages/components/src/tab-panel/test/index.tsx +++ b/packages/components/src/tab-panel/test/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { render, screen, waitFor } from '@testing-library/react'; -import { press, hover, click } from '@ariakit/test'; +import { press, hover, click, sleep } from '@ariakit/test'; /** * WordPress dependencies @@ -155,6 +155,7 @@ describe.each( [ // Tab to focus the tablist. Make sure alpha is focused, and that the // corresponding tooltip is shown. expect( screen.queryByText( 'Alpha' ) ).not.toBeInTheDocument(); + await sleep(); await press.Tab(); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); expect( screen.getByText( 'Alpha' ) ).toBeInTheDocument(); @@ -626,6 +627,7 @@ describe.each( [ // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -663,6 +665,7 @@ describe.each( [ // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -700,6 +703,7 @@ describe.each( [ // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -795,6 +799,7 @@ describe.each( [ // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); expect( mockOnSelect ).toHaveBeenCalledTimes( 1 ); @@ -836,6 +841,7 @@ describe.each( [ // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) @@ -843,6 +849,7 @@ describe.each( [ // Because all other tabs should have `tabindex=-1`, pressing Tab // should NOT move the focus to the next tab, which is Beta. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Beta' } ) diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index 7262a53702c31d..96d17f59df99e8 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -194,12 +194,14 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveFocus(); // By default the tabpanel should receive focus + await sleep(); await press.Tab(); expect( selectedTabPanel ).toHaveFocus(); } ); @@ -229,12 +231,14 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) ).toHaveFocus(); // Because the alpha tabpanel is set to `focusable: false`, pressing // the Tab key should focus the button, not the tabpanel + await sleep(); await press.Tab(); expect( alphaButton ).toHaveFocus(); } ); @@ -305,6 +309,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -338,6 +343,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -373,6 +379,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); @@ -472,6 +479,7 @@ describe( 'Tabs', () => { // Tab to focus the tablist. Make sure Alpha is focused. expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); expect( await getSelectedTab() ).not.toHaveFocus(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveFocus(); // Confirm onSelect has not been re-called @@ -514,6 +522,7 @@ describe( 'Tabs', () => { // Tab should initially focus the first tab in the tablist, which // is Alpha. + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tab', { name: 'Alpha' } ) @@ -522,6 +531,7 @@ describe( 'Tabs', () => { // Because all other tabs should have `tabindex=-1`, pressing Tab // should NOT move the focus to the next tab, which is Beta. // Instead, focus should go to the currently selected tabpanel (alpha). + await sleep(); await press.Tab(); expect( await screen.findByRole( 'tabpanel', { @@ -832,6 +842,7 @@ describe( 'Tabs', () => { expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' ); // Move focus to the tablist, make sure alpha is focused. + await sleep(); await press.Tab(); expect( screen.getByRole( 'tab', { name: 'Alpha' } ) @@ -1238,7 +1249,9 @@ describe( 'Tabs', () => { ); // Tab key should focus the currently selected tab, which is Beta. + await sleep(); await press.Tab(); + await sleep(); await press.Tab(); expect( await getSelectedTab() ).toHaveTextContent( 'Beta' @@ -1273,6 +1286,7 @@ describe( 'Tabs', () => { ).toHaveFocus(); // Press tab, move focus back to the tablist + await sleep(); await press.Tab(); const betaTab = screen.getByRole( 'tab', { @@ -1294,6 +1308,7 @@ describe( 'Tabs', () => { it( 'should automatically select a newly focused tab', async () => { render( ); + await sleep(); await press.Tab(); // Tab key should focus the currently selected tab, which is Beta. diff --git a/packages/components/src/toggle-group-control/test/index.tsx b/packages/components/src/toggle-group-control/test/index.tsx index a8835bc66c58d4..c607d384b0e407 100644 --- a/packages/components/src/toggle-group-control/test/index.tsx +++ b/packages/components/src/toggle-group-control/test/index.tsx @@ -334,9 +334,11 @@ describe.each( [ name: 'R', } ); + await sleep(); await press.Tab(); expect( rigas ).toHaveFocus(); + await sleep(); await press.Tab(); // When in controlled mode, there is an additional "Reset" button. @@ -392,6 +394,7 @@ describe.each( [ ); + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { @@ -400,6 +403,7 @@ describe.each( [ } ) ).toHaveFocus(); + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { diff --git a/packages/components/src/tooltip/test/index.tsx b/packages/components/src/tooltip/test/index.tsx index 85e29f5f3809bc..66734b1737053c 100644 --- a/packages/components/src/tooltip/test/index.tsx +++ b/packages/components/src/tooltip/test/index.tsx @@ -67,6 +67,7 @@ describe( 'Tooltip', () => { screen.getByRole( 'button', { name: 'Second button' } ) ).toBeVisible(); + await sleep(); await press.Tab(); expectTooltipToBeHidden(); @@ -134,6 +135,7 @@ describe( 'Tooltip', () => { ); // Focus the anchor, tooltip should show + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { name: 'Tooltip anchor' } ) @@ -141,6 +143,7 @@ describe( 'Tooltip', () => { await waitExpectTooltipToShow(); // Focus the other button, tooltip should hide + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { name: 'Focus me' } ) @@ -166,11 +169,13 @@ describe( 'Tooltip', () => { expect( anchor ).toHaveAttribute( 'aria-disabled', 'true' ); // Focus anchor, tooltip should show + await sleep(); await press.Tab(); expect( anchor ).toHaveFocus(); await waitExpectTooltipToShow(); // Focus another button, tooltip should hide + await sleep(); await press.Tab(); expect( screen.getByRole( 'button', { From acd79ef3d55ca1b96bcfb908e1a10576a2797e9d Mon Sep 17 00:00:00 2001 From: Carlos Bravo <37012961+c4rl0sbr4v0@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:59:46 +0100 Subject: [PATCH 29/31] Refactor to use string instead of an object (#59034) Co-authored-by: c4rl0sbr4v0 Co-authored-by: SantosGuillamot --- .../block-templates/render.php.mustache | 2 +- .../interactive-blocks/directive-bind/render.php | 2 +- .../interactive-blocks/directive-context/view.js | 2 +- .../interactive-blocks/directive-each/render.php | 4 ++-- .../interactive-blocks/directive-each/view.js | 2 +- .../interactive-blocks/directive-init/render.php | 2 +- .../interactive-blocks/directive-key/render.php | 2 +- .../interactive-blocks/directive-key/view.js | 2 +- .../directive-on-document/render.php | 4 ++-- .../directive-on-window/render.php | 2 +- .../interactive-blocks/directive-on/render.php | 2 +- .../directive-priorities/render.php | 4 ++-- .../interactive-blocks/directive-run/render.php | 4 ++-- .../interactive-blocks/directive-run/view.js | 2 +- .../directive-style/render.php | 2 +- .../interactive-blocks/directive-text/render.php | 2 +- .../directive-watch/render.php | 2 +- .../negation-operator/render.php | 2 +- .../interactive-blocks/store-tag/render.php | 2 +- .../interactive-blocks/tovdom-islands/render.php | 16 ++++++++-------- .../plugins/interactive-blocks/tovdom/render.php | 2 +- .../interactive-blocks/with-scope/render.php | 2 +- packages/interactivity/docs/1-getting-started.md | 2 +- packages/interactivity/src/hooks.tsx | 4 ++-- packages/interactivity/src/store.ts | 2 +- 25 files changed, 37 insertions(+), 37 deletions(-) diff --git a/packages/create-block-interactive-template/block-templates/render.php.mustache b/packages/create-block-interactive-template/block-templates/render.php.mustache index 960da619f790a4..bb8f843d80a77e 100644 --- a/packages/create-block-interactive-template/block-templates/render.php.mustache +++ b/packages/create-block-interactive-template/block-templates/render.php.mustache @@ -17,7 +17,7 @@ $unique_id = wp_unique_id( 'p-' );
    - data-wp-interactive='{ "namespace": "{{namespace}}" }' + data-wp-interactive="{{namespace}}" data-wp-context='{ "isOpen": false }' data-wp-watch="callbacks.logIsOpen" > diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php index 24e3c9343c1157..1511a8b428de10 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-bind/render.php @@ -8,7 +8,7 @@ wp_enqueue_script_module( 'directive-bind-view' ); ?> -