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