@wordpress/block-editor
Version:
95 lines (80 loc) • 2.37 kB
JavaScript
/**
* WordPress dependencies
*/
import { useLayoutEffect, useReducer } from '@wordpress/element';
/**
* Internal dependencies
*/
import ContrastChecker from '../components/contrast-checker';
import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs';
function getComputedValue( node, property ) {
return node.ownerDocument.defaultView
.getComputedStyle( node )
.getPropertyValue( property );
}
function getBlockElementColors( blockEl ) {
if ( ! blockEl ) {
return {};
}
const firstLinkElement = blockEl.querySelector( 'a' );
const linkColor = !! firstLinkElement?.innerText
? getComputedValue( firstLinkElement, 'color' )
: undefined;
const textColor = getComputedValue( blockEl, 'color' );
let backgroundColorNode = blockEl;
let backgroundColor = getComputedValue(
backgroundColorNode,
'background-color'
);
while (
backgroundColor === 'rgba(0, 0, 0, 0)' &&
backgroundColorNode.parentNode &&
backgroundColorNode.parentNode.nodeType ===
backgroundColorNode.parentNode.ELEMENT_NODE
) {
backgroundColorNode = backgroundColorNode.parentNode;
backgroundColor = getComputedValue(
backgroundColorNode,
'background-color'
);
}
return {
textColor,
backgroundColor,
linkColor,
};
}
function reducer( prevColors, newColors ) {
const hasChanged = Object.keys( newColors ).some(
( key ) => prevColors[ key ] !== newColors[ key ]
);
// Do not re-render if the colors have not changed.
return hasChanged ? newColors : prevColors;
}
export default function BlockColorContrastChecker( { clientId } ) {
const blockEl = useBlockElement( clientId );
const [ colors, setColors ] = useReducer( reducer, {} );
// There are so many things that can change the color of a block
// So we perform this check on every render.
useLayoutEffect( () => {
if ( ! blockEl ) {
return;
}
function updateColors() {
setColors( getBlockElementColors( blockEl ) );
}
// Combine `useLayoutEffect` and two rAF calls to ensure that values are read
// after the current paint but before the next paint.
window.requestAnimationFrame( () =>
window.requestAnimationFrame( updateColors )
);
} );
return (
<ContrastChecker
backgroundColor={ colors.backgroundColor }
textColor={ colors.textColor }
linkColor={ colors.linkColor }
enableAlphaChecker
/>
);
}