diff --git a/block-library/index.js b/block-library/index.js index ba1faf30c115b..1c9990c034c31 100644 --- a/block-library/index.js +++ b/block-library/index.js @@ -28,6 +28,7 @@ import * as column from '../packages/block-library/src/columns/column'; import * as coverImage from '../packages/block-library/src/cover-image'; import * as embed from '../packages/block-library/src/embed'; import * as file from '../packages/block-library/src/file'; +import * as halfMedia from '../packages/block-library/src/layout-half-media'; import * as latestComments from '../packages/block-library/src/latest-comments'; import * as latestPosts from '../packages/block-library/src/latest-posts'; import * as list from '../packages/block-library/src/list'; @@ -78,6 +79,7 @@ export const registerCoreBlocks = () => { ...embed.others, file, freeform, + halfMedia, html, latestComments, latestPosts, diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index c994183e6fcf0..8e12f1215d433 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -12,6 +12,7 @@ @import "./image/editor.scss"; @import "./latest-comments/editor.scss"; @import "./latest-posts/editor.scss"; +@import "./layout-half-media/editor.scss"; @import "./list/editor.scss"; @import "./more/editor.scss"; @import "./nextpage/editor.scss"; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 6d8ef11b8770e..7cc931be50190 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -25,6 +25,7 @@ import * as column from './columns/column'; import * as coverImage from './cover-image'; import * as embed from './embed'; import * as file from './file'; +import * as halfMedia from './layout-half-media'; import * as latestComments from './latest-comments'; import * as latestPosts from './latest-posts'; import * as list from './list'; @@ -68,6 +69,7 @@ export const registerCoreBlocks = () => { ...embed.common, ...embed.others, file, + halfMedia, latestComments, latestPosts, more, diff --git a/packages/block-library/src/layout-half-media/edit.js b/packages/block-library/src/layout-half-media/edit.js new file mode 100644 index 0000000000000..6c2dc37cad194 --- /dev/null +++ b/packages/block-library/src/layout-half-media/edit.js @@ -0,0 +1,154 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; +import { get } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { + BlockControls, + InnerBlocks, + InspectorControls, + PanelColorSettings, + withColors, + MediaContainer, +} from '@wordpress/editor'; +import { Component, Fragment } from '@wordpress/element'; +import { Toolbar } from '@wordpress/components'; + +/** + * Constants + */ +const ALLOWED_BLOCKS = [ 'core/button', 'core/paragraph', 'core/heading', 'core/list' ]; +const TEMPLATE = [ + [ 'core/paragraph', { fontSize: 'large', placeholder: 'Content…' } ], +]; +const MAX_MEDIA_WIDTH = 900; + +class ImageEdit extends Component { + constructor() { + super( ...arguments ); + + this.onSelectMedia = this.onSelectMedia.bind( this ); + this.onWidthChange = this.onWidthChange.bind( this ); + } + + onSelectMedia( media ) { + const { setAttributes } = this.props; + let newMediaWidth; + if ( media.width ) { + newMediaWidth = parseInt( media.width ); + } else { + const fullSizeWidth = get( media, [ 'sizes', 'full', 'width' ] ); + if ( fullSizeWidth ) { + newMediaWidth = parseInt( fullSizeWidth ); + } + } + + const mediaWidthProp = Number.isFinite( newMediaWidth ) ? + { mediaWidth: Math.min( newMediaWidth, MAX_MEDIA_WIDTH ) } : + {}; + + let mediaType; + // for media selections originated from a file upload. + if ( media.media_type ) { + if ( media.media_type === 'image' ) { + mediaType = 'image'; + } else { + // only images and videos are accepted so if the media_type is not an image we can assume it is a video. + // video contain the media type of 'file' in the object returned from the rest api. + mediaType = 'video'; + } + } else { // for media selections originated from existing files in the media library. + mediaType = media.type; + } + + setAttributes( { + mediaAlt: media.alt, + mediaId: media.id, + mediaType, + mediaUrl: media.url, + mediaWidth: newMediaWidth, + ...mediaWidthProp, + } ); + } + + onWidthChange( width ) { + const { setAttributes } = this.props; + + setAttributes( { + mediaWidth: width, + } ); + } + + renderMediaArea() { + const { attributes } = this.props; + const { mediaAlt, mediaId, mediaPosition, mediaType, mediaUrl, mediaWidth } = attributes; + + return ( + + ); + } + + render() { + const { attributes, backgroundColor, setAttributes, setBackgroundColor } = this.props; + const { mediaPosition } = attributes; + const className = classnames( 'wp-block-half-media', { + 'has-media-on-the-right': 'right' === mediaPosition, + [ backgroundColor.class ]: backgroundColor.class, + } ); + const style = { + backgroundColor: backgroundColor.value, + }; + const colorSettings = [ { + value: backgroundColor.value, + onChange: setBackgroundColor, + label: __( 'Background Color' ), + } ]; + const toolbarControls = [ { + icon: 'align-left', + title: __( 'Show media on left' ), + isActive: mediaPosition === 'left', + onClick: () => setAttributes( { mediaPosition: 'left' } ), + }, { + icon: 'align-left', + title: __( 'Show media on right' ), + isActive: mediaPosition === 'right', + onClick: () => setAttributes( { mediaPosition: 'right' } ), + } ]; + return ( + + + + + + + +
+ { this.renderMediaArea() } + +
+
+ ); + } +} + +export default withColors( 'backgroundColor' )( ImageEdit ); diff --git a/packages/block-library/src/layout-half-media/editor.scss b/packages/block-library/src/layout-half-media/editor.scss new file mode 100644 index 0000000000000..ad8b5b929eab0 --- /dev/null +++ b/packages/block-library/src/layout-half-media/editor.scss @@ -0,0 +1,40 @@ + +.wp-block-half-media .editor-media-container__resizer { + grid-area: half-media-media; + align-self: center; +} + +.wp-block-half-media .editor-inner-blocks { + word-break: break-word; + grid-area: half-media-content; + text-align: initial; +} + +.editor-block-list__block .editor-media-container__resize-handler { + display: block; +} + +.wp-block-half-media > .editor-inner-blocks > .editor-block-list__layout > .editor-block-list__block { + max-width: unset; +} + +figure.block-library-half-media__media-container { + margin: 0; + height: 100%; + width: 100%; +} + +.block-library-half-media__media-container img, +.block-library-half-media__media-container video { + margin-bottom: -10px; + width: 100%; +} + +.editor-block-list__block .editor-media-container__resize-handler { + display: none; +} + +.editor-block-list__block.is-selected .editor-media-container__resize-handler, +.editor-block-list__block.is-focused .editor-media-container__resize-handler { + display: block; +} diff --git a/packages/block-library/src/layout-half-media/index.js b/packages/block-library/src/layout-half-media/index.js new file mode 100644 index 0000000000000..0f40840f54ab3 --- /dev/null +++ b/packages/block-library/src/layout-half-media/index.js @@ -0,0 +1,121 @@ +/** + * External dependencies + */ +import { noop } from 'lodash'; +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { + InnerBlocks, + getColorClass, +} from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import edit from './edit'; + +export const name = 'core/half-media'; + +export const settings = { + title: __( 'Half Media' ), + + icon: , + + category: 'layout', + + attributes: { + align: { + type: 'string', + default: 'wide', + }, + backgroundColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + mediaAlt: { + type: 'string', + source: 'attribute', + selector: 'figure img', + attribute: 'alt', + default: '', + }, + mediaPosition: { + type: 'string', + default: 'left', + }, + mediaId: { + type: 'number', + }, + mediaUrl: { + type: 'string', + source: 'attribute', + selector: 'figure video,figure img', + attribute: 'src', + }, + mediaType: { + type: 'string', + }, + mediaWidth: { + type: 'number', + source: 'attribute', + selector: 'figure video,figure img', + attribute: 'width', + }, + }, + + supports: { + align: [ 'wide', 'full' ], + }, + + edit, + + save( { attributes } ) { + const { + backgroundColor, + customBackgroundColor, + mediaAlt, + mediaPosition, + mediaType, + mediaUrl, + mediaWidth, + } = attributes; + const mediaTypeRenders = { + image: () => { + return ( + { + ); + }, + video: () => { + return ( +