diff --git a/packages/block-editor/src/components/block-pattern-picker/index.js b/packages/block-editor/src/components/block-pattern-picker/index.js index b0abe60066f2fa..3b2b0a1c05383f 100644 --- a/packages/block-editor/src/components/block-pattern-picker/index.js +++ b/packages/block-editor/src/components/block-pattern-picker/index.js @@ -42,7 +42,7 @@ function BlockPatternPicker( { isLarge icon={ pattern.icon } size={ 48 } - onClick={ () => onSelect( pattern.innerBlocks ) } + onClick={ () => onSelect( pattern ) } className="block-editor-block-pattern-picker__pattern" label={ pattern.label } /> @@ -54,7 +54,7 @@ function BlockPatternPicker( {
diff --git a/packages/block-library/src/columns/edit.js b/packages/block-library/src/columns/edit.js index f550523ac3f84d..01c6c240bfba02 100644 --- a/packages/block-library/src/columns/edit.js +++ b/packages/block-library/src/columns/edit.js @@ -107,8 +107,8 @@ export function ColumnsEdit( {
{ - setTemplate( nextTemplate ); + __experimentalOnSelectPattern={ ( nextPattern = defaultPattern ) => { + setTemplate( nextPattern.innerBlocks ); setForceUseTemplate( true ); } } __experimentalAllowPatternSkip diff --git a/packages/block-library/src/media-text/deprecated.js b/packages/block-library/src/media-text/deprecated.js index 721a6cf7f3a318..48ebad81a434b5 100644 --- a/packages/block-library/src/media-text/deprecated.js +++ b/packages/block-library/src/media-text/deprecated.js @@ -15,7 +15,7 @@ import { /** * Internal dependencies */ -import { imageFillStyles } from './media-container'; +import { imageFillStyles } from './shared'; const DEFAULT_MEDIA_WIDTH = 50; diff --git a/packages/block-library/src/media-text/icon-retry.native.js b/packages/block-library/src/media-text/edit/icon-retry.native.js similarity index 100% rename from packages/block-library/src/media-text/icon-retry.native.js rename to packages/block-library/src/media-text/edit/icon-retry.native.js diff --git a/packages/block-library/src/media-text/edit/index.js b/packages/block-library/src/media-text/edit/index.js new file mode 100644 index 00000000000000..492cf201a35abb --- /dev/null +++ b/packages/block-library/src/media-text/edit/index.js @@ -0,0 +1,72 @@ +/** + * External dependencies + */ +import { get, map } from 'lodash'; + +/** + * WordPress dependencies + */ +import { createBlock } from '@wordpress/blocks'; +import { __experimentalBlockPatternPicker } from '@wordpress/block-editor'; +import { useDispatch, useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import MediaTextContainer from './media-text-container'; + +const createBlocksFromInnerBlocksTemplate = ( innerBlocksTemplate ) => { + return map( + innerBlocksTemplate, + ( [ name, attributes, innerBlocks = [] ] ) => + createBlock( name, attributes, createBlocksFromInnerBlocksTemplate( innerBlocks ) ) + ); +}; + +const MediaTextEdit = ( props ) => { + const { clientId, name } = props; + const { blockType, defaultPattern, hasInnerBlocks, patterns } = useSelect( ( select ) => { + const { + __experimentalGetBlockPatterns, + getBlockType, + __experimentalGetDefaultBlockPattern, + } = select( 'core/blocks' ); + + return { + blockType: getBlockType( name ), + defaultPattern: __experimentalGetDefaultBlockPattern( name ), + hasInnerBlocks: select( 'core/block-editor' ).getBlocks( clientId ).length > 0, + patterns: __experimentalGetBlockPatterns( name ), + }; + }, [ clientId, name ] ); + + const { replaceInnerBlocks } = useDispatch( 'core/block-editor' ); + + if ( hasInnerBlocks ) { + return ( + + ); + } + + return ( + <__experimentalBlockPatternPicker + icon={ get( blockType, [ 'icon', 'src' ] ) } + label={ get( blockType, [ 'title' ] ) } + patterns={ patterns } + onSelect={ ( nextPattern = defaultPattern ) => { + if ( nextPattern.attributes ) { + props.setAttributes( nextPattern.attributes ); + } + if ( nextPattern.innerBlocks ) { + replaceInnerBlocks( + props.clientId, + createBlocksFromInnerBlocksTemplate( nextPattern.innerBlocks ) + ); + } + } } + allowSkip + /> + ); +}; + +export default MediaTextEdit; diff --git a/packages/block-library/src/media-text/edit.native.js b/packages/block-library/src/media-text/edit/index.native.js similarity index 99% rename from packages/block-library/src/media-text/edit.native.js rename to packages/block-library/src/media-text/edit/index.native.js index 009eb4bbbcb256..2fae7b7427b173 100644 --- a/packages/block-library/src/media-text/edit.native.js +++ b/packages/block-library/src/media-text/edit/index.native.js @@ -25,7 +25,7 @@ import { withViewportMatch } from '@wordpress/viewport'; * Internal dependencies */ import MediaContainer from './media-container'; -import styles from './style.scss'; +import styles from '../style.scss'; /** * Constants diff --git a/packages/block-library/src/media-text/media-container-icon.js b/packages/block-library/src/media-text/edit/media-container-icon.js similarity index 100% rename from packages/block-library/src/media-text/media-container-icon.js rename to packages/block-library/src/media-text/edit/media-container-icon.js diff --git a/packages/block-library/src/media-text/media-container.js b/packages/block-library/src/media-text/edit/media-container.js similarity index 94% rename from packages/block-library/src/media-text/media-container.js rename to packages/block-library/src/media-text/edit/media-container.js index fce35487d6a03b..c20dc5f0366cbd 100644 --- a/packages/block-library/src/media-text/media-container.js +++ b/packages/block-library/src/media-text/edit/media-container.js @@ -17,21 +17,13 @@ import { withDispatch } from '@wordpress/data'; * Internal dependencies */ import icon from './media-container-icon'; +import { imageFillStyles } from '../shared'; /** * Constants */ const ALLOWED_MEDIA_TYPES = [ 'image', 'video' ]; -export function imageFillStyles( url, focalPoint ) { - return url ? - { - backgroundImage: `url(${ url })`, - backgroundPosition: focalPoint ? `${ focalPoint.x * 100 }% ${ focalPoint.y * 100 }%` : `50% 50%`, - } : - {}; -} - class MediaContainer extends Component { constructor() { super( ...arguments ); diff --git a/packages/block-library/src/media-text/media-container.native.js b/packages/block-library/src/media-text/edit/media-container.native.js similarity index 99% rename from packages/block-library/src/media-text/media-container.native.js rename to packages/block-library/src/media-text/edit/media-container.native.js index fea6a9671965c4..192566ebba9e10 100644 --- a/packages/block-library/src/media-text/media-container.native.js +++ b/packages/block-library/src/media-text/edit/media-container.native.js @@ -35,7 +35,7 @@ import { compose, withPreferredColorScheme } from '@wordpress/compose'; /** * Internal dependencies */ -import styles from './style.scss'; +import styles from '../style.scss'; import icon from './media-container-icon'; import SvgIconRetry from './icon-retry'; diff --git a/packages/block-library/src/media-text/edit.js b/packages/block-library/src/media-text/edit/media-text-container.js similarity index 95% rename from packages/block-library/src/media-text/edit.js rename to packages/block-library/src/media-text/edit/media-text-container.js index 94495a7d635d65..71c93f76ab97f9 100644 --- a/packages/block-library/src/media-text/edit.js +++ b/packages/block-library/src/media-text/edit/media-text-container.js @@ -7,7 +7,7 @@ import { get } from 'lodash'; /** * WordPress dependencies */ -import { __, _x } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { BlockControls, BlockVerticalAlignmentToolbar, @@ -25,22 +25,17 @@ import { ExternalLink, FocalPointPicker, } from '@wordpress/components'; + /** * Internal dependencies */ import MediaContainer from './media-container'; -/** - * Constants - */ -const TEMPLATE = [ - [ 'core/paragraph', { fontSize: 'large', placeholder: _x( 'Content…', 'content placeholder' ) } ], -]; // this limits the resize to a safe zone to avoid making broken layouts const WIDTH_CONSTRAINT_PERCENTAGE = 15; const applyWidthConstraints = ( width ) => Math.max( WIDTH_CONSTRAINT_PERCENTAGE, Math.min( width, 100 - WIDTH_CONSTRAINT_PERCENTAGE ) ); -class MediaTextEdit extends Component { +class MediaTextContainer extends Component { constructor() { super( ...arguments ); @@ -235,7 +230,6 @@ class MediaTextEdit extends Component {
{ this.renderMediaArea() }
@@ -244,4 +238,4 @@ class MediaTextEdit extends Component { } } -export default withColors( 'backgroundColor' )( MediaTextEdit ); +export default withColors( 'backgroundColor' )( MediaTextContainer ); diff --git a/packages/block-library/src/media-text/index.js b/packages/block-library/src/media-text/index.js index 73f1ee2080a1b4..a57ef0dc8d4424 100644 --- a/packages/block-library/src/media-text/index.js +++ b/packages/block-library/src/media-text/index.js @@ -10,6 +10,7 @@ import deprecated from './deprecated'; import edit from './edit'; import icon from './icon'; import metadata from './block.json'; +import patterns from './patterns'; import save from './save'; import transforms from './transforms'; @@ -26,6 +27,7 @@ export const settings = { align: [ 'wide', 'full' ], html: false, }, + patterns, example: { attributes: { mediaType: 'image', diff --git a/packages/block-library/src/media-text/patterns.js b/packages/block-library/src/media-text/patterns.js index e69de29bb2d1d6..2b70199c6831c2 100644 --- a/packages/block-library/src/media-text/patterns.js +++ b/packages/block-library/src/media-text/patterns.js @@ -0,0 +1,59 @@ +/** + * WordPress dependencies + */ +import { __, _x } from '@wordpress/i18n'; + +const innerBlocks = [ + [ 'core/paragraph', { fontSize: 'large', placeholder: _x( 'Content…', 'content placeholder' ) } ], +]; + +/** + * Template option choices for predefined columns layouts. + * + * @type {WPBlockPattern[]} + */ +const patterns = [ + { + name: 'media-left-equal', + label: __( 'Media on left; equal split' ), + icon: 'align-pull-left', + isDefault: true, + attributes: { + mediaPosition: 'left', + mediaWidth: 50, + }, + innerBlocks, + }, + { + name: 'media-left-one-third-two-thirds', + label: __( 'Media on left; one-third, two-thirds split' ), + icon: 'align-pull-left', + attributes: { + mediaPosition: 'left', + mediaWidth: 33.33, + }, + innerBlocks, + }, + { + name: 'media-right-two-thirds-one-thirds', + label: __( 'Media on right; two-thirds, one-third split' ), + icon: 'align-pull-right', + attributes: { + mediaPosition: 'right', + mediaWidth: 33.33, + }, + innerBlocks, + }, + { + name: 'media-right-equal', + label: __( 'Media on right; equal split' ), + icon: 'align-pull-right', + attributes: { + mediaPosition: 'right', + mediaWidth: 50, + }, + innerBlocks, + }, +]; + +export default patterns; diff --git a/packages/block-library/src/media-text/save.js b/packages/block-library/src/media-text/save.js index 8d4529173948e6..7a2fed9849f676 100644 --- a/packages/block-library/src/media-text/save.js +++ b/packages/block-library/src/media-text/save.js @@ -15,7 +15,7 @@ import { /** * Internal dependencies */ -import { imageFillStyles } from './media-container'; +import { imageFillStyles } from './shared'; const DEFAULT_MEDIA_WIDTH = 50; diff --git a/packages/block-library/src/media-text/shared.js b/packages/block-library/src/media-text/shared.js new file mode 100644 index 00000000000000..103b3e4a2b12ae --- /dev/null +++ b/packages/block-library/src/media-text/shared.js @@ -0,0 +1,8 @@ +export function imageFillStyles( url, focalPoint ) { + return url ? + { + backgroundImage: `url(${ url })`, + backgroundPosition: focalPoint ? `${ focalPoint.x * 100 }% ${ focalPoint.y * 100 }%` : `50% 50%`, + } : + {}; +} diff --git a/packages/components/src/placeholder/index.js b/packages/components/src/placeholder/index.js index 3a7c40c993001f..c4f01e47ad7c5b 100644 --- a/packages/components/src/placeholder/index.js +++ b/packages/components/src/placeholder/index.js @@ -4,6 +4,11 @@ import classnames from 'classnames'; import { isString } from 'lodash'; +/** + * WordPress dependencies + */ +import { cloneElement } from '@wordpress/element'; + /** * Internal dependencies */ @@ -27,7 +32,7 @@ function Placeholder( { icon, children, label, instructions, className, notices,
}
- { isString( icon ) ? : icon } + { isString( icon ) ? : cloneElement( icon, { height: 24, width: 24 } ) } { label }
{ !! instructions &&
{ instructions }
}