From 6c9bbce95728203215a81ee34b70c7a1a2490917 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:06:15 +1100 Subject: [PATCH 1/3] Background image support: Try adding background position controls --- packages/block-editor/src/hooks/background.js | 81 +++++++++++++++++++ .../src/styles/background/index.ts | 19 ++++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index d093d3da55c8d..5843526ef47e6 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -18,6 +18,7 @@ import { __experimentalVStack as VStack, DropZone, FlexItem, + FocalPointPicker, MenuItem, VisuallyHidden, __experimentalItemGroup as ItemGroup, @@ -367,6 +368,64 @@ function backgroundSizeHelpText( value ) { return __( 'Set a fixed width.' ); } +const coordsToBackgroundPosition = ( value ) => { + if ( ! value ) { + return undefined; + } + + if ( value.x === 0 && value.y === 0 ) { + return 'left top'; + } + + if ( value.x === 0 && value.y === 1 ) { + return 'left bottom'; + } + + if ( value.x === 1 && value.y === 0 ) { + return 'right top'; + } + + if ( value.x === 1 && value.y === 1 ) { + return 'right bottom'; + } + + if ( value.x === 0.5 && value.y === 0.5 ) { + return 'center'; + } + + return `${ value.x * 100 }% ${ value.y * 100 }%`; +}; + +const backgroundPositionToCoords = ( value ) => { + if ( ! value ) { + return { x: 0.5, y: 0.5 }; + } + + if ( value === 'left top' ) { + return { x: 0, y: 0 }; + } + + if ( value === 'left bottom' ) { + return { x: 0, y: 1 }; + } + + if ( value === 'right top' ) { + return { x: 1, y: 0 }; + } + + if ( value === 'right bottom' ) { + return { x: 1, y: 1 }; + } + + if ( value === 'center' ) { + return { x: 0.5, y: 0.5 }; + } + + const [ x, y ] = value.split( ' ' ).map( ( v ) => parseFloat( v ) / 100 ); + + return { x, y }; +}; + function BackgroundSizePanelItem( { clientId, isShownByDefault, @@ -446,6 +505,18 @@ function BackgroundSizePanelItem( { } ); }; + const updateBackgroundPosition = ( next ) => { + setAttributes( { + style: cleanEmptyObject( { + ...style, + background: { + ...style?.background, + backgroundPosition: coordsToBackgroundPosition( next ), + }, + } ), + } ); + }; + const toggleIsRepeated = () => { setAttributes( { style: cleanEmptyObject( { @@ -471,6 +542,16 @@ function BackgroundSizePanelItem( { resetAllFilter={ resetAllFilter } panelId={ clientId } > + { + return generateRule( + style, + options, + [ 'background', 'backgroundPosition' ], + 'backgroundPosition' + ); + }, +}; + const backgroundSize = { name: 'backgroundSize', generate: ( style: Style, options: StyleOptions ) => { @@ -89,4 +101,9 @@ const backgroundSize = { }, }; -export default [ backgroundImage, backgroundRepeat, backgroundSize ]; +export default [ + backgroundImage, + backgroundRepeat, + backgroundPosition, + backgroundSize, +]; From d9d87ba23f4604f1e7520ddc6e50f1fbce36f395 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:44:40 +1100 Subject: [PATCH 2/3] Fix reset and hasValue logic, add tests, update label --- packages/block-editor/src/hooks/background.js | 63 +++++-------------- .../block-editor/src/hooks/test/background.js | 50 +++++++++++++++ .../src/styles/background/index.ts | 14 ++--- packages/style-engine/src/test/index.js | 6 ++ 4 files changed, 78 insertions(+), 55 deletions(-) create mode 100644 packages/block-editor/src/hooks/test/background.js diff --git a/packages/block-editor/src/hooks/background.js b/packages/block-editor/src/hooks/background.js index 5843526ef47e6..9524564b487ec 100644 --- a/packages/block-editor/src/hooks/background.js +++ b/packages/block-editor/src/hooks/background.js @@ -60,13 +60,17 @@ export function hasBackgroundImageValue( style ) { /** * Checks if there is a current value in the background size block support - * attributes. + * attributes. Background size values include background size as well + * as background position. * * @param {Object} style Style attribute. * @return {boolean} Whether or not the block has a background size value set. */ export function hasBackgroundSizeValue( style ) { - return style?.background?.backgroundSize !== undefined; + return ( + style?.background?.backgroundPosition !== undefined || + style?.background?.backgroundSize !== undefined + ); } /** @@ -131,6 +135,7 @@ function resetBackgroundSize( style = {}, setAttributes ) { ...style, background: { ...style?.background, + backgroundPosition: undefined, backgroundRepeat: undefined, backgroundSize: undefined, }, @@ -368,60 +373,22 @@ function backgroundSizeHelpText( value ) { return __( 'Set a fixed width.' ); } -const coordsToBackgroundPosition = ( value ) => { - if ( ! value ) { +export const coordsToBackgroundPosition = ( value ) => { + if ( ! value || isNaN( value.x ) || isNaN( value.y ) ) { return undefined; } - if ( value.x === 0 && value.y === 0 ) { - return 'left top'; - } - - if ( value.x === 0 && value.y === 1 ) { - return 'left bottom'; - } - - if ( value.x === 1 && value.y === 0 ) { - return 'right top'; - } - - if ( value.x === 1 && value.y === 1 ) { - return 'right bottom'; - } - - if ( value.x === 0.5 && value.y === 0.5 ) { - return 'center'; - } - return `${ value.x * 100 }% ${ value.y * 100 }%`; }; -const backgroundPositionToCoords = ( value ) => { +export const backgroundPositionToCoords = ( value ) => { if ( ! value ) { - return { x: 0.5, y: 0.5 }; - } - - if ( value === 'left top' ) { - return { x: 0, y: 0 }; - } - - if ( value === 'left bottom' ) { - return { x: 0, y: 1 }; - } - - if ( value === 'right top' ) { - return { x: 1, y: 0 }; - } - - if ( value === 'right bottom' ) { - return { x: 1, y: 1 }; - } - - if ( value === 'center' ) { - return { x: 0.5, y: 0.5 }; + return { x: undefined, y: undefined }; } - const [ x, y ] = value.split( ' ' ).map( ( v ) => parseFloat( v ) / 100 ); + let [ x, y ] = value.split( ' ' ).map( ( v ) => parseFloat( v ) / 100 ); + x = isNaN( x ) ? undefined : x; + y = isNaN( y ) ? x : y; return { x, y }; }; @@ -545,7 +512,7 @@ function BackgroundSizePanelItem( { { + it( 'should return the correct coordinates for a percentage value using 2-value syntax', () => { + expect( backgroundPositionToCoords( '25% 75%' ) ).toEqual( { + x: 0.25, + y: 0.75, + } ); + } ); + + it( 'should return the correct coordinates for a percentage using 1-value syntax', () => { + expect( backgroundPositionToCoords( '50%' ) ).toEqual( { + x: 0.5, + y: 0.5, + } ); + } ); + + it( 'should return undefined coords in given an empty value', () => { + expect( backgroundPositionToCoords( '' ) ).toEqual( { + x: undefined, + y: undefined, + } ); + } ); + + it( 'should return undefined coords in given a string that cannot be converted', () => { + expect( backgroundPositionToCoords( 'apples' ) ).toEqual( { + x: undefined, + y: undefined, + } ); + } ); +} ); + +describe( 'coordsToBackgroundPosition', () => { + it( 'should return the correct background position for a set of coordinates', () => { + expect( coordsToBackgroundPosition( { x: 0.25, y: 0.75 } ) ).toBe( + '25% 75%' + ); + } ); + + it( 'should return undefined if no coordinates are provided', () => { + expect( coordsToBackgroundPosition( {} ) ).toBeUndefined(); + } ); +} ); diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index 1cb36fbf0dcad..8ce8c7d577fb2 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -40,26 +40,26 @@ const backgroundImage = { }, }; -const backgroundRepeat = { +const backgroundPosition = { name: 'backgroundRepeat', generate: ( style: Style, options: StyleOptions ) => { return generateRule( style, options, - [ 'background', 'backgroundRepeat' ], - 'backgroundRepeat' + [ 'background', 'backgroundPosition' ], + 'backgroundPosition' ); }, }; -const backgroundPosition = { +const backgroundRepeat = { name: 'backgroundRepeat', generate: ( style: Style, options: StyleOptions ) => { return generateRule( style, options, - [ 'background', 'backgroundPosition' ], - 'backgroundPosition' + [ 'background', 'backgroundRepeat' ], + 'backgroundRepeat' ); }, }; @@ -103,7 +103,7 @@ const backgroundSize = { export default [ backgroundImage, - backgroundRepeat, backgroundPosition, + backgroundRepeat, backgroundSize, ]; diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js index 1727ed535897b..b679775d3f37f 100644 --- a/packages/style-engine/src/test/index.js +++ b/packages/style-engine/src/test/index.js @@ -229,6 +229,7 @@ describe( 'getCSSRules', () => { source: 'file', url: 'https://example.com/image.jpg', }, + backgroundPosition: '50% 50%', backgroundRepeat: 'no-repeat', backgroundSize: '300px', }, @@ -384,6 +385,11 @@ describe( 'getCSSRules', () => { key: 'backgroundImage', value: "url( 'https://example.com/image.jpg' )", }, + { + selector: '.some-selector', + key: 'backgroundPosition', + value: '50% 50%', + }, { selector: '.some-selector', key: 'backgroundRepeat', From 5af7895c8a21ed9842364bf56874d735f685c165 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 6 Feb 2024 13:48:15 +1100 Subject: [PATCH 3/3] Ensure default position of focal point picker control is centered --- packages/components/CHANGELOG.md | 1 + packages/components/src/focal-point-picker/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 94f69636b3e05..3c4dd1e29476c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -9,6 +9,7 @@ ### Bug Fix +- `FocalPointPicker`: Allow `PointerCircle` to render in a default centered position when x and y coordinates are undefined ([#58592](https://github.com/WordPress/gutenberg/pull/58592)). - `DateTime`: Add a timezone offset value for display purposes. ([#56682](https://github.com/WordPress/gutenberg/pull/56682)). - `Placeholder`: Fix Placeholder component padding when body text font size is changed ([#58323](https://github.com/WordPress/gutenberg/pull/58323)). - `Placeholder`: Fix Global Styles typography settings bleeding into placeholder component ([#58303](https://github.com/WordPress/gutenberg/pull/58303)). diff --git a/packages/components/src/focal-point-picker/index.tsx b/packages/components/src/focal-point-picker/index.tsx index 1b4c4d9dff966..33fd505f67fe1 100644 --- a/packages/components/src/focal-point-picker/index.tsx +++ b/packages/components/src/focal-point-picker/index.tsx @@ -217,8 +217,8 @@ export function FocalPointPicker( { }; const focalPointPosition = { - left: x * bounds.width, - top: y * bounds.height, + left: x !== undefined ? x * bounds.width : 0.5 * bounds.width, + top: y !== undefined ? y * bounds.height : 0.5 * bounds.height, }; const classes = classnames(