diff --git a/components/popover/index.js b/components/popover/index.js
index f10e52f2d60ab7..48b82a1fa2a573 100644
--- a/components/popover/index.js
+++ b/components/popover/index.js
@@ -9,6 +9,7 @@ import { isEqual, noop } from 'lodash';
*/
import { Component } from '@wordpress/element';
import { focus, keycodes } from '@wordpress/utils';
+import { withViewportMatch } from '@wordpress/viewport';
/**
* Internal dependencies
@@ -29,7 +30,6 @@ const { ESCAPE } = keycodes;
* @type {String}
*/
const SLOT_NAME = 'Popover';
-const isMobile = () => window.innerWidth < 782;
class Popover extends Component {
constructor() {
@@ -47,7 +47,6 @@ class Popover extends Component {
this.state = {
forcedYAxis: null,
forcedXAxis: null,
- isMobile: false,
};
}
@@ -140,28 +139,17 @@ class Popover extends Component {
}
setOffset() {
- const { getAnchorRect = this.getAnchorRect, expandOnMobile = false } = this.props;
+ const { getAnchorRect = this.getAnchorRect, isMobile, expandOnMobile = false } = this.props;
const { popover } = this.nodes;
- if ( isMobile() && expandOnMobile ) {
+ if ( isMobile && expandOnMobile ) {
popover.style.left = 0;
popover.style.top = 0;
popover.style.right = 0;
popover.style.bottom = 0;
- if ( ! this.state.isMobile ) {
- this.setState( {
- isMobile: true,
- } );
- }
return;
}
- if ( this.state.isMobile ) {
- this.setState( {
- isMobile: false,
- } );
- }
-
const [ yAxis, xAxis ] = this.getPositions();
const isTop = 'top' === yAxis;
const isLeft = 'left' === xAxis;
@@ -250,6 +238,7 @@ class Popover extends Component {
range,
focusOnMount,
getAnchorRect,
+ isMobile,
expandOnMobile,
/* eslint-enable no-unused-vars */
...contentProps
@@ -262,7 +251,7 @@ class Popover extends Component {
'is-' + yAxis,
'is-' + xAxis,
{
- 'is-mobile': this.state.isMobile,
+ 'is-mobile': isMobile,
}
);
@@ -278,7 +267,7 @@ class Popover extends Component {
{ ...contentProps }
onKeyDown={ this.maybeClose }
>
- { this.state.isMobile && (
+ { isMobile && (
@@ -316,6 +305,17 @@ Popover.contextTypes = {
getSlot: noop,
};
+const _Popover = Popover;
+
+Popover = withViewportMatch( {
+ isMobile: '< small',
+} )( Popover );
+
+// TODO: This is a useful pattern for retrieving the unmodified component from
+// within unit tests, and might be something to consider building into a common
+// `createHigherOrderComponent` helper function (along with `displayName`).
+Popover.WrappedComponent = _Popover;
+
Popover.Slot = () => ;
export default Popover;
diff --git a/components/popover/test/index.js b/components/popover/test/index.js
index 8fa4b179a2ed7e..901e5566bd9e53 100644
--- a/components/popover/test/index.js
+++ b/components/popover/test/index.js
@@ -7,7 +7,9 @@ import { noop } from 'lodash';
/**
* Internal dependencies
*/
-import Popover from '../';
+import EnhancedPopover from '../';
+
+const Popover = EnhancedPopover.WrappedComponent;
describe( 'Popover', () => {
describe( '#componentDidUpdate()', () => {
diff --git a/components/tooltip/test/index.js b/components/tooltip/test/index.js
index 57e9b1a674eee4..4cf7abc361edf6 100644
--- a/components/tooltip/test/index.js
+++ b/components/tooltip/test/index.js
@@ -7,6 +7,7 @@ import { shallow, mount } from 'enzyme';
* Internal dependencies
*/
import Tooltip from '../';
+import Popover from '../../popover';
describe( 'Tooltip', () => {
describe( '#render()', () => {
@@ -42,11 +43,11 @@ describe( 'Tooltip', () => {
wrapper.setState( { isOver: true } );
const button = wrapper.find( 'button' );
- const popover = wrapper.find( 'Popover' );
+ const popover = wrapper.find( Popover );
expect( wrapper.type() ).toBe( 'button' );
expect( button.children() ).toHaveLength( 2 );
expect( button.childAt( 0 ).text() ).toBe( 'Hover Me!' );
- expect( button.childAt( 1 ).name() ).toBe( 'Popover' );
+ expect( button.childAt( 1 ).type() ).toBe( Popover );
expect( popover.prop( 'focusOnMount' ) ).toBe( false );
expect( popover.prop( 'position' ) ).toBe( 'bottom right' );
expect( popover.children().text() ).toBe( 'Help text' );
@@ -69,14 +70,14 @@ describe( 'Tooltip', () => {
const button = wrapper.find( 'button' );
button.simulate( 'focus', event );
- const popover = wrapper.find( 'Popover' );
+ const popover = wrapper.find( Popover );
expect( originalFocus ).toHaveBeenCalledWith( event );
expect( wrapper.state( 'isOver' ) ).toBe( true );
expect( popover ).toHaveLength( 1 );
} );
it( 'should show popover on delayed mouseenter', () => {
- const expectPopoverVisible = ( wrapper, visible ) => expect( wrapper.find( 'Popover' ) ).toHaveLength( visible ? 1 : 0 );
+ const expectPopoverVisible = ( wrapper, visible ) => expect( wrapper.find( Popover ) ).toHaveLength( visible ? 1 : 0 );
// Mount: Issues with using `setState` asynchronously with shallow-
// rendered components: https://github.com/airbnb/enzyme/issues/450
@@ -135,7 +136,7 @@ describe( 'Tooltip', () => {
expect( originalMouseEnter ).toHaveBeenCalled();
- const popover = wrapper.find( 'Popover' );
+ const popover = wrapper.find( Popover );
wrapper.instance().delayedSetIsOver.flush();
expect( wrapper.state( 'isOver' ) ).toBe( false );
expect( popover ).toHaveLength( 0 );
@@ -162,7 +163,7 @@ describe( 'Tooltip', () => {
wrapper.instance().delayedSetIsOver.flush();
- const popover = wrapper.find( 'Popover' );
+ const popover = wrapper.find( Popover );
expect( wrapper.state( 'isOver' ) ).toBe( false );
expect( popover ).toHaveLength( 0 );
} );
diff --git a/lib/client-assets.php b/lib/client-assets.php
index 72d9a2bc8785d8..6531357fdc6fb4 100644
--- a/lib/client-assets.php
+++ b/lib/client-assets.php
@@ -141,7 +141,7 @@ function gutenberg_register_scripts_and_styles() {
wp_register_script(
'wp-components',
gutenberg_url( 'components/build/index.js' ),
- array( 'wp-element', 'wp-i18n', 'wp-utils', 'wp-hooks', 'wp-api-request', 'moment' ),
+ array( 'wp-element', 'wp-i18n', 'wp-utils', 'wp-hooks', 'wp-api-request', 'wp-viewport', 'moment' ),
filemtime( gutenberg_dir_path() . 'components/build/index.js' )
);
wp_register_script(
@@ -161,7 +161,7 @@ function gutenberg_register_scripts_and_styles() {
wp_register_script(
'wp-viewport',
gutenberg_url( 'viewport/build/index.js' ),
- array( 'wp-element', 'wp-data', 'wp-components' ),
+ array( 'wp-element', 'wp-data' ),
filemtime( gutenberg_dir_path() . 'viewport/build/index.js' )
);
// Loading the old editor and its config to ensure the classic block works as expected.
diff --git a/viewport/if-viewport-matches.js b/viewport/if-viewport-matches.js
index 4fb9c4daf190d0..4d26a1940f3744 100644
--- a/viewport/if-viewport-matches.js
+++ b/viewport/if-viewport-matches.js
@@ -2,7 +2,25 @@
* WordPress dependencies
*/
import { compose, getWrapperDisplayName } from '@wordpress/element';
-import { ifCondition } from '@wordpress/components';
+
+// TEMPORARY: A circular dependency exists between `@wordpress/components`
+// and `@wordpress/viewport` (Popover -> withViewportMatch, ifViewportMatches
+// -> ifCondition).
+
+// import { ifCondition } from '@wordpress/components';
+const ifCondition = ( predicate ) => ( WrappedComponent ) => {
+ const EnhancedComponent = ( props ) => {
+ if ( ! predicate( props ) ) {
+ return null;
+ }
+
+ return ;
+ };
+
+ EnhancedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'ifCondition' );
+
+ return EnhancedComponent;
+};
/**
* Internal dependencies