From 89eb5b13403568c37c2ab84bfbed82a5d18fbadb Mon Sep 17 00:00:00 2001 From: "Russell, David" Date: Sun, 27 May 2018 17:41:16 -0400 Subject: [PATCH 1/4] Add table cell text alignment options to table block toolbar --- core-blocks/table/table-block.js | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/core-blocks/table/table-block.js b/core-blocks/table/table-block.js index 642db9fbccdbd0..cdb86fdf2f4ce8 100644 --- a/core-blocks/table/table-block.js +++ b/core-blocks/table/table-block.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import { find } from 'lodash'; + /** * WordPress dependencies */ @@ -5,10 +10,16 @@ import { Component, Fragment } from '@wordpress/element'; import { Toolbar, DropdownMenu } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { + AlignmentToolbar, BlockControls, RichText, } from '@wordpress/editor'; +/** + * Internal dependencies + */ +import { domToFormat } from '../../editor/components/rich-text/format'; + function isTableSelected( editor ) { return editor.dom.getParent( editor.selection.getStart( true ), @@ -74,6 +85,7 @@ export default class TableBlock extends Component { constructor() { super(); this.handleSetup = this.handleSetup.bind( this ); + this.alignText = this.alignText.bind( this ); this.state = { editor: null, }; @@ -86,9 +98,46 @@ export default class TableBlock extends Component { selectFirstCell( editor ); } } ); + + // Update the alignment toolbar to match the CSS `text-align` + // property of the current table cell. + editor.on( 'nodechange', ( { selectionChange, parents } ) => { + if ( document.activeElement !== editor.getBody() ) { + return; + } + if ( selectionChange ) { + const selectedCell = find( parents, ( node ) => node.tagName === 'TD' || node.tagName === 'TH' ); + const textAlign = selectedCell ? selectedCell.style.textAlign : null; + this.setState( { textAlign } ); + } + } ); + this.setState( { editor } ); } + /** + * Sets the CSS `text-align` property of the current table cell. + * + * @param {string} nextAlign The next `text-align` value to set. + */ + alignText( nextAlign ) { + const { editor } = this.state; + const { onChange } = this.props; + const currentNode = editor.selection.getNode(); + const tableCell = editor.dom.getParent( currentNode, ( parentNode ) => parentNode.tagName === 'TD' || parentNode.tagName === 'TH' ); + + if ( tableCell ) { + // If `nextAlign` is undefined, set the `textAlign` value to an empty + // string in order to update both the CSS `text-align` property on the + // current table cell and the current state value. + const textAlign = nextAlign ? nextAlign : ''; + editor.dom.setStyle( tableCell, 'text-align', textAlign ); + const content = domToFormat( editor.getBody().childNodes || [], 'element', editor ); + onChange( content ); + this.setState( { textAlign } ); + } + } + render() { const { content, onChange, className, isSelected } = this.props; @@ -118,6 +167,10 @@ export default class TableBlock extends Component { } ) ) } /> + ); From ff2f07d907f0b4e47d60958052e2fcdc77c736a3 Mon Sep 17 00:00:00 2001 From: "Russell, David" Date: Tue, 29 May 2018 12:05:56 -0400 Subject: [PATCH 2/4] Move Table block alignment toolbar to inspector sidebar --- core-blocks/table/index.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/core-blocks/table/index.js b/core-blocks/table/index.js index 5600a0abe37295..b0d0690836d9a3 100644 --- a/core-blocks/table/index.js +++ b/core-blocks/table/index.js @@ -10,13 +10,13 @@ import classnames from 'classnames'; import { Fragment } from '@wordpress/element'; import { getPhrasingContentSchema } from '@wordpress/blocks'; import { - BlockControls, BlockAlignmentToolbar, RichText, InspectorControls, } from '@wordpress/editor'; import { + BaseControl, PanelBody, ToggleControl, } from '@wordpress/components'; @@ -119,12 +119,6 @@ export const settings = { return ( - - - + + + Date: Tue, 29 May 2018 21:03:20 -0400 Subject: [PATCH 3/4] Adjust margin-bottom style for inspector sidebar toolbar --- core-blocks/table/style.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core-blocks/table/style.scss b/core-blocks/table/style.scss index 5f6e6654b6ff31..737fc7de263eb3 100644 --- a/core-blocks/table/style.scss +++ b/core-blocks/table/style.scss @@ -21,3 +21,6 @@ table-layout: fixed; } } +.edit-post-sidebar .components-block-alignment .components-toolbar { + margin-bottom: 0; +} From 804710f53215f94a0f2ad4d18e8d7366f17f0b19 Mon Sep 17 00:00:00 2001 From: "Russell, David" Date: Wed, 30 May 2018 19:36:37 -0400 Subject: [PATCH 4/4] Add formatting options to Table block inspector sidebar --- core-blocks/table/editor.scss | 2 +- core-blocks/table/style.scss | 2 +- core-blocks/table/table-block.js | 201 +++++++++++++++++++++++++++---- 3 files changed, 180 insertions(+), 25 deletions(-) diff --git a/core-blocks/table/editor.scss b/core-blocks/table/editor.scss index 447ebbc9a02c04..ffb3eec10c6269 100644 --- a/core-blocks/table/editor.scss +++ b/core-blocks/table/editor.scss @@ -7,7 +7,7 @@ td, th { padding: 0.5em; - border: 1px solid currentColor; + border: 1px solid #444; } td[data-mce-selected="1"], diff --git a/core-blocks/table/style.scss b/core-blocks/table/style.scss index 737fc7de263eb3..200e5767b54519 100644 --- a/core-blocks/table/style.scss +++ b/core-blocks/table/style.scss @@ -13,7 +13,7 @@ td, th { padding: 0.5em; - border: 1px solid currentColor; + border: 1px solid #444; } // Fixed layout toggle diff --git a/core-blocks/table/table-block.js b/core-blocks/table/table-block.js index cdb86fdf2f4ce8..03ed830199f870 100644 --- a/core-blocks/table/table-block.js +++ b/core-blocks/table/table-block.js @@ -1,18 +1,27 @@ /** * External dependencies */ -import { find } from 'lodash'; +import { find, parseInt, isEmpty } from 'lodash'; +import tinycolor from 'tinycolor2'; /** * WordPress dependencies */ import { Component, Fragment } from '@wordpress/element'; -import { Toolbar, DropdownMenu } from '@wordpress/components'; +import { + Toolbar, + DropdownMenu, + FontSizePicker, + PanelBody, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { AlignmentToolbar, BlockControls, RichText, + ContrastChecker, + InspectorControls, + PanelColor, } from '@wordpress/editor'; /** @@ -81,17 +90,45 @@ const TABLE_CONTROLS = [ }, ]; +const FONT_SIZES = [ + { + name: 'small', + shortName: 'S', + size: 14, + }, + { + name: 'regular', + shortName: 'M', + size: 16, + }, + { + name: 'large', + shortName: 'L', + size: 36, + }, + { + name: 'larger', + shortName: 'XL', + size: 48, + }, +]; + export default class TableBlock extends Component { constructor() { - super(); + super( ...arguments ); this.handleSetup = this.handleSetup.bind( this ); - this.alignText = this.alignText.bind( this ); + this.getFontSize = this.getFontSize.bind( this ); + this.setFontSize = this.setFontSize.bind( this ); + this.setBorderColor = this.setBorderColor.bind( this ); + this.updateTableCellStyle = this.updateTableCellStyle.bind( this ); this.state = { editor: null, }; } - handleSetup( editor, isSelected ) { + handleSetup( editor ) { + const { isSelected } = this.props; + // select the end of the first table cell editor.on( 'init', () => { if ( isSelected ) { @@ -99,47 +136,129 @@ export default class TableBlock extends Component { } } ); - // Update the alignment toolbar to match the CSS `text-align` - // property of the current table cell. + // Update the alignment toolbar, font size, text and background color + // value for the current table cell. editor.on( 'nodechange', ( { selectionChange, parents } ) => { if ( document.activeElement !== editor.getBody() ) { return; } + if ( selectionChange ) { const selectedCell = find( parents, ( node ) => node.tagName === 'TD' || node.tagName === 'TH' ); - const textAlign = selectedCell ? selectedCell.style.textAlign : null; - this.setState( { textAlign } ); + const { + textAlign, + borderColor, + fontSize, + color, + backgroundColor, + } = selectedCell ? selectedCell.style : {}; + + this.setFontSize( parseInt( fontSize ) ); + this.setState( { + textAlign, + color: color ? tinycolor( color ).toHexString() : null, + backgroundColor: backgroundColor ? tinycolor( backgroundColor ).toHexString() : null, + borderColor: borderColor ? tinycolor( borderColor ).toHexString() : null, + } ); } } ); this.setState( { editor } ); } + // Get the correct font size value using the font size data stored + // in state. + getFontSize() { + const { customFontSize, fontSize } = this.state; + + if ( fontSize ) { + const fontSizeObj = find( FONT_SIZES, { name: fontSize } ); + if ( fontSizeObj ) { + return fontSizeObj.size; + } + } + + if ( customFontSize ) { + return customFontSize; + } + } + /** - * Sets the CSS `text-align` property of the current table cell. + * Save the correct font size value in state. If the font size is a + * defined in the `FONT_SIZES` constant, save the name of the font + * size instead. * - * @param {string} nextAlign The next `text-align` value to set. + * @param {number} fontSizeValue The numeric font size value. */ - alignText( nextAlign ) { + setFontSize( fontSizeValue ) { + const thresholdFontSize = find( FONT_SIZES, { size: fontSizeValue } ); + + if ( thresholdFontSize ) { + this.setState( { + fontSize: thresholdFontSize.name, + customFontSize: undefined, + } ); + return; + } + + this.setState( { + fontSize: undefined, + customFontSize: fontSizeValue, + } ); + } + + /** + * Sets the specified CSS property of the current table cell. + * + * @param {string} property The CSS property name (camelcased). + * @param {(string|number)} value The value to set. + * @param {boolean} updateStateValue Whether to update the property value stored in state. + */ + updateTableCellStyle( property, value, updateStateValue = true ) { const { editor } = this.state; const { onChange } = this.props; const currentNode = editor.selection.getNode(); const tableCell = editor.dom.getParent( currentNode, ( parentNode ) => parentNode.tagName === 'TD' || parentNode.tagName === 'TH' ); if ( tableCell ) { - // If `nextAlign` is undefined, set the `textAlign` value to an empty - // string in order to update both the CSS `text-align` property on the - // current table cell and the current state value. - const textAlign = nextAlign ? nextAlign : ''; - editor.dom.setStyle( tableCell, 'text-align', textAlign ); + // If `propertyValue` is undefined, set `propertyValue` to an empty + // string in order to update both the CSS property on the current + // table cell and the current state value. + const propertyValue = value ? value : ''; + editor.dom.setStyle( tableCell, property, propertyValue ); + const content = domToFormat( editor.getBody().childNodes || [], 'element', editor ); + onChange( content ); + + if ( updateStateValue ) { + this.setState( { [ property ]: propertyValue } ); + } + } + } + + /** + * Set the border color for each table cell. + * + * @param {string} nextBorderColor The next border color value to set. + */ + setBorderColor( nextBorderColor ) { + const { onChange } = this.props; + const { editor } = this.state; + const cells = editor.dom.select( 'td,th' ); + + if ( ! isEmpty( cells ) ) { + const borderColor = nextBorderColor ? nextBorderColor : ''; + editor.dom.setStyle( cells, 'border-color', borderColor ); const content = domToFormat( editor.getBody().childNodes || [], 'element', editor ); onChange( content ); - this.setState( { textAlign } ); + + this.setState( { borderColor: nextBorderColor } ); } } render() { - const { content, onChange, className, isSelected } = this.props; + const { content, onChange, className } = this.props; + const { textAlign, color, backgroundColor, borderColor, editor } = this.state; + const fontSize = this.getFontSize(); return ( @@ -151,7 +270,8 @@ export default class TableBlock extends Component { plugins: ( settings.plugins || [] ).concat( 'table' ), table_tab_navigation: false, } ) } - onSetup={ ( editor ) => this.handleSetup( editor, isSelected ) } + style={ borderColor ? { borderColor } : null } + onSetup={ ( currentEditor ) => this.handleSetup( currentEditor ) } onChange={ onChange } value={ content } /> @@ -163,15 +283,50 @@ export default class TableBlock extends Component { controls={ TABLE_CONTROLS.map( ( control ) => ( { ...control, - onClick: () => control.onClick( this.state.editor ), + onClick: () => control.onClick( editor ), } ) ) } /> this.updateTableCellStyle( 'textAlign', nextAlign ) } /> + + + + { + this.updateTableCellStyle( 'fontSize', nextFontSize, false ); + this.setFontSize( nextFontSize ); + } } + /> + + this.updateTableCellStyle( 'color', nextTextColor ) } + /> + = 18 } + /> + this.updateTableCellStyle( 'backgroundColor', nextBackgroundColor ) } + /> + ); }