From 64a15ab3757d77965c437f18229530984010bdaa Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 15 Apr 2021 17:02:40 +1000 Subject: [PATCH] Add utilities to retrieve color block support classes and styles This includes two functions. The first collects CSS classes and styles, suitable for a block's save. The second is a hook to also force inline styles so named color selections are respected even when themes do not load their color stylesheets in the editor. --- packages/block-editor/src/hooks/index.js | 2 + .../block-editor/src/hooks/use-color-props.js | 118 ++++++++++++++++++ packages/block-editor/src/index.js | 4 + 3 files changed, 124 insertions(+) create mode 100644 packages/block-editor/src/hooks/use-color-props.js diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index c087e994ba9eb9..815d9ecc2440e7 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -9,3 +9,5 @@ import './style'; import './color'; import './font-size'; import './layout'; + +export { getColorClassesAndStyles, useColorProps } from './use-color-props'; diff --git a/packages/block-editor/src/hooks/use-color-props.js b/packages/block-editor/src/hooks/use-color-props.js new file mode 100644 index 00000000000000..4522f5e34e8d2f --- /dev/null +++ b/packages/block-editor/src/hooks/use-color-props.js @@ -0,0 +1,118 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * Internal dependencies + */ +import { getInlineStyles } from './style'; +import { + getColorClassName, + getColorObjectByAttributeValues, +} from '../components/colors'; +import { + __experimentalGetGradientClass, + getGradientValueBySlug, +} from '../components/gradients'; +import useEditorFeature from '../components/use-editor-feature'; + +// The code in this file has largely been lifted from the color block support +// hook. +// +// This utility is intended to assist where the serialization of the colors +// block support is being skipped for a block but the color related CSS classes +// & styles still need to be generated so they can be applied to inner elements. + +const EMPTY_ARRAY = []; + +/** + * Provides the CSS class names and inline styles for a block's color support + * attributes. + * + * @param {Object} attributes Block attributes. + * @return {Object} Color block support derived CSS classes & styles. + */ +export function getColorClassesAndStyles( attributes ) { + const { backgroundColor, textColor, gradient, style } = attributes; + + // Collect color CSS classes. + const backgroundClass = getColorClassName( + 'background-color', + backgroundColor + ); + const textClass = getColorClassName( 'color', textColor ); + + const gradientClass = __experimentalGetGradientClass( gradient ); + const hasGradient = gradientClass || style?.color?.gradient; + + // Determine color CSS class name list. + const className = classnames( textClass, gradientClass, { + // Don't apply the background class if there's a gradient. + [ backgroundClass ]: ! hasGradient && !! backgroundClass, + 'has-text-color': textColor || style?.color?.text, + 'has-background': + backgroundColor || + style?.color?.background || + gradient || + style?.color?.gradient, + 'has-link-color': style?.color?.link, + } ); + + // Collect inline styles for colors. + const colorStyles = style?.color || {}; + const styleProp = getInlineStyles( { color: colorStyles } ); + + return { + className: className || undefined, + style: styleProp, + }; +} + +/** + * Determines the color related props for a block derived from its color block + * support attributes. + * + * Inline styles are forced for named colors to ensure these selections are + * reflected when themes do not load their color stylesheets in the editor. + * + * @param {Object} attributes Block attributes. + * @return {Object} ClassName & style props from colors block support. + */ +export function useColorProps( attributes ) { + const { backgroundColor, textColor, gradient } = attributes; + + const colors = useEditorFeature( 'color.palette' ) || EMPTY_ARRAY; + const gradients = useEditorFeature( 'color.gradients' ) || EMPTY_ARRAY; + + const colorProps = getColorClassesAndStyles( attributes ); + + // Force inline styles to apply colors when themes do not load their color + // stylesheets in the editor. + if ( backgroundColor ) { + const backgroundColorObject = getColorObjectByAttributeValues( + colors, + backgroundColor + ); + + colorProps.style.backgroundColor = backgroundColorObject.color; + } + + if ( gradient ) { + colorProps.style.background = getGradientValueBySlug( + gradients, + gradient + ); + } + + if ( textColor ) { + const textColorObject = getColorObjectByAttributeValues( + colors, + textColor + ); + + colorProps.style.color = textColorObject.color; + } + + return colorProps; +} diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index e8a1ebcd480c2b..a5604c367c0252 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -7,6 +7,10 @@ import '@wordpress/rich-text'; * Internal dependencies */ import './hooks'; +export { + getColorClassesAndStyles as __experimentalGetColorClassesAndStyles, + useColorProps as __experimentalUseColorProps, +} from './hooks'; export * from './components'; export * from './utils'; export { storeConfig, store } from './store';