diff --git a/blocks/duotone-filter/duotone.php b/blocks/duotone-filter/duotone.php new file mode 100644 index 00000000..68390c77 --- /dev/null +++ b/blocks/duotone-filter/duotone.php @@ -0,0 +1,60 @@ + $r / 0xff, + 'g' => $g / 0xff, + 'b' => $b / 0xff, + ); + } +} + +// phpcs:disable +$duotone_id = $block['attrs']['duotoneId']; +$duotone_dark = hex2rgb( $block['attrs']['duotoneDark'] ); +$duotone_light = hex2rgb( $block['attrs']['duotoneLight'] ); +// phpcs:enable + +?> + + + + + + values=".2989 .5870 .1140 0 0 + .2989 .5870 .1140 0 0 + .2989 .5870 .1140 0 0 + 0 0 0 1 0" + + /> + + + + + + + + diff --git a/blocks/duotone-filter/index.php b/blocks/duotone-filter/index.php new file mode 100644 index 00000000..fe5dcd7c --- /dev/null +++ b/blocks/duotone-filter/index.php @@ -0,0 +1,31 @@ + 'block-experiments', + 'style' => 'block-experiments', + 'editor_style' => 'block-experiments-editor', + ] ); + + function is_supported_block( $block ) { + $supported_blocks = [ 'core/image', 'core/cover' ]; + return in_array( $block['blockName'], $supported_blocks, true ); + } + + add_filter( 'render_block', function ( $block_content, $block ) { + if ( + ! is_supported_block( $block ) || + ! array_key_exists( 'duotoneId', $block['attrs'] ) || + ! array_key_exists( 'duotoneDark', $block['attrs'] ) || + ! array_key_exists( 'duotoneLight', $block['attrs'] ) + ) { + return $block_content; + } + + ob_start(); + include 'duotone.php'; + $duotone = ob_get_clean(); + + return $duotone . $block_content; + }, 10, 2 ); +} ); diff --git a/blocks/duotone-filter/src/duotone.js b/blocks/duotone-filter/src/duotone.js new file mode 100644 index 00000000..7688acfb --- /dev/null +++ b/blocks/duotone-filter/src/duotone.js @@ -0,0 +1,79 @@ +/** + * WordPress dependencies + */ +import { SVG } from '@wordpress/components'; + +const hex2rgb = ( color = '' ) => { + let r = '0'; + let g = '0'; + let b = '0'; + + if ( color.length === 4 ) { + r = '0x' + color[ 1 ] + color[ 1 ]; + g = '0x' + color[ 2 ] + color[ 2 ]; + b = '0x' + color[ 3 ] + color[ 3 ]; + } else if ( color.length === 7 ) { + r = '0x' + color[ 1 ] + color[ 2 ]; + g = '0x' + color[ 3 ] + color[ 4 ]; + b = '0x' + color[ 5 ] + color[ 6 ]; + } else { + return {}; + } + + return { + r: r / 0xff, + g: g / 0xff, + b: b / 0xff, + }; +}; + +function Duotone( { id: duotoneId, darkColor, lightColor } ) { + const duotoneDark = hex2rgb( darkColor ); + const duotoneLight = hex2rgb( lightColor ); + + return ( + + + + + + + + + + + + + ); +} + +export default Duotone; diff --git a/blocks/duotone-filter/src/index.js b/blocks/duotone-filter/src/index.js new file mode 100644 index 00000000..b0b432e5 --- /dev/null +++ b/blocks/duotone-filter/src/index.js @@ -0,0 +1,132 @@ +/** + * WordPress dependencies + */ +import { InspectorControls, PanelColorSettings } from '@wordpress/block-editor'; +import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose'; +import { useEffect } from '@wordpress/element'; +import { addFilter } from '@wordpress/hooks'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import Duotone from './duotone'; + +const SUPPORTED_BLOCKS = [ 'core/image', 'core/cover' ]; + +export const isSupportedBlock = ( blockName ) => + SUPPORTED_BLOCKS.includes( blockName ); + +const withDuotoneAttributes = ( settings, blockName ) => { + if ( isSupportedBlock( blockName ) ) { + Object.assign( settings.attributes, { + duotoneId: { + type: 'string', + }, + duotoneDark: { + type: 'string', + }, + duotoneLight: { + type: 'string', + }, + } ); + } + return settings; +}; + +const withDuotoneEditorControls = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const { name: blockName, attributes, setAttributes } = props; + + if ( ! isSupportedBlock( blockName ) ) { + return ; + } + + const instanceId = useInstanceId( BlockEdit ); + + useEffect( () => { + setAttributes( { + duotoneId: `a8c-duotone-filter-${ instanceId }`, + } ); + }, [ instanceId ] ); + + return ( + <> + + + setAttributes( { duotoneDark } ), + }, + { + label: __( 'Light Color', 'block-experiments' ), + value: attributes.duotoneLight, + onChange: ( duotoneLight ) => + setAttributes( { duotoneLight } ), + }, + ] } + /> + + { attributes.duotoneDark && + attributes.duotoneLight && + attributes.duotoneId ? ( + <> + +
+ +
+ + ) : ( + + ) } + + ); + }, + 'withDuotoneEditorControls' +); + +function addDuotoneFilterStyle( props, block, attributes ) { + if ( + ! isSupportedBlock( block.name ) || + ! attributes.duotoneDark || + ! attributes.duotoneLight || + ! attributes.duotoneId + ) { + return props; + } + + const { style = {} } = props; + + return { style: { ...style, filter: `url( #${ attributes.duotoneId } )` } }; +} + +export function registerBlock() { + addFilter( + 'editor.BlockEdit', + 'a8c/duotone-filter/with-editor-controls', + withDuotoneEditorControls + ); + addFilter( + 'blocks.registerBlockType', + 'a8c/duotone-filter/add-attributes', + withDuotoneAttributes + ); + addFilter( + 'blocks.getSaveContent.extraProps', + 'a8c/duotone-filter/add-filter-style', + addDuotoneFilterStyle + ); +} diff --git a/src/index.js b/src/index.js index c9317974..3313f868 100644 --- a/src/index.js +++ b/src/index.js @@ -23,6 +23,7 @@ setCategories( [ * Load all our blocks */ import * as bauhausCentenaryBlock from '../blocks/bauhaus-centenary/src'; +import * as duotoneFilter from '../blocks/duotone-filter/src'; import * as eventBlock from '../blocks/event/src'; import * as layoutGridBlock from '../blocks/layout-grid/src'; import * as motionBackgroundBlock from '../blocks/motion-background/src'; @@ -32,6 +33,7 @@ import * as bookBlock from '../blocks/book/src'; // Instantiate the blocks, adding them to our block category bauhausCentenaryBlock.registerBlock(); +duotoneFilter.registerBlock(); eventBlock.registerBlock(); layoutGridBlock.registerBlock(); motionBackgroundBlock.registerBlock();