From eb2ded55041342339e9c5032e964b3b3a79fc2dd Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 3 Oct 2022 21:20:29 +1300 Subject: [PATCH 01/23] Quote block: stop slash inserter popup showing in citation (#44634) --- packages/block-library/src/quote/block.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json index 3ceaf0fcf3e038..adb9fddca78731 100644 --- a/packages/block-library/src/quote/block.json +++ b/packages/block-library/src/quote/block.json @@ -29,7 +29,6 @@ }, "supports": { "anchor": true, - "__experimentalSlashInserter": true, "__experimentalOnEnter": true, "typography": { "fontSize": true, From 9d1fe960a283707748ffc1b141b8f9c8ac10afb4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Mon, 3 Oct 2022 10:09:58 +0400 Subject: [PATCH 02/23] Query Loop: Fix condition for displaying 'parents' control (#44630) The logical NOT here is a typo. The Query Loop block should display the filter for hierarchical post types; unless the `allowedControls` list omits the control filter. --- .../block-library/src/query/edit/inspector-controls/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/block-library/src/query/edit/inspector-controls/index.js b/packages/block-library/src/query/edit/inspector-controls/index.js index 33e77def49352d..2579696e443e51 100644 --- a/packages/block-library/src/query/edit/inspector-controls/index.js +++ b/packages/block-library/src/query/edit/inspector-controls/index.js @@ -241,10 +241,7 @@ export default function QueryInspectorControls( { ) } { isPostTypeHierarchical && - ! isControlAllowed( - allowedControls, - 'parents' - ) && ( + isControlAllowed( allowedControls, 'parents' ) && ( !! parents?.length } label={ __( 'Parents' ) } From 7e9fd398d0adca41b3ac941d327299c926dd9f49 Mon Sep 17 00:00:00 2001 From: Michal Date: Fri, 30 Sep 2022 17:50:38 -0500 Subject: [PATCH 03/23] Hide the Classic block in the Site Editor (#44554) * Hide the classic block using a filter * Update the comment wording --- packages/edit-site/src/index.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index b3c4b5dc161037..a09133c956f957 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -18,6 +18,7 @@ import { store as preferencesStore } from '@wordpress/preferences'; import { __ } from '@wordpress/i18n'; import { store as viewportStore } from '@wordpress/viewport'; import { getQueryArgs } from '@wordpress/url'; +import { addFilter } from '@wordpress/hooks'; /** * Internal dependencies @@ -51,6 +52,26 @@ export function reinitializeEditor( target, settings ) { return; } + /* + * Prevent adding the Clasic block in the site editor. + * Only add the filter when the site editor is initialized, not imported. + * Also only add the filter(s) after registerCoreBlocks() + * so that common filters in the block library are not overwritten. + * + * This usage here is inspired by previous usage of the filter in the post editor: + * https://github.com/WordPress/gutenberg/pull/37157 + */ + addFilter( + 'blockEditor.__unstableCanInsertBlockType', + 'removeClassicBlockFromInserter', + ( canInsert, blockType ) => { + if ( blockType.name === 'core/freeform' ) { + return false; + } + return canInsert; + } + ); + // This will be a no-op if the target doesn't have any React nodes. unmountComponentAtNode( target ); const reboot = reinitializeEditor.bind( null, target, settings ); From 1bbc3ab4013c696146e1c0269914a55121de0cd3 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 30 Sep 2022 14:04:06 +0800 Subject: [PATCH 04/23] Fix navigation block console error (#44594) --- .../src/navigation/edit/index.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 751d33b9b501f4..6cb773e60107bd 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -282,16 +282,18 @@ function Navigation( { hasResolvedNavigationMenus && ! hasUncontrolledInnerBlocks; - if ( isPlaceholder && ! ref ) { - /** - * this fallback only displays (both in editor and on front) - * the list of pages block if no menu is available as a fallback. - * We don't want the fallback to request a save, - * nor to be undoable, hence we mark it non persistent. - */ - __unstableMarkNextChangeAsNotPersistent(); - replaceInnerBlocks( clientId, [ createBlock( 'core/page-list' ) ] ); - } + useEffect( () => { + if ( isPlaceholder && ! ref ) { + /** + * this fallback only displays (both in editor and on front) + * the list of pages block if no menu is available as a fallback. + * We don't want the fallback to request a save, + * nor to be undoable, hence we mark it non persistent. + */ + __unstableMarkNextChangeAsNotPersistent(); + replaceInnerBlocks( clientId, [ createBlock( 'core/page-list' ) ] ); + } + }, [ clientId, isPlaceholder, ref ] ); const isEntityAvailable = ! isNavigationMenuMissing && isNavigationMenuResolved; From 50bb90d156e337115bcea1152523bd3b317373d0 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 30 Sep 2022 13:18:31 +1300 Subject: [PATCH 05/23] Remove the invalid spacing preset setting (#44555) --- lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php index 5c1639d3d2ce6b..c4b6935142dc3a 100644 --- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php @@ -1151,15 +1151,6 @@ protected static function get_property_value( $styles, $path, $theme_json = null 'classes' => array(), 'properties' => array( 'padding', 'margin' ), ), - array( - 'path' => array( 'spacing', 'spacingScale' ), - 'prevent_override' => false, - 'use_default_names' => true, - 'value_key' => 'size', - 'css_vars' => '--wp--preset--spacing--$slug', - 'classes' => array(), - 'properties' => array( 'padding', 'margin' ), - ), ); /** From 2159bbb9c16f7b8b7d993b0990fd5a2f92e03879 Mon Sep 17 00:00:00 2001 From: Nick Diego Date: Thu, 29 Sep 2022 10:39:26 -0500 Subject: [PATCH 06/23] Add box-sizing. (#44580) --- packages/block-library/src/code/style.scss | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/code/style.scss b/packages/block-library/src/code/style.scss index e8d3b07cd034fa..670a4f7f1ef4c8 100644 --- a/packages/block-library/src/code/style.scss +++ b/packages/block-library/src/code/style.scss @@ -1,8 +1,13 @@ -// Provide a minimum of overflow handling and ensure the code markup inherits -// the font-family set on pre. -.wp-block-code code { - display: block; - font-family: inherit; - overflow-wrap: break-word; - white-space: pre-wrap; +.wp-block-code { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; + + // Provide a minimum of overflow handling and ensure the code markup inherits + // the font-family set on pre. + code { + display: block; + font-family: inherit; + overflow-wrap: break-word; + white-space: pre-wrap; + } } From 14d650026d7972fe371ad20ec9a5f625acbcb10c Mon Sep 17 00:00:00 2001 From: Nick Diego Date: Thu, 29 Sep 2022 08:18:40 -0500 Subject: [PATCH 07/23] Remove border from Global Styles previews (#44556) * Remove border from global styles preview. * Fix spacing. * Add missing semicolon Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> --- packages/edit-site/src/components/global-styles/preview.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/preview.js b/packages/edit-site/src/components/global-styles/preview.js index a424da638da2b5..0fd3e578cfaa0e 100644 --- a/packages/edit-site/src/components/global-styles/preview.js +++ b/packages/edit-site/src/components/global-styles/preview.js @@ -79,13 +79,13 @@ const StylesPreview = ( { label, isFocused } ) => { ) .slice( 0, 2 ); - // Reset leaked styles from WP common.css and remove main content layout padding. + // Reset leaked styles from WP common.css and remove main content layout padding and border. const editorStyles = useMemo( () => { if ( styles ) { return [ ...styles, { - css: 'body{min-width: 0;padding: 0;}', + css: 'body{min-width: 0;padding: 0;border: none;}', isGlobalStyles: true, }, ]; From ad37bdd3c1e643d776869dd5427a14761bbd4057 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 29 Sep 2022 16:36:17 +1300 Subject: [PATCH 08/23] Spacing presets: Modify the styling of the input controls when in unlinked mode in order to better differentiate sides (#44141) --- .../components/spacing-sizes-control/index.js | 18 +++++-- .../spacing-input-control.js | 15 +++--- .../spacing-sizes-control/style.scss | 52 ++++++++++--------- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js index ba379713b4bcc5..7b016e7a08ee72 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/index.js +++ b/packages/block-editor/src/components/spacing-sizes-control/index.js @@ -1,9 +1,14 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ import { useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { __experimentalText as Text } from '@wordpress/components'; +import { BaseControl } from '@wordpress/components'; /** * Internal dependencies @@ -68,8 +73,15 @@ export default function SpacingSizesControl( { }; return ( -
- { label } +
+ + { label } + { ! hasOneSide && ( ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js index c0d2573b42e807..cf9a663fe1fa1e 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js @@ -9,12 +9,12 @@ import classnames from 'classnames'; import { useState, useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { + BaseControl, Button, RangeControl, CustomSelectControl, __experimentalUnitControl as UnitControl, __experimentalHStack as HStack, - __experimentalText as Text, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, } from '@wordpress/components'; @@ -167,21 +167,21 @@ export default function SpacingInputControl( { <> { side !== 'all' && ( - + { LABELS[ side ] } - + { showHint && ( - + { currentValueHint } - + ) } ) } { side === 'all' && showHint && ( - + { currentValueHint } - + ) } { ! disableCustomSpacingSizes && ( @@ -256,6 +256,7 @@ export default function SpacingInputControl( { marks={ marks } label={ ariaLabel } hideLabelFromVision={ true } + __nextHasNoMarginBottom={ true } /> ) } { ! showRangeControl && ! showCustomValueControl && ( diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss index 448a21cc0ac1ba..27b83a9ba5ca81 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/style.scss +++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss @@ -1,7 +1,8 @@ .tools-panel-item-spacing { display: grid; grid-template-columns: auto 1fr auto; - grid-row-gap: $grid-unit-05; + align-items: center; + grid-template-rows: 25px auto; } .component-spacing-sizes-control { @@ -17,21 +18,34 @@ align-self: center; } + .components-base-control__label { + margin-bottom: 0; + height: $grid-unit-20; + } + .components-spacing-sizes-control__side-labels { grid-column: 1 / 1; - min-height: 30px; justify-content: left; + height: $grid-unit-20; + margin-top: $grid-unit-15; + } + + .components-spacing-sizes-control__side-label { + grid-column: 1 / 1; + justify-self: left; + margin-bottom: 0; } - .components-spacing-sizes-control__hint-single { - margin-top: 0; - margin-left: 0; + &.is-unlinked { + .components-range-control.components-spacing-sizes-control__range-control { + margin-top: $grid-unit-15; + } } .components-spacing-sizes-control__hint-single, .components-spacing-sizes-control__hint-all { color: $gray-700; - font-size: 12px; + margin-bottom: 0; } .components-spacing-sizes-control__hint-all { @@ -47,6 +61,11 @@ grid-row: 1 / 1; justify-self: end; padding: 0; + &.is-small.has-icon { + padding: 0; + min-width: $icon-size; + height: $grid-unit-20; + } } .component-spacing-sizes-control__linked-button ~ .components-spacing-sizes-control__custom-toggle-all { @@ -56,13 +75,11 @@ .components-spacing-sizes-control__custom-toggle-single { grid-column: 3 / 3; justify-self: end; - } - - .components-spacing-sizes-control__custom-toggle-all, - .components-spacing-sizes-control__custom-toggle-single { &.is-small.has-icon { padding: 0; min-width: $icon-size; + height: $grid-unit-20; + margin-top: $grid-unit-15; } } @@ -75,7 +92,6 @@ .components-spacing-sizes-control__custom-value-range { grid-column: span 2; margin-left: $grid-unit-10; - padding-right: $grid-unit-10; height: 30px; } @@ -85,12 +101,7 @@ .components-spacing-sizes-control__range-control { grid-column: span 3; - padding-right: $grid-unit-10; - height: 30px; - } - - .components-range-control__wrapper { - margin-bottom: 0; + height: 40px; } .components-range-control__mark { @@ -112,13 +123,6 @@ z-index: 3; } - .components-spacing-sizes-control__side-label { - margin-right: $grid-unit-05; - grid-column: 1 / 1; - justify-self: left; - font-size: 12px; - } - .components-spacing-sizes-control__custom-select-control { grid-column: span 3; } From 4a0fbe0222d5965721931adb5e3a9294966cf25e Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Tue, 27 Sep 2022 10:08:23 +1000 Subject: [PATCH 09/23] [TypeScript] Preserve the generic signature of getEntityRecord and getEntityRecords through currying (#44453) Declare GetEntityRecord as a *callable interface* that is callable as usually, but also ships another signature without the state argument. This works around a TypeScript limitation that doesn't allow currying generic functions: ```ts type CurriedState = F extends ( state: any, ...args: infer P ) => infer R ? ( ...args: P ) => R : F; type Selector = ( state: any, kind: K, key: K extends string ? 'string value' : false ) => K; type BadlyInferredSignature = CurriedState< Selector > // BadlyInferredSignature evaluates to: // (kind: string number, key: false | "string value") => string number ``` The signature without the state parameter shipped as CurriedSignature is used in the return value of `select( coreStore )`. See https://github.com/WordPress/gutenberg/pull/41578 for more details. This commit includes a docgen update to add support for typecasting selectors --- packages/core-data/src/selectors.ts | 92 +++++++++++++++++++-- packages/data/src/types.ts | 65 +++++++++++++-- packages/docgen/lib/get-type-annotation.js | 10 ++- packages/docgen/test/get-type-annotation.js | 77 +++++++++-------- 4 files changed, 195 insertions(+), 49 deletions(-) diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 79309d84fb98b1..4151a94824acb5 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -221,6 +221,55 @@ export function getEntityConfig( return find( state.entities.config, { kind, name } ); } +/** + * GetEntityRecord is declared as a *callable interface* with + * two signatures to work around the fact that TypeScript doesn't + * allow currying generic functions: + * + * ```ts + * type CurriedState = F extends ( state: any, ...args: infer P ) => infer R + * ? ( ...args: P ) => R + * : F; + * type Selector = ( + * state: any, + * kind: K, + * key: K extends string ? 'string value' : false + * ) => K; + * type BadlyInferredSignature = CurriedState< Selector > + * // BadlyInferredSignature evaluates to: + * // (kind: string number, key: false | "string value") => string number + * ``` + * + * The signature without the state parameter shipped as CurriedSignature + * is used in the return value of `select( coreStore )`. + * + * See https://github.com/WordPress/gutenberg/pull/41578 for more details. + */ +export interface GetEntityRecord { + < + EntityRecord extends + | ET.EntityRecord< any > + | Partial< ET.EntityRecord< any > > + >( + state: State, + kind: string, + name: string, + key: EntityRecordKey, + query?: GetRecordsHttpQuery + ): EntityRecord | undefined; + + CurriedSignature: < + EntityRecord extends + | ET.EntityRecord< any > + | Partial< ET.EntityRecord< any > > + >( + kind: string, + name: string, + key: EntityRecordKey, + query?: GetRecordsHttpQuery + ) => EntityRecord | undefined; +} + /** * Returns the Entity's record object by key. Returns `null` if the value is not * yet received, undefined if the value entity is known to not exist, or the @@ -236,7 +285,7 @@ export function getEntityConfig( * @return Record. */ export const getEntityRecord = createSelector( - < + ( < EntityRecord extends | ET.EntityRecord< any > | Partial< ET.EntityRecord< any > > @@ -279,7 +328,7 @@ export const getEntityRecord = createSelector( } return item; - }, + } ) as GetEntityRecord, ( state: State, kind, name, recordId, query ) => { const context = query?.context ?? 'default'; return [ @@ -301,7 +350,7 @@ export const getEntityRecord = createSelector( ] ), ]; } -); +) as GetEntityRecord; /** * Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity records from the API if the entity record isn't available in the local state. @@ -414,6 +463,37 @@ export function hasEntityRecords( return Array.isArray( getEntityRecords( state, kind, name, query ) ); } +/** + * GetEntityRecord is declared as a *callable interface* with + * two signatures to work around the fact that TypeScript doesn't + * allow currying generic functions. + * + * @see GetEntityRecord + * @see https://github.com/WordPress/gutenberg/pull/41578 + */ +export interface GetEntityRecords { + < + EntityRecord extends + | ET.EntityRecord< any > + | Partial< ET.EntityRecord< any > > + >( + state: State, + kind: string, + name: string, + query?: GetRecordsHttpQuery + ): EntityRecord[] | null; + + CurriedSignature: < + EntityRecord extends + | ET.EntityRecord< any > + | Partial< ET.EntityRecord< any > > + >( + kind: string, + name: string, + query?: GetRecordsHttpQuery + ) => EntityRecord[] | null; +} + /** * Returns the Entity's records. * @@ -425,7 +505,7 @@ export function hasEntityRecords( * * @return Records. */ -export const getEntityRecords = < +export const getEntityRecords = ( < EntityRecord extends | ET.EntityRecord< any > | Partial< ET.EntityRecord< any > > @@ -433,7 +513,7 @@ export const getEntityRecords = < state: State, kind: string, name: string, - query?: GetRecordsHttpQuery + query: GetRecordsHttpQuery ): EntityRecord[] | null => { // Queried data state is prepopulated for all known entities. If this is not // assigned for the given parameters, then it is known to not exist. @@ -446,7 +526,7 @@ export const getEntityRecords = < return null; } return getQueriedItems( queriedState, query ); -}; +} ) as GetEntityRecords; type DirtyEntityRecord = { title: string; diff --git a/packages/data/src/types.ts b/packages/data/src/types.ts index 0e1b9d7618957e..fe7d9061d3c5d8 100644 --- a/packages/data/src/types.ts +++ b/packages/data/src/types.ts @@ -77,22 +77,75 @@ export type CurriedSelectorsOf< S > = S extends StoreDescriptor< : never; /** - * Removes the first argument from a function + * Removes the first argument from a function. * - * This is designed to remove the `state` parameter from + * By default, it removes the `state` parameter from * registered selectors since that argument is supplied * by the editor when calling `select(…)`. * * For functions with no arguments, which some selectors * are free to define, returns the original function. + * + * It is possible to manually provide a custom curried signature + * and avoid the automatic inference. When the + * F generic argument passed to this helper extends the + * SelectorWithCustomCurrySignature type, the F['CurriedSignature'] + * property is used verbatim. + * + * This is useful because TypeScript does not correctly remove + * arguments from complex function signatures constrained by + * interdependent generic parameters. + * For more context, see https://github.com/WordPress/gutenberg/pull/41578 */ -export type CurriedState< F > = F extends ( - state: any, - ...args: infer P -) => infer R +type CurriedState< F > = F extends SelectorWithCustomCurrySignature + ? F[ 'CurriedSignature' ] + : F extends ( state: any, ...args: infer P ) => infer R ? ( ...args: P ) => R : F; +/** + * Utility to manually specify curried selector signatures. + * + * It comes handy when TypeScript can't automatically produce the + * correct curried function signature. For example: + * + * ```ts + * type BadlyInferredSignature = CurriedState< + * ( + * state: any, + * kind: K, + * key: K extends string ? 'one value' : false + * ) => K + * > + * // BadlyInferredSignature evaluates to: + * // (kind: string number, key: false "one value") => string number + * ``` + * + * With SelectorWithCustomCurrySignature, we can provide a custom + * signature and avoid relying on TypeScript inference: + * ```ts + * interface MySelectorSignature extends SelectorWithCustomCurrySignature { + * ( + * state: any, + * kind: K, + * key: K extends string ? 'one value' : false + * ): K; + * + * CurriedSignature: ( + * kind: K, + * key: K extends string ? 'one value' : false + * ): K; + * } + * type CorrectlyInferredSignature = CurriedState + * // (kind: K, key: K extends string ? 'one value' : false): K; + * + * For even more context, see https://github.com/WordPress/gutenberg/pull/41578 + * ``` + */ +export interface SelectorWithCustomCurrySignature { + CurriedSignature: Function; +} + export interface DataRegistry { register: ( store: StoreDescriptor< any > ) => void; } diff --git a/packages/docgen/lib/get-type-annotation.js b/packages/docgen/lib/get-type-annotation.js index c03c3104fd040c..6bf65cc27465a3 100644 --- a/packages/docgen/lib/get-type-annotation.js +++ b/packages/docgen/lib/get-type-annotation.js @@ -405,18 +405,24 @@ function unwrapWrappedSelectors( token ) { return token; } + if ( babelTypes.isTSAsExpression( token ) ) { + // ( ( state, queryId ) => state.queries[ queryId ] ) as any; + // \------------------------------------------------/ CallExpression.expression + return unwrapWrappedSelectors( token.expression ); + } + if ( babelTypes.isCallExpression( token ) ) { // createSelector( ( state, queryId ) => state.queries[ queryId ] ); // \--------------------------------------------/ CallExpression.arguments[0] if ( token.callee.name === 'createSelector' ) { - return token.arguments[ 0 ]; + return unwrapWrappedSelectors( token.arguments[ 0 ] ); } // createRegistrySelector( ( selector ) => ( state, queryId ) => select( 'core/queries' ).get( queryId ) ); // \-----------------------------------------------------------/ CallExpression.arguments[0].body // \---------------------------------------------------------------------------/ CallExpression.arguments[0] if ( token.callee.name === 'createRegistrySelector' ) { - return token.arguments[ 0 ].body; + return unwrapWrappedSelectors( token.arguments[ 0 ].body ); } } } diff --git a/packages/docgen/test/get-type-annotation.js b/packages/docgen/test/get-type-annotation.js index 13ff923f229906..fdf114dfd1f674 100644 --- a/packages/docgen/test/get-type-annotation.js +++ b/packages/docgen/test/get-type-annotation.js @@ -394,46 +394,53 @@ describe( 'Type annotations', () => { } ); describe( 'statically-wrapped function exceptions', () => { - it( 'should find types for inner function with `createSelector`', () => { - const { tokens } = engine( - 'test.ts', - `/** - * Returns the number of things - * - * @param state - stores all the things - */ - export const getCount = createSelector( ( state: string[] ) => state.length ); - ` + const getStateArgType = ( code ) => { + const { tokens } = engine( 'test.ts', code ); + return getTypeAnnotation( + { tag: 'param', name: 'state' }, + tokens[ 0 ], + 0 ); + }; - expect( - getTypeAnnotation( - { tag: 'param', name: 'state' }, - tokens[ 0 ], - 0 - ) - ).toBe( 'string[]' ); + const docString = `/** + * Returns the number of things + * + * @param state - stores all the things + */`; + it( 'should find types for a typecasted function', () => { + const code = `${ docString } + export const getCount = ( state: string[] ) => state.length; + `; + expect( getStateArgType( code ) ).toBe( 'string[]' ); } ); - it( 'should find types for inner function with `createRegistrySelector`', () => { - const { tokens } = engine( - 'test.ts', - `/** - * Returns the number of things - * - * @param state - stores all the things - */ - export const getCount = createRegistrySelector( ( select ) => ( state: number ) => state ); - ` - ); + it( 'should find types for a doubly typecasted function', () => { + const code = `${ docString } + export const getCount = ( ( state: string[] ) => state.length ) as any as any; + `; + expect( getStateArgType( code ) ).toBe( 'string[]' ); + } ); - expect( - getTypeAnnotation( - { tag: 'param', name: 'state' }, - tokens[ 0 ], - 0 - ) - ).toBe( 'number' ); + it( 'should find types for inner function with `createSelector`', () => { + const code = `${ docString } + export const getCount = createSelector( ( state: string[] ) => state.length ); + `; + expect( getStateArgType( code ) ).toBe( 'string[]' ); + } ); + + it( 'should find types for inner typecasted function with `createSelector`', () => { + const code = `${ docString } + export const getCount = createSelector( (( state: string[] ) => state.length) as any ); + `; + expect( getStateArgType( code ) ).toBe( 'string[]' ); + } ); + + it( 'should find types for inner function with `createRegistrySelector`', () => { + const code = `${ docString } + export const getCount = createRegistrySelector( ( select ) => ( state: number ) => state ); + `; + expect( getStateArgType( code ) ).toBe( 'number' ); } ); } ); } ); From 4b92996290a52a9591da57df3553637b5a3061dd Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Wed, 28 Sep 2022 09:29:00 +0900 Subject: [PATCH 10/23] Theme.json: fix some outline properties doesn't work properly on the editor (#44504) --- .../global-styles/use-global-styles-output.js | 23 +++++++++++-------- .../style-engine/src/styles/outline/index.ts | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index 189fb3ebbb2586..8aa61a829a9634 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -434,9 +434,14 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => { const pickStyleKeys = ( treeToPickFrom ) => pickBy( treeToPickFrom, ( value, key ) => - [ 'border', 'color', 'spacing', 'typography', 'filter' ].includes( - key - ) + [ + 'border', + 'color', + 'spacing', + 'typography', + 'filter', + 'outline', + ].includes( key ) ); // Top-level. @@ -605,12 +610,12 @@ export const toStyles = ( } if ( useRootPaddingAlign ) { - ruleset += `padding-right: 0; padding-left: 0; padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom) } - .has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } - .has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; } - .has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); } - .has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; } - .has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } + ruleset += `padding-right: 0; padding-left: 0; padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom) } + .has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } + .has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; } + .has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); } + .has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; } + .has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } .has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0;`; } diff --git a/packages/style-engine/src/styles/outline/index.ts b/packages/style-engine/src/styles/outline/index.ts index c6c3101fa90272..4526b31f1fa40f 100644 --- a/packages/style-engine/src/styles/outline/index.ts +++ b/packages/style-engine/src/styles/outline/index.ts @@ -22,7 +22,7 @@ const offset = { style: Style, options: StyleOptions, path: string[] = [ 'outline', 'offset' ], - ruleKey: string = 'outlineColor' + ruleKey: string = 'outlineOffset' ): GeneratedCSSRule[] => { return generateRule( style, options, path, ruleKey ); }, From af3f84e5006613b29a413560522f5bf03151b0c2 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 27 Sep 2022 16:36:31 -0700 Subject: [PATCH 11/23] Add style-engine to gutenberg tsconfig references (#44516) --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index be2b2c31082485..7618b05fc70f7d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,6 +33,7 @@ { "path": "packages/project-management-automation" }, { "path": "packages/react-i18n" }, { "path": "packages/report-flaky-tests" }, + { "path": "packages/style-engine" }, { "path": "packages/token-list" }, { "path": "packages/url" }, { "path": "packages/warning" }, From 9aaf066644035ceb5340e7d284196ec19534f65e Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 28 Sep 2022 12:30:34 +0300 Subject: [PATCH 12/23] [Block Library - Query Loop]: Rename Query Loop variations `allowControls` to `allowedControls` (#44523) --- packages/block-library/src/query/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/query/utils.js b/packages/block-library/src/query/utils.js index d6848724b82874..276d7b21638173 100644 --- a/packages/block-library/src/query/utils.js +++ b/packages/block-library/src/query/utils.js @@ -162,7 +162,7 @@ export function useAllowedControls( attributes ) { select( blocksStore ).getActiveBlockVariation( queryLoopName, attributes - )?.allowControls, + )?.allowedControls, [ attributes ] ); From 32de2fb42ba3581e315b307513fb384124099ae6 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 27 Sep 2022 18:31:22 +1000 Subject: [PATCH 13/23] Post Featured Image: Fix borders after addition of overlay feature (#44286) --- .../src/post-featured-image/block.json | 2 +- .../src/post-featured-image/editor.scss | 142 +++++++++--------- .../src/post-featured-image/index.php | 42 +++--- .../src/post-featured-image/overlay.js | 31 ++-- 4 files changed, 106 insertions(+), 111 deletions(-) diff --git a/packages/block-library/src/post-featured-image/block.json b/packages/block-library/src/post-featured-image/block.json index 1072c7576d6454..40f51cffa06e75 100644 --- a/packages/block-library/src/post-featured-image/block.json +++ b/packages/block-library/src/post-featured-image/block.json @@ -62,7 +62,7 @@ "color": true, "radius": true, "width": true, - "__experimentalSelector": "img, .block-editor-media-placeholder", + "__experimentalSelector": "img, .block-editor-media-placeholder, .wp-block-post-featured-image__overlay", "__experimentalSkipSerialization": true, "__experimentalDefaultControls": { "color": true, diff --git a/packages/block-library/src/post-featured-image/editor.scss b/packages/block-library/src/post-featured-image/editor.scss index c52d14f44f7a6c..37c29160055d85 100644 --- a/packages/block-library/src/post-featured-image/editor.scss +++ b/packages/block-library/src/post-featured-image/editor.scss @@ -6,87 +6,85 @@ backdrop-filter: none; // Removes background blur so the overlay's actual color is visible. } - &.wp-block-post-featured-image { - // Style the placeholder. - .wp-block-post-featured-image__placeholder, - .components-placeholder { - justify-content: center; - align-items: center; - padding: 0; + // Style the placeholder. + .wp-block-post-featured-image__placeholder, + .components-placeholder { + justify-content: center; + align-items: center; + padding: 0; - // Hide the upload button, as it's also available in the media library. - .components-form-file-upload { - display: none; - } + // Hide the upload button, as it's also available in the media library. + .components-form-file-upload { + display: none; + } - // Style the upload button. - .components-button.components-button { - padding: 0; - display: flex; - justify-content: center; - align-items: center; - width: $grid-unit-60; - height: $grid-unit-60; - border-radius: 50%; - position: relative; - background: var(--wp-admin-theme-color); - border-color: var(--wp-admin-theme-color); - border-style: solid; - color: $white; + // Style the upload button. + .components-button { + padding: 0; + display: flex; + justify-content: center; + align-items: center; + width: $grid-unit-60; + height: $grid-unit-60; + border-radius: 50%; + position: relative; + background: var(--wp-admin-theme-color); + border-color: var(--wp-admin-theme-color); + border-style: solid; + color: $white; - > svg { - color: inherit; - } + > svg { + color: inherit; } + } - // Show default placeholder height when not resized. - min-height: 200px; - - // The following override the default placeholder styles that remove - // its border so that a user selection for border color or width displays - // a visual border. - &:where(.has-border-color) { - border-style: solid; - } - &:where([style*="border-top-color"]) { - border-top-style: solid; - } - &:where([style*="border-right-color"]) { - border-right-style: solid; - } - &:where([style*="border-bottom-color"]) { - border-bottom-style: solid; - } - &:where([style*="border-left-color"]) { - border-left-style: solid; - } + // Show default placeholder height when not resized. + min-height: 200px; - &:where([style*="border-width"]) { - border-style: solid; - } - &:where([style*="border-top-width"]) { - border-top-style: solid; - } - &:where([style*="border-right-width"]) { - border-right-style: solid; - } - &:where([style*="border-bottom-width"]) { - border-bottom-style: solid; - } - &:where([style*="border-left-width"]) { - border-left-style: solid; - } + // The following override the default placeholder styles that remove + // its border so that a user selection for border color or width displays + // a visual border. + &:where(.has-border-color) { + border-style: solid; + } + &:where([style*="border-top-color"]) { + border-top-style: solid; + } + &:where([style*="border-right-color"]) { + border-right-style: solid; + } + &:where([style*="border-bottom-color"]) { + border-bottom-style: solid; + } + &:where([style*="border-left-color"]) { + border-left-style: solid; } - // Provide a minimum size for the placeholder when resized. - // Note, this should be as small as we can afford it, and exists only - // to ensure there's room for the upload button. - &[style*="height"] .components-placeholder { - min-height: $grid-unit-60; - min-width: $grid-unit-60; - height: 100%; - width: 100%; + &:where([style*="border-width"]) { + border-style: solid; + } + &:where([style*="border-top-width"]) { + border-top-style: solid; + } + &:where([style*="border-right-width"]) { + border-right-style: solid; + } + &:where([style*="border-bottom-width"]) { + border-bottom-style: solid; } + &:where([style*="border-left-width"]) { + border-left-style: solid; + } + } + + // Provide a minimum size for the placeholder when resized. + // Note, this should be as small as we can afford it, and exists only + // to ensure there's room for the upload button. + &[style*="height"] .components-placeholder { + min-height: $grid-unit-60; + min-width: $grid-unit-60; + height: 100%; + width: 100%; } } diff --git a/packages/block-library/src/post-featured-image/index.php b/packages/block-library/src/post-featured-image/index.php index 595f58cbfe95e7..de5683b297027a 100644 --- a/packages/block-library/src/post-featured-image/index.php +++ b/packages/block-library/src/post-featured-image/index.php @@ -83,16 +83,25 @@ function get_block_core_post_featured_image_overlay_element_markup( $attributes $has_custom_gradient = isset( $attributes['customGradient'] ) && $attributes['customGradient']; $has_solid_overlay = isset( $attributes['overlayColor'] ) && $attributes['overlayColor']; $has_custom_overlay = isset( $attributes['customOverlayColor'] ) && $attributes['customOverlayColor']; - $class_names = array( - 'wp-block-post-featured-image__overlay', - ); - $styles_properties = array(); + $class_names = array( 'wp-block-post-featured-image__overlay' ); + $styles = array(); if ( ! $has_dim_background ) { return ''; } - // Generate required classes for the element. + // Apply border classes and styles. + $border_attributes = get_block_core_post_featured_image_border_attributes( $attributes ); + + if ( ! empty( $border_attributes['class'] ) ) { + $class_names[] = $border_attributes['class']; + } + + if ( ! empty( $border_attributes['style'] ) ) { + $styles[] = $border_attributes['style']; + } + + // Apply overlay and gradient classes. if ( $has_dim_background ) { $class_names[] = 'has-background-dim'; $class_names[] = "has-background-dim-{$attributes['dimRatio']}"; @@ -110,35 +119,20 @@ function get_block_core_post_featured_image_overlay_element_markup( $attributes $class_names[] = "has-{$attributes['gradient']}-gradient-background"; } - // Generate required CSS properties and their values. - if ( ! empty( $attributes['style']['border']['radius'] ) ) { - $styles_properties['border-radius'] = $attributes['style']['border']['radius']; - } - - if ( ! empty( $attributes['style']['border']['width'] ) ) { - $styles_properties['border-width'] = $attributes['style']['border']['width']; - } - + // Apply background styles. if ( $has_custom_gradient ) { - $styles_properties['background-image'] = $attributes['customGradient']; + $styles[] = sprintf( 'background-image: %s;', $attributes['customGradient'] ); } if ( $has_custom_overlay ) { - $styles_properties['background-color'] = $attributes['customOverlayColor']; - } - - $styles = ''; - - foreach ( $styles_properties as $style_attribute => $style_attribute_value ) { - $styles .= "{$style_attribute}: $style_attribute_value; "; + $styles[] = sprintf( 'background-color: %s;', $attributes['customOverlayColor'] ); } return sprintf( '', esc_attr( implode( ' ', $class_names ) ), - esc_attr( trim( $styles ) ) + esc_attr( safecss_filter_attr( implode( ' ', $styles ) ) ) ); - } /** diff --git a/packages/block-library/src/post-featured-image/overlay.js b/packages/block-library/src/post-featured-image/overlay.js index 572cef64801e76..f577978b9a3c93 100644 --- a/packages/block-library/src/post-featured-image/overlay.js +++ b/packages/block-library/src/post-featured-image/overlay.js @@ -47,20 +47,23 @@ const Overlay = ( { return ( <> -