Skip to content

Commit

Permalink
Use Colors: Add text color detection support. (#18547)
Browse files Browse the repository at this point in the history
* Use Colors: Add text color detection support.

* Use Colors: Support specific selectors for color detection.

* Use Colors: Pass down refs to contrast checker to avoid stale values.

* Heading: Detect inherited text color for contrast checking.
  • Loading branch information
epiqueras authored Dec 2, 2019
1 parent e00fa01 commit 2fd13b6
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 46 deletions.
130 changes: 87 additions & 43 deletions packages/block-editor/src/components/colors/use-colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import memoize from 'memize';
import classnames from 'classnames';
import { map, kebabCase, camelCase, startCase } from 'lodash';
import { map, kebabCase, camelCase, castArray, startCase } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -48,7 +48,8 @@ const ColorPanel = ( {
colorSettings,
colorPanelProps,
contrastCheckers,
detectedBackgroundColor,
detectedBackgroundColorRef,
detectedColorRef,
panelChildren,
} ) => (
<PanelColorSettings
Expand All @@ -63,9 +64,13 @@ const ColorPanel = ( {
backgroundColor = resolveContrastCheckerColor(
backgroundColor,
colorSettings,
detectedBackgroundColor
detectedBackgroundColorRef.current
);
textColor = resolveContrastCheckerColor(
textColor,
colorSettings,
detectedColorRef.current
);
textColor = resolveContrastCheckerColor( textColor, colorSettings );
return (
<ContrastChecker
key={ `${ backgroundColor }-${ textColor }` }
Expand All @@ -80,11 +85,12 @@ const ColorPanel = ( {
backgroundColor = resolveContrastCheckerColor(
backgroundColor || value,
colorSettings,
detectedBackgroundColor
detectedBackgroundColorRef.current
);
textColor = resolveContrastCheckerColor(
textColor || value,
colorSettings
colorSettings,
detectedColorRef.current
);
return (
<ContrastChecker
Expand Down Expand Up @@ -192,37 +198,72 @@ export default function __experimentalUseColors(
);

const detectedBackgroundColorRef = useRef();
const BackgroundColorDetector = useMemo(
() =>
contrastCheckers &&
( Array.isArray( contrastCheckers ) ?
contrastCheckers.some(
( { backgroundColor } ) => backgroundColor === true
) :
contrastCheckers.backgroundColor === true ) &&
withFallbackStyles( ( node, { querySelector } ) => {
if ( querySelector ) {
node = node.parentNode.querySelector( querySelector );
}
let backgroundColor = getComputedStyle( node ).backgroundColor;
while ( backgroundColor === 'rgba(0, 0, 0, 0)' && node.parentNode ) {
node = node.parentNode;
backgroundColor = getComputedStyle( node ).backgroundColor;
const detectedColorRef = useRef();
const ColorDetector = useMemo( () => {
let needsBackgroundColor = false;
let needsColor = false;
for ( const { backgroundColor, textColor } of castArray( contrastCheckers ) ) {
if ( ! needsBackgroundColor ) {
needsBackgroundColor = backgroundColor === true;
}
if ( ! needsColor ) {
needsColor = textColor === true;
}
if ( needsBackgroundColor && needsColor ) {
break;
}
}
return (
( needsBackgroundColor || needsColor ) &&
withFallbackStyles(
(
node,
{
querySelector,
backgroundColorSelector = querySelector,
textColorSelector = querySelector,
}
) => {
let backgroundColorNode = node;
let textColorNode = node;
if ( backgroundColorSelector ) {
backgroundColorNode = node.parentNode.querySelector(
backgroundColorSelector
);
}
if ( textColorSelector ) {
textColorNode = node.parentNode.querySelector( textColorSelector );
}
let backgroundColor;
const color = getComputedStyle( textColorNode ).color;
if ( needsBackgroundColor ) {
backgroundColor = getComputedStyle( backgroundColorNode )
.backgroundColor;
while (
backgroundColor === 'rgba(0, 0, 0, 0)' &&
backgroundColorNode.parentNode
) {
backgroundColorNode = backgroundColorNode.parentNode;
backgroundColor = getComputedStyle( backgroundColorNode )
.backgroundColor;
}
}
detectedBackgroundColorRef.current = backgroundColor;
detectedColorRef.current = color;
return { backgroundColor, color };
}
detectedBackgroundColorRef.current = backgroundColor;
return { backgroundColor };
} )( () => <></> ),
[
colorConfigs.reduce(
( acc, colorConfig ) =>
`${ acc } | ${ attributes[ colorConfig.name ] } | ${
attributes[ camelCase( `custom ${ colorConfig.name }` ) ]
}`,
''
),
...deps,
]
);
)( () => <></> )
);
}, [
colorConfigs.reduce(
( acc, colorConfig ) =>
`${ acc } | ${ attributes[ colorConfig.name ] } | ${
attributes[ camelCase( `custom ${ colorConfig.name }` ) ]
}`,
''
),
...deps,
] );

return useMemo( () => {
const colorSettings = {};
Expand All @@ -249,9 +290,9 @@ export default function __experimentalUseColors(
const customColor = attributes[ camelCase( `custom ${ name }` ) ];
// We memoize the non-primitives to avoid unnecessary updates
// when they are used as props for other components.
const _color = ! customColor ?
colors.find( ( __color ) => __color.slug === color ) :
undefined;
const _color = customColor ?
undefined :
colors.find( ( __color ) => __color.slug === color );
acc[ componentName ] = createComponent(
name,
property,
Expand All @@ -261,7 +302,9 @@ export default function __experimentalUseColors(
customColor
);
acc[ componentName ].displayName = componentName;
acc[ componentName ].color = customColor ? customColor : ( _color && _color.color );
acc[ componentName ].color = customColor ?
customColor :
_color && _color.color;
acc[ componentName ].slug = color;
acc[ componentName ].setColor = createSetColor( name, colors );

Expand All @@ -287,7 +330,8 @@ export default function __experimentalUseColors(
colorSettings,
colorPanelProps,
contrastCheckers,
detectedBackgroundColor: detectedBackgroundColorRef.current,
detectedBackgroundColorRef,
detectedColorRef,
panelChildren,
};
return {
Expand All @@ -296,7 +340,7 @@ export default function __experimentalUseColors(
InspectorControlsColorPanel: (
<InspectorControlsColorPanel { ...wrappedColorPanelProps } />
),
BackgroundColorDetector,
ColorDetector,
};
}, [ attributes, setAttributes, detectedBackgroundColorRef.current, ...deps ] );
}, [ attributes, setAttributes, ...deps ] );
}
6 changes: 3 additions & 3 deletions packages/block-library/src/heading/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ function HeadingEdit( {
onReplace,
className,
} ) {
const { TextColor, InspectorControlsColorPanel, BackgroundColorDetector } = __experimentalUseColors(
const { TextColor, InspectorControlsColorPanel, ColorDetector } = __experimentalUseColors(
[ { name: 'textColor', property: 'color' } ],
{
contrastCheckers: { backgroundColor: true },
contrastCheckers: { backgroundColor: true, textColor: true },
},
[]
);
Expand All @@ -56,7 +56,7 @@ function HeadingEdit( {
</InspectorControls>
{ InspectorControlsColorPanel }
<TextColor>
<BackgroundColorDetector querySelector='[contenteditable="true"]' />
<ColorDetector querySelector='[contenteditable="true"]' />
<RichText
identifier="content"
tagName={ tagName }
Expand Down

0 comments on commit 2fd13b6

Please sign in to comment.