From 597af755db62f5f3fc078c9b10860e5c8de577f4 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 5 Jun 2017 14:29:17 +0100 Subject: [PATCH] Blocks: Extract and factorize block alignment controls --- blocks/block-alignment-toolbar/index.js | 50 +++++++++++++++ blocks/library/button/index.js | 53 ++++----------- blocks/library/embed/index.js | 85 +++++++++---------------- blocks/library/image/index.js | 81 ++++++++--------------- blocks/library/table/index.js | 61 +++++------------- 5 files changed, 136 insertions(+), 194 deletions(-) create mode 100644 blocks/block-alignment-toolbar/index.js diff --git a/blocks/block-alignment-toolbar/index.js b/blocks/block-alignment-toolbar/index.js new file mode 100644 index 00000000000000..4c1126a73ba1d3 --- /dev/null +++ b/blocks/block-alignment-toolbar/index.js @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import { __ } from 'i18n'; +import { Toolbar } from 'components'; + +const BLOCK_ALIGNMENTS_CONTROLS = { + left: { + icon: 'align-left', + title: __( 'Align left' ), + }, + center: { + icon: 'align-center', + title: __( 'Align center' ), + }, + right: { + icon: 'align-right', + title: __( 'Align right' ), + }, + wide: { + icon: 'align-wide', + title: __( 'Wide width' ), + }, + full: { + icon: 'align-full-width', + title: __( 'Full width' ), + }, +}; + +const DEFAULT_CONTROLS = [ 'left', 'center', 'right' ]; + +export default function BlockAlignmentToolbar( { value, onChange, controls = DEFAULT_CONTROLS } ) { + function applyOrUnset( align ) { + return () => onChange( value === align ? undefined : align ); + } + + return ( + { + return { + ...BLOCK_ALIGNMENTS_CONTROLS[ control ], + isActive: value === control, + onClick: applyOrUnset( control ), + }; + } ) + } + /> + ); +} diff --git a/blocks/library/button/index.js b/blocks/library/button/index.js index f391e6d9634512..c4c0d0e43a9e73 100644 --- a/blocks/library/button/index.js +++ b/blocks/library/button/index.js @@ -9,23 +9,11 @@ import { IconButton } from 'components'; import './style.scss'; import { registerBlockType, query } from '../../api'; import Editable from '../../editable'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { attr, children } = query; -/** - * Returns an attribute setter with behavior that if the target value is - * already the assigned attribute value, it will be set to undefined. - * - * @param {string} align Alignment value - * @return {Function} Attribute setter - */ -function applyOrUnset( align ) { - return ( attributes, setAttributes ) => { - const nextAlign = attributes.align === align ? undefined : align; - setAttributes( { align: nextAlign } ); - }; -} - registerBlockType( 'core/button', { title: wp.i18n.__( 'Button' ), @@ -39,27 +27,6 @@ registerBlockType( 'core/button', { text: children( 'a' ), }, - controls: [ - { - icon: 'align-left', - title: wp.i18n.__( 'Align left' ), - isActive: ( { align } ) => 'left' === align, - onClick: applyOrUnset( 'left' ), - }, - { - icon: 'align-center', - title: wp.i18n.__( 'Align center' ), - isActive: ( { align } ) => 'center' === align, - onClick: applyOrUnset( 'center' ), - }, - { - icon: 'align-right', - title: wp.i18n.__( 'Align right' ), - isActive: ( { align } ) => 'right' === align, - onClick: applyOrUnset( 'right' ), - }, - ], - getEditWrapperProps( attributes ) { const { align } = attributes; if ( 'left' === align || 'right' === align || 'center' === align ) { @@ -68,10 +35,16 @@ registerBlockType( 'core/button', { }, edit( { attributes, setAttributes, focus, setFocus } ) { - const { text, url, title } = attributes; + const { text, url, title, align } = attributes; + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); - return ( - + return [ + focus && ( + + + + ), + } - - ); + , + ]; }, save( { attributes } ) { diff --git a/blocks/library/embed/index.js b/blocks/library/embed/index.js index a58e571bb77a9e..8e9875d16aa496 100644 --- a/blocks/library/embed/index.js +++ b/blocks/library/embed/index.js @@ -15,25 +15,13 @@ import { Button, Placeholder, HtmlEmbed, Spinner } from 'components'; import './style.scss'; import { registerBlockType, query } from '../../api'; import Editable from '../../editable'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { attr, children } = query; const HOSTS_NO_PREVIEWS = [ 'facebook.com' ]; -/** - * Returns an attribute setter with behavior that if the target value is - * already the assigned attribute value, it will be set to undefined. - * - * @param {string} align Alignment value - * @return {Function} Attribute setter - */ -function toggleAlignment( align ) { - return ( attributes, setAttributes ) => { - const nextAlign = attributes.align === align ? undefined : align; - setAttributes( { align: nextAlign } ); - }; -} - function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { return { title: wp.i18n.__( title ), @@ -47,33 +35,6 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { caption: children( 'figcaption' ), }, - controls: [ - { - icon: 'align-left', - title: wp.i18n.__( 'Align left' ), - isActive: ( { align } ) => 'left' === align, - onClick: toggleAlignment( 'left' ), - }, - { - icon: 'align-center', - title: wp.i18n.__( 'Align center' ), - isActive: ( { align } ) => ! align || 'center' === align, - onClick: toggleAlignment( 'center' ), - }, - { - icon: 'align-right', - title: wp.i18n.__( 'Align right' ), - isActive: ( { align } ) => 'right' === align, - onClick: toggleAlignment( 'right' ), - }, - { - icon: 'align-full-width', - title: wp.i18n.__( 'Wide width' ), - isActive: ( { align } ) => 'wide' === align, - onClick: toggleAlignment( 'wide' ), - }, - ], - getEditWrapperProps( attributes ) { const { align } = attributes; if ( 'left' === align || 'right' === align || 'wide' === align ) { @@ -138,21 +99,36 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { render() { const { html, type, error, fetching } = this.state; - const { url, caption } = this.props.attributes; + const { align, url, caption } = this.props.attributes; const { setAttributes, focus, setFocus } = this.props; + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + + const controls = ( + focus && ( + + + + ) + ); if ( fetching ) { - return ( -
+ return [ + controls, +

{ wp.i18n.__( 'Embedding…' ) }

-
- ); +
, + ]; } if ( ! html ) { - return ( - + return [ + controls, +
{ error &&

{ wp.i18n.__( 'Sorry, we could not embed that content.' ) }

}
-
- ); +
, + ]; } const parsedUrl = parse( url ); @@ -179,8 +155,9 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { typeClassName = 'blocks-embed-video'; } - return ( -
+ return [ + controls, +
{ ( cannotPreview ) ? (

{ url }

@@ -201,8 +178,8 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { inlineToolbar /> ) : null } -
- ); +
, + ]; } }, diff --git a/blocks/library/image/index.js b/blocks/library/image/index.js index 1bdfe5ac0dbbed..7c3b78ab25372a 100644 --- a/blocks/library/image/index.js +++ b/blocks/library/image/index.js @@ -10,23 +10,11 @@ import './style.scss'; import { registerBlockType, query } from '../../api'; import Editable from '../../editable'; import MediaUploadButton from '../../media-upload-button'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { attr, children } = query; -/** - * Returns an attribute setter with behavior that if the target value is - * already the assigned attribute value, it will be set to undefined. - * - * @param {string} align Alignment value - * @return {Function} Attribute setter - */ -function toggleAlignment( align ) { - return ( attributes, setAttributes ) => { - const nextAlign = attributes.align === align ? undefined : align; - setAttributes( { align: nextAlign } ); - }; -} - registerBlockType( 'core/image', { title: wp.i18n.__( 'Image' ), @@ -40,39 +28,6 @@ registerBlockType( 'core/image', { caption: children( 'figcaption' ), }, - controls: [ - { - icon: 'align-left', - title: wp.i18n.__( 'Align left' ), - isActive: ( { align } ) => 'left' === align, - onClick: toggleAlignment( 'left' ), - }, - { - icon: 'align-center', - title: wp.i18n.__( 'Align center' ), - isActive: ( { align } ) => ! align || 'center' === align, - onClick: toggleAlignment( 'center' ), - }, - { - icon: 'align-right', - title: wp.i18n.__( 'Align right' ), - isActive: ( { align } ) => 'right' === align, - onClick: toggleAlignment( 'right' ), - }, - { - icon: 'align-wide', - title: wp.i18n.__( 'Wide width' ), - isActive: ( { align } ) => 'wide' === align, - onClick: toggleAlignment( 'wide' ), - }, - { - icon: 'align-full-width', - title: wp.i18n.__( 'Full width' ), - isActive: ( { align } ) => 'full' === align, - onClick: toggleAlignment( 'full' ), - }, - ], - getEditWrapperProps( attributes ) { const { align } = attributes; if ( 'left' === align || 'right' === align || 'wide' === align || 'full' === align ) { @@ -81,13 +36,28 @@ registerBlockType( 'core/image', { }, edit( { attributes, setAttributes, focus, setFocus } ) { - const { url, alt, caption } = attributes; + const { url, alt, caption, align } = attributes; + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + + const controls = ( + focus && ( + + + + ) + ); if ( ! url ) { const uploadButtonProps = { isLarge: true }; const setMediaURL = ( media ) => setAttributes( { url: media.url } ); - return ( + return [ + controls, { wp.i18n.__( 'Insert from Media Library' ) } - - ); + , + ]; } const focusCaption = ( focusValue ) => setFocus( { editable: 'caption', ...focusValue } ); @@ -109,8 +79,9 @@ registerBlockType( 'core/image', { // Disable reason: Each block can be selected by clicking on it /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ - return ( -
+ return [ + controls, +
{ { ( caption && caption.length > 0 ) || !! focus ? ( ) : null } -
- ); +
, + ]; /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ }, diff --git a/blocks/library/table/index.js b/blocks/library/table/index.js index b14e101eeb47dd..6ad98f5cac4f47 100644 --- a/blocks/library/table/index.js +++ b/blocks/library/table/index.js @@ -4,23 +4,11 @@ import './style.scss'; import { registerBlockType, query as hpq } from '../../api'; import Editable from '../../editable'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; const { children, query } = hpq; -/** - * Returns an attribute setter with behavior that if the target value is - * already the assigned attribute value, it will be set to undefined. - * - * @param {string} align Alignment value - * @return {Function} Attribute setter - */ -function toggleAlignment( align ) { - return ( attributes, setAttributes ) => { - const nextAlign = attributes.align === align ? undefined : align; - setAttributes( { align: nextAlign } ); - }; -} - registerBlockType( 'core/table', { title: wp.i18n.__( 'Table' ), icon: 'editor-table', @@ -36,33 +24,6 @@ registerBlockType( 'core/table', { body: [ [ [], [] ], [ [], [] ] ], }, - controls: [ - { - icon: 'align-left', - title: wp.i18n.__( 'Align left' ), - isActive: ( { align } ) => 'left' === align, - onClick: toggleAlignment( 'left' ), - }, - { - icon: 'align-center', - title: wp.i18n.__( 'Align center' ), - isActive: ( { align } ) => 'center' === align, - onClick: toggleAlignment( 'center' ), - }, - { - icon: 'align-right', - title: wp.i18n.__( 'Align right' ), - isActive: ( { align } ) => 'right' === align, - onClick: toggleAlignment( 'right' ), - }, - { - icon: 'align-full-width', - title: wp.i18n.__( 'Wide width' ), - isActive: ( { align } ) => 'wide' === align, - onClick: toggleAlignment( 'wide' ), - }, - ], - getEditWrapperProps( attributes ) { const { align } = attributes; if ( 'left' === align || 'right' === align || 'wide' === align ) { @@ -72,9 +33,19 @@ registerBlockType( 'core/table', { edit( { attributes, setAttributes, focus, setFocus } ) { const focussedKey = focus ? focus.editable || 'body.0.0' : null; + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); - return ( - + return [ + focus && ( + + + + ), +
{ [ 'head', 'body', 'foot' ].map( ( part ) => attributes[ part ] && attributes[ part ].length ? wp.element.createElement( 't' + part, { key: part }, @@ -107,8 +78,8 @@ registerBlockType( 'core/table', { ) : null ) } -
- ); + , + ]; }, save( { attributes } ) {