From 91e6e9e260b8eb2df3da7cf923e49cacdc977744 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Mon, 28 Oct 2024 10:59:41 +0100 Subject: [PATCH 1/9] BlockStyleWrapper aware of block themes --- packages/types/src/config/Blocks.d.ts | 2 + packages/types/src/index.d.ts | 1 + packages/types/src/widgets/colors.d.ts | 11 + packages/types/src/widgets/index.d.ts | 1 + .../manage/Blocks/Block/EditBlockWrapper.jsx | 2 +- .../manage/Blocks/Block/StyleWrapper.jsx | 2 +- packages/volto/src/helpers/Blocks/Blocks.js | 93 +++++--- .../volto/src/helpers/Blocks/Blocks.test.js | 202 +++++++++++++++--- 8 files changed, 253 insertions(+), 61 deletions(-) create mode 100644 packages/types/src/widgets/colors.d.ts create mode 100644 packages/types/src/widgets/index.d.ts diff --git a/packages/types/src/config/Blocks.d.ts b/packages/types/src/config/Blocks.d.ts index 2b2a6b4f4c..5e84e44564 100644 --- a/packages/types/src/config/Blocks.d.ts +++ b/packages/types/src/config/Blocks.d.ts @@ -2,6 +2,7 @@ import type { Content } from '../content'; import type { BlockViewProps, BlockEditProps } from '../blocks'; import type { IntlShape } from 'react-intl'; import { User } from '../services'; +import { Color } from '../widgets'; export interface BlocksConfig { blocksConfig: BlocksConfigData; @@ -9,6 +10,7 @@ export interface BlocksConfig { requiredBlocks: string[]; initialBlocks: Record | Record; initialBlocksFocus: Record; + blockThemes: Color[]; } export interface BlocksConfigData { diff --git a/packages/types/src/index.d.ts b/packages/types/src/index.d.ts index 9364577e39..5c6690facf 100644 --- a/packages/types/src/index.d.ts +++ b/packages/types/src/index.d.ts @@ -2,5 +2,6 @@ export * from './blocks'; export * from './config'; export * from './content'; export * from './services'; +export * from './widgets'; export * from './utils'; import './modules'; diff --git a/packages/types/src/widgets/colors.d.ts b/packages/types/src/widgets/colors.d.ts new file mode 100644 index 0000000000..62ba67b019 --- /dev/null +++ b/packages/types/src/widgets/colors.d.ts @@ -0,0 +1,11 @@ +export type Color = + | { + name: string; + label: string; + style: Record<`--${string}`, string>; + } + | { + name: string; + label: string; + style: undefined; + }; diff --git a/packages/types/src/widgets/index.d.ts b/packages/types/src/widgets/index.d.ts new file mode 100644 index 0000000000..1bae1c0e49 --- /dev/null +++ b/packages/types/src/widgets/index.d.ts @@ -0,0 +1 @@ +export * from './colors'; diff --git a/packages/volto/src/components/manage/Blocks/Block/EditBlockWrapper.jsx b/packages/volto/src/components/manage/Blocks/Block/EditBlockWrapper.jsx index 4e047bcd18..fbfa549d51 100644 --- a/packages/volto/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +++ b/packages/volto/src/components/manage/Blocks/Block/EditBlockWrapper.jsx @@ -69,7 +69,7 @@ const EditBlockWrapper = (props) => { data, classNames, }); - const style = buildStyleObjectFromData(data.styles); + const style = buildStyleObjectFromData(data); // We need to merge the StyleWrapper styles with the draggable props from b-D&D const styleMergedWithDragProps = { diff --git a/packages/volto/src/components/manage/Blocks/Block/StyleWrapper.jsx b/packages/volto/src/components/manage/Blocks/Block/StyleWrapper.jsx index 45c06d6fb2..3f94877a7d 100644 --- a/packages/volto/src/components/manage/Blocks/Block/StyleWrapper.jsx +++ b/packages/volto/src/components/manage/Blocks/Block/StyleWrapper.jsx @@ -19,7 +19,7 @@ const StyleWrapper = (props) => { classNames, }); - style = buildStyleObjectFromData(data.styles); + style = buildStyleObjectFromData(data); const rewrittenChildren = React.Children.map(children, (child) => { if (React.isValidElement(child)) { diff --git a/packages/volto/src/helpers/Blocks/Blocks.js b/packages/volto/src/helpers/Blocks/Blocks.js index 6b24de9080..cbc8ca791a 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.js +++ b/packages/volto/src/helpers/Blocks/Blocks.js @@ -629,11 +629,11 @@ export const styleDataToStyleObject = (key, value, prefix = '') => { * Generate styles object from data * * @function buildStyleObjectFromData - * @param {Object} obj A style wrapper object data + * @param {Object} data A block data object * @param {string} prefix The prefix (could be dragged from a recursive call, initially empty) * @return {Object} The style object ready to be passed as prop */ -export const buildStyleObjectFromData = (obj = {}, prefix = '') => { +export const buildStyleObjectFromData = (data = {}, prefix = '') => { // style wrapper object has the form: // const styles = { // color: 'red', @@ -641,39 +641,68 @@ export const buildStyleObjectFromData = (obj = {}, prefix = '') => { // } // Returns: {'--background-color: '#AABBCC'} - return Object.fromEntries( - Object.entries(obj) - .filter(([k, v]) => k.startsWith('--') || isObject(v)) - .reduce( - (acc, [k, v]) => [ - ...acc, - // Kept for easy debugging - // ...(() => { - // if (isObject(v)) { - // return Object.entries( - // buildStyleObjectFromData( - // v, - // `${k.endsWith(':noprefix') ? '' : `${prefix}${k}--`}`, - // ), - // ); - // } - // return [styleDataToStyleObject(k, v, prefix)]; - // })(), - ...(isObject(v) - ? Object.entries( - buildStyleObjectFromData( - v, - `${k.endsWith(':noprefix') ? '' : `${prefix}${k}--`}`, // We don't add a prefix if the key ends with the marker suffix - ), - ) - : [styleDataToStyleObject(k, v, prefix)]), - ], - [], - ) - .filter((v) => !!v), + function recursiveBuildStyleObjectFromData(obj, prefix) { + return Object.fromEntries( + Object.entries(obj) + .filter(([k, v]) => k.startsWith('--') || isObject(v)) + .reduce( + (acc, [k, v]) => [ + ...acc, + // Kept for easy debugging + // ...(() => { + // if (isObject(v)) { + // return Object.entries( + // buildStyleObjectFromData( + // v, + // `${k.endsWith(':noprefix') ? '' : `${prefix}${k}--`}`, + // ), + // ); + // } + // return [styleDataToStyleObject(k, v, prefix)]; + // })(), + ...(isObject(v) + ? Object.entries( + recursiveBuildStyleObjectFromData( + v, + `${k.endsWith(':noprefix') ? '' : `${prefix}${k}--`}`, // We don't add a prefix if the key ends with the marker suffix + ), + ) + : [styleDataToStyleObject(k, v, prefix)]), + ], + [], + ) + .filter((v) => !!v), + ); + } + + const styleObj = data.styles || {}; + const stylesFromCSSproperties = recursiveBuildStyleObjectFromData( + styleObj, + prefix, ); + + const blockStyleDefinitions = + // We look up for the blockThemes in the block's data, then in the global config + // We keep data.colors for BBB, but data.themes should be used + data.themes || data.colors || config.blocks.blockThemes || []; + const stylesFromBlockThemes = data.theme + ? findStyleByName(blockStyleDefinitions, data.theme) + : {}; + return { ...stylesFromCSSproperties, ...stylesFromBlockThemes }; }; +/** + * Find a matching style by name given a style definition + * + * @function findStyleByName + * @param {Object} styleDefinitions An object with the style definitions + * @param {string} name The name of the style to find + * @return {Object} The style object of the matching name + */ +function findStyleByName(styleDefinitions, name) { + return styleDefinitions.find((color) => color.name === name)?.style; +} + /** * Return previous/next blocks given the content object and the current block id * diff --git a/packages/volto/src/helpers/Blocks/Blocks.test.js b/packages/volto/src/helpers/Blocks/Blocks.test.js index 900171717f..fc804ce4a4 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.test.js +++ b/packages/volto/src/helpers/Blocks/Blocks.test.js @@ -1104,37 +1104,43 @@ describe('Blocks', () => { describe('buildStyleObjectFromData', () => { it('Understands style converter for style values, no styles found', () => { - const styles = { - color: 'red', - backgroundColor: '#FFF', + const data = { + styles: { + color: 'red', + backgroundColor: '#FFF', + }, }; - expect(buildStyleObjectFromData(styles)).toEqual({}); + expect(buildStyleObjectFromData(data)).toEqual({}); }); it('Understands style converter for style values', () => { - const styles = { - color: 'red', - '--background-color': '#FFF', + const data = { + styles: { + color: 'red', + '--background-color': '#FFF', + }, }; - expect(buildStyleObjectFromData(styles)).toEqual({ + expect(buildStyleObjectFromData(data)).toEqual({ '--background-color': '#FFF', }); }); it('Supports multiple nested levels', () => { - const styles = { - '--color': 'red', - backgroundColor: '#AABBCC', - nested: { - l1: 'white', - '--foo': 'white', - level2: { - '--foo': '#fff', - bar: '#000', + const data = { + styles: { + '--color': 'red', + backgroundColor: '#AABBCC', + nested: { + l1: 'white', + '--foo': 'white', + level2: { + '--foo': '#fff', + bar: '#000', + }, }, }, }; - expect(buildStyleObjectFromData(styles)).toEqual({ + expect(buildStyleObjectFromData(data)).toEqual({ '--color': 'red', '--nested--foo': 'white', '--nested--level2--foo': '#fff', @@ -1142,22 +1148,164 @@ describe('Blocks', () => { }); it('Supports multiple nested levels and optional inclusion of the name of the level', () => { - const styles = { + const data = { + styles: { + '--color': 'red', + backgroundColor: '#AABBCC', + 'nested:noprefix': { + l1: 'white', + '--foo': 'white', + level2: { + '--foo': '#fff', + bar: '#000', + }, + }, + }, + }; + expect(buildStyleObjectFromData(data)).toEqual({ '--color': 'red', - backgroundColor: '#AABBCC', - 'nested:noprefix': { - l1: 'white', - '--foo': 'white', - level2: { - '--foo': '#fff', - bar: '#000', + '--foo': 'white', + '--level2--foo': '#fff', + }); + }); + + it('Supports named theme block - with global config', () => { + config.blocks.blockThemes = [ + { + style: { + '--primary-color': '#fff', + '--primary-foreground-color': '#ecebeb', + }, + name: 'default', + label: 'Default', + }, + { + style: { + '--primary-color': '#000', + '--primary-foreground-color': '#fff', + }, + name: 'primary', + label: 'Primary', + }, + ]; + const data = { + theme: 'primary', + }; + expect(buildStyleObjectFromData(data)).toEqual({ + '--primary-color': '#000', + '--primary-foreground-color': '#fff', + }); + }); + + it('Supports named theme block - with local block themes config', () => { + config.blocks.blockThemes = [ + { + style: { + '--primary-color': '#fff', + '--primary-foreground-color': '#ecebeb', + }, + name: 'default', + label: 'Default', + }, + { + style: { + '--primary-color': '#000', + '--primary-foreground-color': '#fff', + }, + name: 'primary', + label: 'Primary', + }, + ]; + const themes = [ + { + style: { + '--primary-color': '#fff', + '--primary-foreground-color': '#ecebeb', + }, + name: 'default', + label: 'Default', + }, + { + style: { + '--secondary-color': '#bbb', + '--secondary-foreground-color': '#ddd', + }, + name: 'secondary', + label: 'Secondary', + }, + ]; + + const data = { + theme: 'secondary', + themes, + }; + expect(buildStyleObjectFromData(data)).toEqual({ + '--secondary-color': '#bbb', + '--secondary-foreground-color': '#ddd', + }); + }); + + it('All together now - named theme block - with local block themes config', () => { + config.blocks.blockThemes = [ + { + style: { + '--primary-color': '#fff', + '--primary-foreground-color': '#ecebeb', + }, + name: 'default', + label: 'Default', + }, + { + style: { + '--primary-color': '#000', + '--primary-foreground-color': '#fff', + }, + name: 'primary', + label: 'Primary', + }, + ]; + const themes = [ + { + style: { + '--primary-color': '#fff', + '--primary-foreground-color': '#ecebeb', }, + name: 'default', + label: 'Default', }, + { + style: { + '--secondary-color': '#bbb', + '--secondary-foreground-color': '#ddd', + }, + name: 'secondary', + label: 'Secondary', + }, + ]; + + const data = { + styles: { + '--color': 'red', + backgroundColor: '#AABBCC', + 'nested:noprefix': { + l1: 'white', + '--foo': 'white', + level2: { + '--foo': '#fff', + bar: '#000', + }, + }, + }, + theme: 'secondary', + themes, }; - expect(buildStyleObjectFromData(styles)).toEqual({ + + expect(buildStyleObjectFromData(data)).toEqual({ '--color': 'red', '--foo': 'white', '--level2--foo': '#fff', + '--secondary-color': '#bbb', + '--secondary-foreground-color': '#ddd', }); }); }); From 881b19648cb6cfc49e360339af3ffd934c68f166 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Mon, 28 Oct 2024 11:26:54 +0100 Subject: [PATCH 2/9] Make it pluggable --- packages/volto/src/helpers/Blocks/Blocks.js | 23 +++++++++++-------- .../volto/src/helpers/Blocks/Blocks.test.js | 17 ++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/packages/volto/src/helpers/Blocks/Blocks.js b/packages/volto/src/helpers/Blocks/Blocks.js index cbc8ca791a..e7f67aad36 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.js +++ b/packages/volto/src/helpers/Blocks/Blocks.js @@ -681,14 +681,19 @@ export const buildStyleObjectFromData = (data = {}, prefix = '') => { prefix, ); - const blockStyleDefinitions = - // We look up for the blockThemes in the block's data, then in the global config - // We keep data.colors for BBB, but data.themes should be used - data.themes || data.colors || config.blocks.blockThemes || []; - const stylesFromBlockThemes = data.theme - ? findStyleByName(blockStyleDefinitions, data.theme) - : {}; - return { ...stylesFromCSSproperties, ...stylesFromBlockThemes }; + let stylesFromObjectStyleEnhancers = {}; + const enhancers = config.getUtilities({ + type: 'styleWrapperStyleObjectEnhancer', + }); + + enhancers.forEach(({ method }) => { + stylesFromObjectStyleEnhancers = { + ...stylesFromObjectStyleEnhancers, + ...method(data), + }; + }); + + return { ...stylesFromCSSproperties, ...stylesFromObjectStyleEnhancers }; }; /** @@ -699,7 +704,7 @@ export const buildStyleObjectFromData = (data = {}, prefix = '') => { * @param {string} name The name of the style to find * @return {Object} The style object of the matching name */ -function findStyleByName(styleDefinitions, name) { +export function findStyleByName(styleDefinitions, name) { return styleDefinitions.find((color) => color.name === name)?.style; } diff --git a/packages/volto/src/helpers/Blocks/Blocks.test.js b/packages/volto/src/helpers/Blocks/Blocks.test.js index fc804ce4a4..f2f3fdfe04 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.test.js +++ b/packages/volto/src/helpers/Blocks/Blocks.test.js @@ -24,6 +24,7 @@ import { findBlocks, findContainer, isBlockContainer, + findStyleByName, } from './Blocks'; import config from '@plone/volto/registry'; @@ -968,6 +969,22 @@ describe('Blocks', () => { }); describe('buildStyleClassNamesFromData', () => { + beforeEach(() => { + function blockThemesEnhancer(data) { + const blockStyleDefinitions = + // We look up for the blockThemes in the block's data, then in the global config + // We keep data.colors for BBB, but data.themes should be used + data.themes || data.colors || config.blocks.blockThemes || []; + return data.theme + ? findStyleByName(blockStyleDefinitions, data.theme) + : {}; + } + config.registerUtility({ + name: 'blockThemesEnhancer', + type: 'styleWrapperStyleObjectEnhancer', + method: blockThemesEnhancer, + }); + }); it('Sets styles classname array according to style values', () => { const styles = { color: 'red', From 3cb2077412c50e65ee32481d6657a62d8b2b7de4 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Mon, 28 Oct 2024 11:38:15 +0100 Subject: [PATCH 3/9] Some renaming --- packages/types/src/blocks/index.d.ts | 12 ++++++++++++ packages/types/src/config/Blocks.d.ts | 5 +++-- packages/types/src/index.d.ts | 1 - packages/types/src/widgets/colors.d.ts | 11 ----------- packages/types/src/widgets/index.d.ts | 1 - packages/volto/src/helpers/Blocks/Blocks.test.js | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 packages/types/src/widgets/colors.d.ts delete mode 100644 packages/types/src/widgets/index.d.ts diff --git a/packages/types/src/blocks/index.d.ts b/packages/types/src/blocks/index.d.ts index 902e205453..149af1143e 100644 --- a/packages/types/src/blocks/index.d.ts +++ b/packages/types/src/blocks/index.d.ts @@ -120,3 +120,15 @@ export interface BlockEditProps { errors: Record>; blocksErrors: Record>>; } + +export type StyleDefinition = + | { + name: string; + label: string; + style: Record<`--${string}`, string>; + } + | { + name: string; + label: string; + style: undefined; + }; diff --git a/packages/types/src/config/Blocks.d.ts b/packages/types/src/config/Blocks.d.ts index 5e84e44564..9204996e8b 100644 --- a/packages/types/src/config/Blocks.d.ts +++ b/packages/types/src/config/Blocks.d.ts @@ -2,7 +2,7 @@ import type { Content } from '../content'; import type { BlockViewProps, BlockEditProps } from '../blocks'; import type { IntlShape } from 'react-intl'; import { User } from '../services'; -import { Color } from '../widgets'; +import { StyleDefinition } from '../blocks'; export interface BlocksConfig { blocksConfig: BlocksConfigData; @@ -10,7 +10,8 @@ export interface BlocksConfig { requiredBlocks: string[]; initialBlocks: Record | Record; initialBlocksFocus: Record; - blockThemes: Color[]; + blocksThemes: StyleDefinition[]; + blocksWidths: StyleDefinition[]; } export interface BlocksConfigData { diff --git a/packages/types/src/index.d.ts b/packages/types/src/index.d.ts index 5c6690facf..9364577e39 100644 --- a/packages/types/src/index.d.ts +++ b/packages/types/src/index.d.ts @@ -2,6 +2,5 @@ export * from './blocks'; export * from './config'; export * from './content'; export * from './services'; -export * from './widgets'; export * from './utils'; import './modules'; diff --git a/packages/types/src/widgets/colors.d.ts b/packages/types/src/widgets/colors.d.ts deleted file mode 100644 index 62ba67b019..0000000000 --- a/packages/types/src/widgets/colors.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type Color = - | { - name: string; - label: string; - style: Record<`--${string}`, string>; - } - | { - name: string; - label: string; - style: undefined; - }; diff --git a/packages/types/src/widgets/index.d.ts b/packages/types/src/widgets/index.d.ts deleted file mode 100644 index 1bae1c0e49..0000000000 --- a/packages/types/src/widgets/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './colors'; diff --git a/packages/volto/src/helpers/Blocks/Blocks.test.js b/packages/volto/src/helpers/Blocks/Blocks.test.js index f2f3fdfe04..5525c93d56 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.test.js +++ b/packages/volto/src/helpers/Blocks/Blocks.test.js @@ -974,7 +974,7 @@ describe('Blocks', () => { const blockStyleDefinitions = // We look up for the blockThemes in the block's data, then in the global config // We keep data.colors for BBB, but data.themes should be used - data.themes || data.colors || config.blocks.blockThemes || []; + data.themes || data.colors || config.blocks.blocksThemes || []; return data.theme ? findStyleByName(blockStyleDefinitions, data.theme) : {}; @@ -1187,7 +1187,7 @@ describe('Blocks', () => { }); it('Supports named theme block - with global config', () => { - config.blocks.blockThemes = [ + config.blocks.blocksThemes = [ { style: { '--primary-color': '#fff', @@ -1215,7 +1215,7 @@ describe('Blocks', () => { }); it('Supports named theme block - with local block themes config', () => { - config.blocks.blockThemes = [ + config.blocks.blocksThemes = [ { style: { '--primary-color': '#fff', @@ -1263,7 +1263,7 @@ describe('Blocks', () => { }); it('All together now - named theme block - with local block themes config', () => { - config.blocks.blockThemes = [ + config.blocks.blocksThemes = [ { style: { '--primary-color': '#fff', From b28fb3c7351be22751752f9cf6214d779c54cd49 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Mon, 28 Oct 2024 17:53:17 +0100 Subject: [PATCH 4/9] David's suggestions --- packages/types/src/config/Blocks.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/config/Blocks.d.ts b/packages/types/src/config/Blocks.d.ts index 9204996e8b..70bf61c5cf 100644 --- a/packages/types/src/config/Blocks.d.ts +++ b/packages/types/src/config/Blocks.d.ts @@ -10,8 +10,8 @@ export interface BlocksConfig { requiredBlocks: string[]; initialBlocks: Record | Record; initialBlocksFocus: Record; - blocksThemes: StyleDefinition[]; - blocksWidths: StyleDefinition[]; + themes: StyleDefinition[]; + widths: StyleDefinition[]; } export interface BlocksConfigData { From 57c61f060cc5af91f737cadf554ea40b17130127 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Mon, 28 Oct 2024 22:21:09 +0100 Subject: [PATCH 5/9] Changelog and upgrade guide --- docs/source/upgrade-guide/index.md | 9 +++++++++ packages/volto/news/6445.breaking | 5 +++++ 2 files changed, 14 insertions(+) create mode 100644 packages/volto/news/6445.breaking diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 7148dbb0ed..2631195c94 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -600,6 +600,15 @@ Add this object to the `pnpm` key in your project {file}`package.json`. ```{versionadded} @plone/registry 3.0.0-alpha.0 ``` +### `buildStyleObjectFromData` helper arguments + +The first argument of `buildStyleObjectFromData` helper function now takes the full block `data` object. +If you are using this helper in your code or add-on, please update the calls to this helper. + +```ts +function buildStyleObjectFromData(data: BlocksFormData, prefix: string): Object +``` + ### Deprecation notices for Volto 18 #### `@plone/generator-volto` diff --git a/packages/volto/news/6445.breaking b/packages/volto/news/6445.breaking new file mode 100644 index 0000000000..e2e1f53037 --- /dev/null +++ b/packages/volto/news/6445.breaking @@ -0,0 +1,5 @@ +Enhance the `buildStyleObjectFromData` helper. @sneridagh + +Breaking: +- `buildStyleObjectFromData` first argument now takes the whole block `data` object. +Please see the [Upgrade Guide](https://6.docs.plone.org/volto/upgrade-guide/index.html). From 4176f81da8ded2d3a8f5dc92cdb64e4dc2e3fc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Tue, 29 Oct 2024 08:56:32 +0100 Subject: [PATCH 6/9] Apply suggestions from code review Co-authored-by: Steve Piercy --- docs/source/upgrade-guide/index.md | 4 ++-- packages/volto/news/6445.breaking | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 2631195c94..ab9ae8bf2d 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -602,8 +602,8 @@ Add this object to the `pnpm` key in your project {file}`package.json`. ### `buildStyleObjectFromData` helper arguments -The first argument of `buildStyleObjectFromData` helper function now takes the full block `data` object. -If you are using this helper in your code or add-on, please update the calls to this helper. +The first argument of the `buildStyleObjectFromData` helper function now takes the full block `data` object. +If you use this helper in your code or add-on, you must update the calls to this helper, as shown in its signature. ```ts function buildStyleObjectFromData(data: BlocksFormData, prefix: string): Object diff --git a/packages/volto/news/6445.breaking b/packages/volto/news/6445.breaking index e2e1f53037..8b86adf95d 100644 --- a/packages/volto/news/6445.breaking +++ b/packages/volto/news/6445.breaking @@ -1,5 +1,5 @@ Enhance the `buildStyleObjectFromData` helper. @sneridagh Breaking: -- `buildStyleObjectFromData` first argument now takes the whole block `data` object. +- The first argument of `buildStyleObjectFromData` now takes the whole block `data` object. Please see the [Upgrade Guide](https://6.docs.plone.org/volto/upgrade-guide/index.html). From e582bcd3c511833550e30374abd4291d5c956256 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Tue, 29 Oct 2024 09:05:52 +0100 Subject: [PATCH 7/9] Fix tests --- .../volto/src/helpers/Blocks/Blocks.test.js | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/packages/volto/src/helpers/Blocks/Blocks.test.js b/packages/volto/src/helpers/Blocks/Blocks.test.js index 5525c93d56..659b3c9b50 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.test.js +++ b/packages/volto/src/helpers/Blocks/Blocks.test.js @@ -969,22 +969,6 @@ describe('Blocks', () => { }); describe('buildStyleClassNamesFromData', () => { - beforeEach(() => { - function blockThemesEnhancer(data) { - const blockStyleDefinitions = - // We look up for the blockThemes in the block's data, then in the global config - // We keep data.colors for BBB, but data.themes should be used - data.themes || data.colors || config.blocks.blocksThemes || []; - return data.theme - ? findStyleByName(blockStyleDefinitions, data.theme) - : {}; - } - config.registerUtility({ - name: 'blockThemesEnhancer', - type: 'styleWrapperStyleObjectEnhancer', - method: blockThemesEnhancer, - }); - }); it('Sets styles classname array according to style values', () => { const styles = { color: 'red', @@ -1120,8 +1104,30 @@ describe('Blocks', () => { }); describe('buildStyleObjectFromData', () => { + beforeEach(() => { + function blockThemesEnhancer(data) { + const blockConfig = config.blocks.blocksConfig[data['@type']]; + const blockStyleDefinitions = + // We look up for the blockThemes in the block's data, then in the global config + // We keep data.colors for BBB, but data.themes should be used + blockConfig.themes || + blockConfig.colors || + config.blocks.themes || + []; + return data.theme + ? findStyleByName(blockStyleDefinitions, data.theme) + : {}; + } + config.registerUtility({ + name: 'blockThemesEnhancer', + type: 'styleWrapperStyleObjectEnhancer', + method: blockThemesEnhancer, + }); + }); + it('Understands style converter for style values, no styles found', () => { const data = { + '@type': 'text', styles: { color: 'red', backgroundColor: '#FFF', @@ -1132,6 +1138,7 @@ describe('Blocks', () => { it('Understands style converter for style values', () => { const data = { + '@type': 'text', styles: { color: 'red', '--background-color': '#FFF', @@ -1144,6 +1151,7 @@ describe('Blocks', () => { it('Supports multiple nested levels', () => { const data = { + '@type': 'text', styles: { '--color': 'red', backgroundColor: '#AABBCC', @@ -1166,6 +1174,7 @@ describe('Blocks', () => { it('Supports multiple nested levels and optional inclusion of the name of the level', () => { const data = { + '@type': 'text', styles: { '--color': 'red', backgroundColor: '#AABBCC', @@ -1187,7 +1196,7 @@ describe('Blocks', () => { }); it('Supports named theme block - with global config', () => { - config.blocks.blocksThemes = [ + config.blocks.themes = [ { style: { '--primary-color': '#fff', @@ -1206,6 +1215,7 @@ describe('Blocks', () => { }, ]; const data = { + '@type': 'text', theme: 'primary', }; expect(buildStyleObjectFromData(data)).toEqual({ @@ -1215,7 +1225,7 @@ describe('Blocks', () => { }); it('Supports named theme block - with local block themes config', () => { - config.blocks.blocksThemes = [ + config.blocks.themes = [ { style: { '--primary-color': '#fff', @@ -1251,11 +1261,12 @@ describe('Blocks', () => { label: 'Secondary', }, ]; - + config.blocks.blocksConfig.text.themes = themes; const data = { + '@type': 'text', theme: 'secondary', - themes, }; + expect(buildStyleObjectFromData(data)).toEqual({ '--secondary-color': '#bbb', '--secondary-foreground-color': '#ddd', @@ -1301,6 +1312,7 @@ describe('Blocks', () => { ]; const data = { + '@type': 'text', styles: { '--color': 'red', backgroundColor: '#AABBCC', From 0f431ebce405ff6553fab4af2b8d803a8db8218d Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Tue, 29 Oct 2024 09:14:09 +0100 Subject: [PATCH 8/9] Remove the breaking as per suggestion --- docs/source/upgrade-guide/index.md | 9 ----- packages/volto/news/6445.breaking | 5 --- packages/volto/news/6445.feature | 1 + packages/volto/src/helpers/Blocks/Blocks.js | 38 ++++++++++++--------- 4 files changed, 23 insertions(+), 30 deletions(-) delete mode 100644 packages/volto/news/6445.breaking create mode 100644 packages/volto/news/6445.feature diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index ab9ae8bf2d..7148dbb0ed 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -600,15 +600,6 @@ Add this object to the `pnpm` key in your project {file}`package.json`. ```{versionadded} @plone/registry 3.0.0-alpha.0 ``` -### `buildStyleObjectFromData` helper arguments - -The first argument of the `buildStyleObjectFromData` helper function now takes the full block `data` object. -If you use this helper in your code or add-on, you must update the calls to this helper, as shown in its signature. - -```ts -function buildStyleObjectFromData(data: BlocksFormData, prefix: string): Object -``` - ### Deprecation notices for Volto 18 #### `@plone/generator-volto` diff --git a/packages/volto/news/6445.breaking b/packages/volto/news/6445.breaking deleted file mode 100644 index 8b86adf95d..0000000000 --- a/packages/volto/news/6445.breaking +++ /dev/null @@ -1,5 +0,0 @@ -Enhance the `buildStyleObjectFromData` helper. @sneridagh - -Breaking: -- The first argument of `buildStyleObjectFromData` now takes the whole block `data` object. -Please see the [Upgrade Guide](https://6.docs.plone.org/volto/upgrade-guide/index.html). diff --git a/packages/volto/news/6445.feature b/packages/volto/news/6445.feature new file mode 100644 index 0000000000..213e80ce46 --- /dev/null +++ b/packages/volto/news/6445.feature @@ -0,0 +1 @@ +Enhance the `buildStyleObjectFromData` helper. @sneridagh diff --git a/packages/volto/src/helpers/Blocks/Blocks.js b/packages/volto/src/helpers/Blocks/Blocks.js index e7f67aad36..e863bfc231 100644 --- a/packages/volto/src/helpers/Blocks/Blocks.js +++ b/packages/volto/src/helpers/Blocks/Blocks.js @@ -675,25 +675,31 @@ export const buildStyleObjectFromData = (data = {}, prefix = '') => { ); } - const styleObj = data.styles || {}; - const stylesFromCSSproperties = recursiveBuildStyleObjectFromData( - styleObj, - prefix, - ); + // If the block has a `@type`, it's a full data block object + // Then apply the style enhancers + if (data['@type']) { + const styleObj = data.styles || {}; + const stylesFromCSSproperties = recursiveBuildStyleObjectFromData( + styleObj, + prefix, + ); - let stylesFromObjectStyleEnhancers = {}; - const enhancers = config.getUtilities({ - type: 'styleWrapperStyleObjectEnhancer', - }); + let stylesFromObjectStyleEnhancers = {}; + const enhancers = config.getUtilities({ + type: 'styleWrapperStyleObjectEnhancer', + }); - enhancers.forEach(({ method }) => { - stylesFromObjectStyleEnhancers = { - ...stylesFromObjectStyleEnhancers, - ...method(data), - }; - }); + enhancers.forEach(({ method }) => { + stylesFromObjectStyleEnhancers = { + ...stylesFromObjectStyleEnhancers, + ...method(data), + }; + }); - return { ...stylesFromCSSproperties, ...stylesFromObjectStyleEnhancers }; + return { ...stylesFromCSSproperties, ...stylesFromObjectStyleEnhancers }; + } else { + return recursiveBuildStyleObjectFromData(data, prefix); + } }; /** From ea8bb4f5d2d597a2b4abe9ca5b37c98b4c198c7f Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Tue, 29 Oct 2024 11:13:14 +0100 Subject: [PATCH 9/9] Changelog --- packages/types/news/6445.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/types/news/6445.feature diff --git a/packages/types/news/6445.feature b/packages/types/news/6445.feature new file mode 100644 index 0000000000..818f3ad7b7 --- /dev/null +++ b/packages/types/news/6445.feature @@ -0,0 +1 @@ +`StyleDefinitions` in types. @sneridagh