From 4af1b88fee0f804229d9db7ecc63261f53883654 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 2 Jun 2021 11:06:09 +1000 Subject: [PATCH] Display wide widgets as popovers in Customizer (#31736) --- .../src/legacy-widget/edit/form.js | 46 ++++++++++++++++++- .../src/legacy-widget/edit/index.js | 17 ++++++- .../src/legacy-widget/editor.scss | 8 ++++ packages/components/src/popover/index.js | 4 +- packages/components/src/popover/utils.js | 15 ++++-- .../customize-widgets/src/filters/index.js | 1 + .../src/filters/wide-widget-display.js | 26 +++++++++++ 7 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 packages/customize-widgets/src/filters/wide-widget-display.js diff --git a/packages/block-library/src/legacy-widget/edit/form.js b/packages/block-library/src/legacy-widget/edit/form.js index cae1bab701075..eb8abefb6dc58 100644 --- a/packages/block-library/src/legacy-widget/edit/form.js +++ b/packages/block-library/src/legacy-widget/edit/form.js @@ -1,3 +1,7 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; /** * WordPress dependencies */ @@ -5,7 +9,8 @@ import { useRef, useEffect } from '@wordpress/element'; import { useDispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; import { __ } from '@wordpress/i18n'; - +import { Popover } from '@wordpress/components'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ @@ -17,11 +22,14 @@ export default function Form( { id, idBase, instance, + isWide, onChangeInstance, onChangeHasPreview, } ) { const ref = useRef(); + const isMediumLargeViewport = useViewportMatch( 'small' ); + // We only want to remount the control when the instance changes // *externally*. For example, if the user performs an undo. To do this, we // keep track of changes made to instance by the control itself and then @@ -68,7 +76,41 @@ export default function Form( { control.destroy(); }; - }, [ id, idBase, instance, onChangeInstance, onChangeHasPreview ] ); + }, [ + id, + idBase, + instance, + onChangeInstance, + onChangeHasPreview, + isMediumLargeViewport, + ] ); + + if ( isWide && isMediumLargeViewport ) { + return ( +
+ { isVisible && ( +

+ { title } +

+ ) } + + + +
+ ); + } return (
+
{ ! id && ! idBase ? ( ) : ( @@ -77,6 +90,7 @@ function NotEmpty( { setAttributes, clientId, isSelected, + isWide = false, } ) { const [ hasPreview, setHasPreview ] = useState( null ); @@ -168,6 +182,7 @@ function NotEmpty( { id={ id } idBase={ idBase } instance={ instance } + isWide={ isWide } onChangeInstance={ setInstance } onChangeHasPreview={ setHasPreview } /> diff --git a/packages/block-library/src/legacy-widget/editor.scss b/packages/block-library/src/legacy-widget/editor.scss index 1282f2a528be1..710e4d905879c 100644 --- a/packages/block-library/src/legacy-widget/editor.scss +++ b/packages/block-library/src/legacy-widget/editor.scss @@ -86,3 +86,11 @@ margin: 0 0 5px; font-weight: 500; } + +// When wide widget is selected it opens in a popover but its container should still have a bit of height. +.is-selected { + .wp-block-legacy-widget__container { + padding: $grid-unit-10 $grid-unit-15; + min-height: 50px; + } +} diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index fa29974e28cf8..3d2d3e650c4e8 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -261,6 +261,7 @@ const Popover = ( __unstableObserveElement, __unstableBoundaryParent, __unstableForcePosition, + __unstableForceXAlignment, /* eslint-enable no-unused-vars */ ...contentProps }, @@ -354,7 +355,8 @@ const Popover = ( containerRef.current, relativeOffsetTop, boundaryElement, - __unstableForcePosition + __unstableForcePosition, + __unstableForceXAlignment ); if ( diff --git a/packages/components/src/popover/utils.js b/packages/components/src/popover/utils.js index 3d23ae71fb211..f7021198085a2 100644 --- a/packages/components/src/popover/utils.js +++ b/packages/components/src/popover/utils.js @@ -21,6 +21,7 @@ const HEIGHT_OFFSET = 10; // used by the arrow and a bit of empty space * @param {string} chosenYAxis yAxis to be used. * @param {Element} boundaryElement Boundary element. * @param {boolean} forcePosition Don't adjust position based on anchor. + * @param {boolean} forceXAlignment Don't adjust alignment based on YAxis * * @return {Object} Popover xAxis position and constraints. */ @@ -32,7 +33,8 @@ export function computePopoverXAxisPosition( stickyBoundaryElement, chosenYAxis, boundaryElement, - forcePosition + forcePosition, + forceXAlignment ) { const { width } = contentSize; @@ -64,7 +66,7 @@ export function computePopoverXAxisPosition( if ( corner === 'right' ) { leftAlignmentX = anchorRect.right; - } else if ( chosenYAxis !== 'middle' ) { + } else if ( chosenYAxis !== 'middle' && ! forceXAlignment ) { leftAlignmentX = anchorMidPoint; } @@ -72,7 +74,7 @@ export function computePopoverXAxisPosition( if ( corner === 'left' ) { rightAlignmentX = anchorRect.left; - } else if ( chosenYAxis !== 'middle' ) { + } else if ( chosenYAxis !== 'middle' && ! forceXAlignment ) { rightAlignmentX = anchorMidPoint; } @@ -285,6 +287,7 @@ export function computePopoverYAxisPosition( * relative positioned parent container. * @param {Element} boundaryElement Boundary element. * @param {boolean} forcePosition Don't adjust position based on anchor. + * @param {boolean} forceXAlignment Don't adjust alignment based on YAxis * * @return {Object} Popover position and constraints. */ @@ -296,7 +299,8 @@ export function computePopoverPosition( anchorRef, relativeOffsetTop, boundaryElement, - forcePosition + forcePosition, + forceXAlignment ) { const [ yAxis, xAxis = 'center', corner ] = position.split( ' ' ); @@ -318,7 +322,8 @@ export function computePopoverPosition( stickyBoundaryElement, yAxisPosition.yAxis, boundaryElement, - forcePosition + forcePosition, + forceXAlignment ); return { diff --git a/packages/customize-widgets/src/filters/index.js b/packages/customize-widgets/src/filters/index.js index fdae4d488b83d..07b68a610103a 100644 --- a/packages/customize-widgets/src/filters/index.js +++ b/packages/customize-widgets/src/filters/index.js @@ -3,3 +3,4 @@ */ import './move-to-sidebar'; import './replace-media-upload'; +import './wide-widget-display'; diff --git a/packages/customize-widgets/src/filters/wide-widget-display.js b/packages/customize-widgets/src/filters/wide-widget-display.js new file mode 100644 index 0000000000000..abcaa3514b640 --- /dev/null +++ b/packages/customize-widgets/src/filters/wide-widget-display.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { createHigherOrderComponent } from '@wordpress/compose'; +import { addFilter } from '@wordpress/hooks'; + +const { wp } = window; + +const withWideWidgetDisplay = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const { idBase } = props.attributes; + const isWide = + wp.customize.Widgets.data.availableWidgets.find( + ( widget ) => widget.id_base === idBase + )?.is_wide ?? false; + + return ; + }, + 'withWideWidgetDisplay' +); + +addFilter( + 'editor.BlockEdit', + 'core/customize-widgets/wide-widget-display', + withWideWidgetDisplay +);