diff --git a/patterns/header-vertical.php b/patterns/header-vertical.php
index d51e9476..e76588a4 100644
--- a/patterns/header-vertical.php
+++ b/patterns/header-vertical.php
@@ -11,28 +11,24 @@
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/blocks/both-sides-content/block.json b/src/blocks/both-sides-content/block.json
index 0fa72b16..4d850c14 100644
--- a/src/blocks/both-sides-content/block.json
+++ b/src/blocks/both-sides-content/block.json
@@ -21,6 +21,7 @@
}
},
"supports": {
+ "inserter": false,
"className": false,
"anchor": true,
"color": {
diff --git a/src/blocks/both-sides/edit.js b/src/blocks/both-sides/edit.js
index 6764815d..60955e60 100644
--- a/src/blocks/both-sides/edit.js
+++ b/src/blocks/both-sides/edit.js
@@ -1,8 +1,24 @@
import classnames from 'classnames';
-import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
+import {
+ InnerBlocks,
+ useBlockProps,
+ useInnerBlocksProps,
+ store as blockEditorStore,
+} from '@wordpress/block-editor';
+
+import { useSelect } from '@wordpress/data';
+
+export default function ( props ) {
+ const { clientId } = props;
+
+ const hasInnerBlocks = useSelect(
+ ( select ) =>
+ !! select( blockEditorStore ).getBlock( clientId )?.innerBlocks
+ ?.length,
+ [ clientId ]
+ );
-export default function () {
const blockProps = useBlockProps();
blockProps[ 'data-unitone-layout' ] = classnames(
'both-sides',
@@ -10,11 +26,9 @@ export default function () {
);
const innerBlocksProps = useInnerBlocksProps( blockProps, {
- templateLock: 'all',
- template: [
- [ 'unitone/both-sides-content' ],
- [ 'unitone/both-sides-content' ],
- ],
+ renderAppender: hasInnerBlocks
+ ? InnerBlocks.DefaultBlockAppender
+ : InnerBlocks.ButtonBlockAppender,
} );
return
;
diff --git a/src/js/editor/hooks/flex-basis.js b/src/js/editor/hooks/flex-basis.js
new file mode 100644
index 00000000..f0001b4b
--- /dev/null
+++ b/src/js/editor/hooks/flex-basis.js
@@ -0,0 +1,95 @@
+import { hasBlockSupport } from '@wordpress/blocks';
+import { TextControl } from '@wordpress/components';
+
+export function hasFlexBasisValue( props ) {
+ return props.attributes?.unitone?.flexBasis !== undefined;
+}
+
+export function resetFlexBasis( { attributes = {}, setAttributes } ) {
+ delete attributes?.unitone?.flexBasis;
+ const newUnitone = { ...attributes?.unitone };
+
+ setAttributes( {
+ unitone: !! Object.keys( newUnitone ).length ? newUnitone : undefined,
+ } );
+}
+
+export function useIsFlexBasisDisabled( {
+ name: blockName,
+ attributes: { __unstableUnitoneSupports },
+} = {} ) {
+ return (
+ ! hasBlockSupport( blockName, 'unitone.flexBasis' ) &&
+ ! __unstableUnitoneSupports?.flexBasis
+ );
+}
+
+export function FlexBasisEdit( props ) {
+ const {
+ label,
+ attributes: { unitone },
+ setAttributes,
+ } = props;
+
+ return (
+
{
+ const newUnitone = {
+ ...unitone,
+ flexBasis: newValue || undefined,
+ };
+ if ( null == newUnitone.flexBasis ) {
+ delete newUnitone.flexBasis;
+ }
+
+ setAttributes( {
+ unitone: !! Object.keys( newUnitone ).length
+ ? newUnitone
+ : undefined,
+ } );
+ } }
+ />
+ );
+}
+
+export function saveFlexBasisProp( extraProps, blockType, attributes ) {
+ if (
+ ! hasBlockSupport( blockType, 'unitone.flexBasis' ) &&
+ ! attributes?.__unstableUnitoneSupports?.flexBasis
+ ) {
+ delete attributes?.unitone?.flexBasis;
+ if (
+ !! attributes?.unitone &&
+ ! Object.keys( attributes?.unitone ).length
+ ) {
+ delete attributes?.unitone;
+ }
+ return extraProps;
+ }
+
+ if ( undefined === attributes?.unitone?.flexBasis ) {
+ return extraProps;
+ }
+
+ extraProps.style = {
+ ...extraProps.style,
+ '--unitone--flex-basis': attributes?.unitone?.flexBasis,
+ };
+
+ return extraProps;
+}
+
+export function editFlexBasisProp( settings ) {
+ const existingGetEditWrapperProps = settings.getEditWrapperProps;
+ settings.getEditWrapperProps = ( attributes ) => {
+ let props = {};
+ if ( existingGetEditWrapperProps ) {
+ props = existingGetEditWrapperProps( attributes );
+ }
+ return saveFlexBasisProp( props, settings, attributes );
+ };
+
+ return settings;
+}
diff --git a/src/js/editor/hooks/layout.js b/src/js/editor/hooks/layout.js
index f1c1fdcc..940febec 100644
--- a/src/js/editor/hooks/layout.js
+++ b/src/js/editor/hooks/layout.js
@@ -46,6 +46,14 @@ import {
editBlockAlignProp,
} from './block-align';
+import {
+ useIsFlexBasisDisabled,
+ hasFlexBasisValue,
+ resetFlexBasis,
+ FlexBasisEdit,
+ editFlexBasisProp,
+} from './flex-basis';
+
import {
useIsMaxWidthDisabled,
hasMaxWidthValue,
@@ -75,6 +83,7 @@ export {
editJustifyContentProp,
editJustifyContentColumnProp,
editBlockAlignProp,
+ editFlexBasisProp,
editMaxWidthProp,
editMinHeightProp,
editAutoRepeatProp,
@@ -86,6 +95,7 @@ export function LayoutPanel( props ) {
useIsJustifyContentColumnDisabled( props );
const isAlignItemsDisabled = useIsAlignItemsDisabled( props );
const isBlockAlignDisabled = useIsBlockAlignDisabled( props );
+ const isFlexBasisDisabled = useIsFlexBasisDisabled( props );
const isMaxWidthDisabled = useIsMaxWidthDisabled( props );
const isMinHeightDisabled = useIsMinHeightDisabled( props );
const isAutoRepeatDisabled = useIsAutoRepeatDisabled( props );
@@ -95,6 +105,7 @@ export function LayoutPanel( props ) {
isJustifyContentColumnDisabled &&
isAlignItemsDisabled &&
isBlockAlignDisabled &&
+ isFlexBasisDisabled &&
isMaxWidthDisabled &&
isMinHeightDisabled &&
isAutoRepeatDisabled
@@ -127,6 +138,7 @@ export function LayoutPanel( props ) {
! isJustifyContentColumnDisabled ||
! isAlignItemsDisabled ||
! isBlockAlignDisabled ||
+ ! isFlexBasisDisabled ||
! isMaxWidthDisabled ||
! isMinHeightDisabled ||
! isAutoRepeatDisabled ) && (
@@ -217,6 +229,28 @@ export function LayoutPanel( props ) {
) }
+ { ! isFlexBasisDisabled && (
+ hasFlexBasisValue( props ) }
+ label={ __( 'Recommended width', 'unitone' ) }
+ onDeselect={ () => resetFlexBasis( props ) }
+ isShownByDefault
+ >
+
+ { __(
+ 'Recommended width',
+ 'unitone'
+ ) }
+ : flex-basis
+ >
+ }
+ />
+
+ ) }
+
{ ! isMaxWidthDisabled && (
hasMaxWidthValue( props ) }
diff --git a/src/js/editor/hooks/max-width.js b/src/js/editor/hooks/max-width.js
index b037c665..b7dc613e 100644
--- a/src/js/editor/hooks/max-width.js
+++ b/src/js/editor/hooks/max-width.js
@@ -14,8 +14,14 @@ export function resetMaxWidth( { attributes = {}, setAttributes } ) {
} );
}
-export function useIsMaxWidthDisabled( { name: blockName } = {} ) {
- return ! hasBlockSupport( blockName, 'unitone.maxWidth' );
+export function useIsMaxWidthDisabled( {
+ name: blockName,
+ attributes: { __unstableUnitoneSupports },
+} = {} ) {
+ return (
+ ! hasBlockSupport( blockName, 'unitone.maxWidth' ) &&
+ ! __unstableUnitoneSupports?.maxWidth
+ );
}
export function MaxWidthEdit( props ) {
@@ -49,7 +55,17 @@ export function MaxWidthEdit( props ) {
}
export function saveMaxWidthProp( extraProps, blockType, attributes ) {
- if ( ! hasBlockSupport( blockType, 'unitone.maxWidth' ) ) {
+ if (
+ ! hasBlockSupport( blockType, 'unitone.maxWidth' ) &&
+ ! attributes?.__unstableUnitoneSupports?.maxWidth
+ ) {
+ delete attributes?.unitone?.maxWidth;
+ if (
+ !! attributes?.unitone &&
+ ! Object.keys( attributes?.unitone ).length
+ ) {
+ delete attributes?.unitone;
+ }
return extraProps;
}
@@ -76,10 +92,6 @@ export function saveMaxWidthProp( extraProps, blockType, attributes ) {
}
export function editMaxWidthProp( settings ) {
- if ( ! hasBlockSupport( settings, 'unitone.maxWidth' ) ) {
- return settings;
- }
-
const existingGetEditWrapperProps = settings.getEditWrapperProps;
settings.getEditWrapperProps = ( attributes ) => {
let props = {};
diff --git a/src/js/editor/hooks/style.js b/src/js/editor/hooks/style.js
index d09ee94d..5c85d26c 100644
--- a/src/js/editor/hooks/style.js
+++ b/src/js/editor/hooks/style.js
@@ -5,6 +5,8 @@
import { hasBlockSupport } from '@wordpress/blocks';
import { createHigherOrderComponent } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
+import { useSelect } from '@wordpress/data';
+import { store as blockEditorStore } from '@wordpress/block-editor';
import {
DimensionsPanel,
@@ -24,6 +26,7 @@ import {
editMaxWidthProp,
editMinHeightProp,
editAutoRepeatProp,
+ editFlexBasisProp,
} from './layout';
import {
@@ -37,47 +40,40 @@ import { DividerPanel, editDividerProp, editDividerTypeProp } from './divider';
import { PositionPanel, editPositionProp } from './position';
function addEditProps( settings ) {
- if ( !! settings.supports?.typography ) {
+ if ( !! settings.supports?.typography?.fontSize ) {
settings = editFluidTypographyProp( settings );
- settings = editHalfLeadingProp( settings );
}
- if ( !! settings.supports?.unitone ) {
- settings = editAlignItemsProp( settings );
- settings = editBlockAlignProp( settings );
- settings = editDividerProp( settings );
- settings = editDividerTypeProp( settings );
- settings = editGapProp( settings );
- settings = editGuttersProp( settings );
- settings = editJustifyContentColumnProp( settings );
- settings = editJustifyContentProp( settings );
- settings = editMaxWidthProp( settings );
- settings = editMinHeightProp( settings );
- settings = editAutoRepeatProp( settings );
- settings = editNegativeProp( settings );
- settings = editOverflowProp( settings );
- settings = editPaddingProp( settings );
- settings = editPositionProp( settings );
+ if ( !! settings.supports?.typography?.lineHeight ) {
+ settings = editHalfLeadingProp( settings );
}
+ settings = editAlignItemsProp( settings );
+ settings = editBlockAlignProp( settings );
+ settings = editDividerProp( settings );
+ settings = editDividerTypeProp( settings );
+ settings = editGapProp( settings );
+ settings = editGuttersProp( settings );
+ settings = editJustifyContentColumnProp( settings );
+ settings = editJustifyContentProp( settings );
+ settings = editMaxWidthProp( settings );
+ settings = editMinHeightProp( settings );
+ settings = editAutoRepeatProp( settings );
+ settings = editFlexBasisProp( settings );
+ settings = editNegativeProp( settings );
+ settings = editOverflowProp( settings );
+ settings = editPaddingProp( settings );
+ settings = editPositionProp( settings );
+
return settings;
}
const addAttribute = ( settings ) => {
- if (
- ! settings.supports?.typography?.fontSize &&
- ! settings.supports?.unitone
- ) {
- return settings;
- }
-
- if ( ! settings.attributes?.unitone ) {
- Object.assign( settings.attributes, {
- unitone: {
- type: 'object',
- },
- } );
- }
+ Object.assign( settings.attributes, {
+ unitone: {
+ type: 'object',
+ },
+ } );
return settings;
};
@@ -87,7 +83,8 @@ const withInspectorControls = createHigherOrderComponent( ( BlockEdit ) => {
if (
! hasBlockSupport( props.name, 'typography.fontSize' ) &&
! hasBlockSupport( props.name, 'typography.lineHeight' ) &&
- ! hasBlockSupport( props.name, 'unitone' )
+ ! hasBlockSupport( props.name, 'unitone' ) &&
+ ! props.attributes?.__unstableUnitoneSupports
) {
return ;
}
@@ -101,7 +98,8 @@ const withInspectorControls = createHigherOrderComponent( ( BlockEdit ) => {
) }
- { hasBlockSupport( props.name, 'unitone' ) && (
+ { ( hasBlockSupport( props.name, 'unitone' ) ||
+ !! props.attributes?.__unstableUnitoneSupports ) && (
<>
@@ -132,3 +130,49 @@ addFilter(
'unitone/with-inspector-controls',
withInspectorControls
);
+
+/**
+ * Add parent block name prop.
+ */
+const withChildBlockAttributes = createHigherOrderComponent(
+ ( BlockListBlock ) => {
+ return ( props ) => {
+ const { getBlockParents, getBlock } = useSelect(
+ ( select ) => {
+ return select( blockEditorStore );
+ },
+ [ props.clientId ]
+ );
+
+ const blockParents = getBlockParents( props.clientId );
+ if ( 0 < blockParents.length ) {
+ const parentClientId = blockParents[ blockParents.length - 1 ];
+ if ( !! parentClientId ) {
+ const parentBlock = getBlock( parentClientId );
+ if ( 'unitone/both-sides' === parentBlock?.name ) {
+ const newProps = {
+ ...props,
+ attributes: {
+ ...props.attributes,
+ __unstableUnitoneSupports: {
+ flexBasis: true,
+ },
+ },
+ };
+
+ return ;
+ }
+ }
+ }
+
+ return ;
+ };
+ },
+ 'withClientIdClassName'
+);
+
+addFilter(
+ 'editor.BlockListBlock',
+ 'unitone/with-child-block-attributes',
+ withChildBlockAttributes
+);