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