diff --git a/blocks/api/parser.js b/blocks/api/parser.js index b5fa7c23d86330..21c1f129604f28 100644 --- a/blocks/api/parser.js +++ b/blocks/api/parser.js @@ -37,12 +37,17 @@ export function parseBlockAttributes( rawContent, blockSettings ) { * @return {Object} All block attributes */ export function getBlockAttributes( blockSettings, rawContent, attributes ) { + // Handle global controls + const contentToParse = attributes && attributes.position + ? query.parse( rawContent, query.html( 'div' ) ) + : rawContent; + // Merge any attributes from comment delimiters with block implementation attributes = attributes || {}; if ( blockSettings ) { attributes = { ...attributes, - ...parseBlockAttributes( rawContent, blockSettings ), + ...parseBlockAttributes( contentToParse, blockSettings ), }; } diff --git a/blocks/api/serializer.js b/blocks/api/serializer.js index de93ef171f4385..8f45acf9ea1dd3 100644 --- a/blocks/api/serializer.js +++ b/blocks/api/serializer.js @@ -69,6 +69,9 @@ export default function serialize( blocks ) { const blockType = block.blockType; const settings = getBlockSettings( blockType ); const saveContent = getSaveContent( settings.save, block.attributes ); + const wrappedSavedContent = block.attributes.position + ? `
${ saveContent }
` + : saveContent; return memo + ( '' + - saveContent + + wrappedSavedContent + '' diff --git a/blocks/controls/index.js b/blocks/controls/index.js new file mode 100644 index 00000000000000..de21407b0ec609 --- /dev/null +++ b/blocks/controls/index.js @@ -0,0 +1,35 @@ +function applyOrUnset( position ) { + return ( attributes, setAttributes ) => { + const nextPosition = attributes.position === position ? undefined : position; + setAttributes( { position: nextPosition } ); + }; +} + +const controls = { + 'core/position-left': { + icon: 'align-left', + title: wp.i18n.__( 'Position left' ), + isActive: ( { position } ) => 'left' === position, + onClick: applyOrUnset( 'left' ) + }, + 'core/position-center': { + icon: 'align-center', + title: wp.i18n.__( 'Position center' ), + isActive: ( { position } ) => 'center' === position, + onClick: applyOrUnset( 'center' ) + }, + 'core/position-right': { + icon: 'align-right', + title: wp.i18n.__( 'Position right' ), + isActive: ( { position } ) => 'right' === position, + onClick: applyOrUnset( 'right' ) + }, + 'core/position-none': { + icon: 'align-none', + title: wp.i18n.__( 'No positionning' ), + isActive: ( { position } ) => ! position || 'none' === position, + onClick: applyOrUnset( 'none' ) + } +}; + +export default controls; diff --git a/blocks/index.js b/blocks/index.js index c72da46d5c8282..fdbdc510bac372 100644 --- a/blocks/index.js +++ b/blocks/index.js @@ -5,3 +5,4 @@ import './library'; export * from './api'; export * from './components'; +export { default as controls } from './controls'; diff --git a/blocks/library/image/index.js b/blocks/library/image/index.js index 1705bbcdd0d8cf..aeea5f20052030 100644 --- a/blocks/library/image/index.js +++ b/blocks/library/image/index.js @@ -19,6 +19,13 @@ registerBlock( 'core/image', { caption: html( 'figcaption' ) }, + controls: [ + 'core/position-left', + 'core/position-center', + 'core/position-right', + 'core/position-none' + ], + edit( { attributes, isSelected, setAttributes } ) { const { url, alt, caption } = attributes; diff --git a/editor/modes/visual-editor/block.js b/editor/modes/visual-editor/block.js index 226efa62b2f32f..9beb3989223925 100644 --- a/editor/modes/visual-editor/block.js +++ b/editor/modes/visual-editor/block.js @@ -3,6 +3,7 @@ */ import { connect } from 'react-redux'; import classnames from 'classnames'; +import { isString, compact } from 'lodash'; /** * Internal dependencies @@ -29,7 +30,7 @@ function VisualEditorBlock( props ) { const className = classnames( 'editor-visual-editor__block', { 'is-selected': isSelected, 'is-hovered': isHovered - } ); + }, block.attributes.position && `align${ block.attributes.position }` ); const { onChange, onSelect, onDeselect, onMouseEnter, onMouseLeave, onInsertAfter } = props; @@ -50,6 +51,12 @@ function VisualEditorBlock( props ) { } } + const controls = settings.controls && compact( + settings.controls.map( ( control ) => { + return isString( control ) ? wp.blocks.controls[ control ] : control; + } ) + ); + // Disable reason: Each block can receive focus but must be able to contain // block children. Tab keyboard navigation enabled by tabIndex assignment. @@ -67,9 +74,9 @@ function VisualEditorBlock( props ) { { ( isSelected || isHovered ) && }
{ isSelected && } - { isSelected && settings.controls ? ( + { isSelected && controls ? ( ( { + controls={ controls.map( ( control ) => ( { ...control, onClick: () => control.onClick( block.attributes, setAttributes ), isActive: () => control.isActive( block.attributes ) diff --git a/editor/modes/visual-editor/style.scss b/editor/modes/visual-editor/style.scss index 6436376cd41c54..9f0401d5db3b6d 100644 --- a/editor/modes/visual-editor/style.scss +++ b/editor/modes/visual-editor/style.scss @@ -57,3 +57,19 @@ .editor-visual-editor .editor-inserter { margin: $item-spacing; } + +.editor-visual-editor .alignright, +.editor-visual-editor .alignleft, +.editor-visual-editor .aligncenter { + z-index: 1; +} + +// Temporary styling before having the possibility +// to edit the block width +.editor-visual-editor .alignright, +.editor-visual-editor .alignleft { + max-width: 50%; + img { + max-width: 100%; + } +} diff --git a/languages/gutenberg.pot b/languages/gutenberg.pot index 88a6bcbc8b5f94..22f3f6b2903d01 100644 --- a/languages/gutenberg.pot +++ b/languages/gutenberg.pot @@ -3,6 +3,22 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "X-Generator: babel-plugin-wp-i18n\n" +#: blocks/controls/index.js:11 +msgid "Position left" +msgstr "" + +#: blocks/controls/index.js:17 +msgid "Position center" +msgstr "" + +#: blocks/controls/index.js:23 +msgid "Position right" +msgstr "" + +#: blocks/controls/index.js:29 +msgid "No positionning" +msgstr "" + #: blocks/library/freeform/index.js:9 msgid "Freeform" msgstr "" @@ -19,7 +35,7 @@ msgstr "" msgid "Image" msgstr "" -#: blocks/library/image/index.js:31 +#: blocks/library/image/index.js:38 msgid "Write caption…" msgstr ""