From 705da6cc480d2e128a8f47999ed824ed23323cd1 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 | 91 +++++++++---------------- blocks/library/image/index.js | 66 +++++------------- blocks/library/table/index.js | 61 +++++------------ 5 files changed, 128 insertions(+), 193 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 9f699af9d3cfdf..22a4fb98bd6ebc 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,39 +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' ), - }, - { - 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 ) { @@ -144,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 ); @@ -185,8 +155,9 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { typeClassName = 'blocks-embed-video'; } - return ( -
+ return [ + controls, +
{ ( cannotPreview ) ? (

{ url }

@@ -207,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 eeab8d1eec4867..10cc2bf6a33fcc 100644 --- a/blocks/library/image/index.js +++ b/blocks/library/image/index.js @@ -13,23 +13,11 @@ import Editable from '../../editable'; import MediaUploadButton from '../../media-upload-button'; import InspectorControls from '../../inspector-controls'; import TextControl from '../../inspector-controls/text-control'; +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: __( 'Image' ), @@ -43,39 +31,6 @@ registerBlockType( 'core/image', { caption: children( 'figcaption' ), }, - controls: [ - { - icon: 'align-left', - title: __( 'Align left' ), - isActive: ( { align } ) => 'left' === align, - onClick: toggleAlignment( 'left' ), - }, - { - icon: 'align-center', - title: __( 'Align center' ), - isActive: ( { align } ) => ! align || 'center' === align, - onClick: toggleAlignment( 'center' ), - }, - { - icon: 'align-right', - title: __( 'Align right' ), - isActive: ( { align } ) => 'right' === align, - onClick: toggleAlignment( 'right' ), - }, - { - icon: 'align-wide', - title: __( 'Wide width' ), - isActive: ( { align } ) => 'wide' === align, - onClick: toggleAlignment( 'wide' ), - }, - { - icon: 'align-full-width', - title: __( 'Full width' ), - isActive: ( { align } ) => 'full' === align, - onClick: toggleAlignment( 'full' ), - }, - ], - getEditWrapperProps( attributes ) { const { align } = attributes; if ( 'left' === align || 'right' === align || 'wide' === align || 'full' === align ) { @@ -84,13 +39,27 @@ registerBlockType( 'core/image', { }, edit( { attributes, setAttributes, focus, setFocus } ) { - const { url, alt, caption } = attributes; + const { url, alt, caption, align } = attributes; const updateAlt = ( newAlt ) => setAttributes( { alt: newAlt } ); + const updateAlignment = ( nextAlign ) => setAttributes( { align: nextAlign } ); + + const controls = ( + focus && ( + + + + ) + ); if ( ! url ) { const uploadButtonProps = { isLarge: true }; const setMediaURL = ( media ) => setAttributes( { url: media.url } ); return [ + controls, diff --git a/blocks/library/table/index.js b/blocks/library/table/index.js index 41d75d2eee300e..3acc0ad7eccb72 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 } ) {