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 ""