diff --git a/blocks/hooks/align.js b/blocks/hooks/align.js
index c323fb57073de0..b724a6ef4f45d1 100644
--- a/blocks/hooks/align.js
+++ b/blocks/hooks/align.js
@@ -7,7 +7,7 @@ import { assign, includes } from 'lodash';
/**
* WordPress dependencies
*/
-import { getWrapperDisplayName } from '@wordpress/element';
+import { createHigherOrderComponent } from '@wordpress/element';
import { addFilter } from '@wordpress/hooks';
import BlockControls from '../block-controls';
import BlockAlignmentToolbar from '../block-alignment-toolbar';
@@ -71,8 +71,8 @@ export function getBlockValidAlignments( blockName ) {
* @param {Function} BlockEdit Original component
* @return {Function} Wrapped component
*/
-export function withToolbarControls( BlockEdit ) {
- const WrappedBlockEdit = ( props ) => {
+export const withToolbarControls = createHigherOrderComponent( ( BlockEdit ) => {
+ return ( props ) => {
const validAlignments = getBlockValidAlignments( props.name );
const updateAlignment = ( nextAlign ) => props.setAttributes( { align: nextAlign } );
@@ -90,10 +90,7 @@ export function withToolbarControls( BlockEdit ) {
,
];
};
- WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'align' );
-
- return WrappedBlockEdit;
-}
+}, 'withToolbarControls' );
/**
* Override the default block element to add alignment wrapper props.
@@ -101,8 +98,8 @@ export function withToolbarControls( BlockEdit ) {
* @param {Function} BlockListBlock Original component
* @return {Function} Wrapped component
*/
-export function withAlign( BlockListBlock ) {
- const WrappedComponent = ( props ) => {
+export const withAlign = createHigherOrderComponent( ( BlockListBlock ) => {
+ return ( props ) => {
const { align } = props.block.attributes;
const validAlignments = getBlockValidAlignments( props.block.name );
@@ -113,11 +110,7 @@ export function withAlign( BlockListBlock ) {
return ;
};
-
- WrappedComponent.displayName = getWrapperDisplayName( BlockListBlock, 'align' );
-
- return WrappedComponent;
-}
+}, 'withAlign' );
/**
* Override props assigned to save component to inject alignment class name if
diff --git a/blocks/hooks/anchor.js b/blocks/hooks/anchor.js
index bc1dd47b401c46..65371a4088c433 100644
--- a/blocks/hooks/anchor.js
+++ b/blocks/hooks/anchor.js
@@ -6,7 +6,7 @@ import { assign } from 'lodash';
/**
* WordPress dependencies
*/
-import { getWrapperDisplayName } from '@wordpress/element';
+import { createHigherOrderComponent } from '@wordpress/element';
import { addFilter } from '@wordpress/hooks';
import { TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
@@ -56,8 +56,8 @@ export function addAttribute( settings ) {
*
* @return {string} Wrapped component.
*/
-export function withInspectorControl( BlockEdit ) {
- const WrappedBlockEdit = ( props ) => {
+export const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
+ return ( props ) => {
const hasAnchor = hasBlockSupport( props.name, 'anchor' ) && props.isSelected;
return [
,
@@ -75,10 +75,7 @@ export function withInspectorControl( BlockEdit ) {
,
];
};
- WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'anchor' );
-
- return WrappedBlockEdit;
-}
+}, 'withInspectorControl' );
/**
* Override props assigned to save component to inject anchor ID, if block
diff --git a/blocks/hooks/custom-class-name.js b/blocks/hooks/custom-class-name.js
index c0a5bc29c1feb3..a8a8fa07591e76 100644
--- a/blocks/hooks/custom-class-name.js
+++ b/blocks/hooks/custom-class-name.js
@@ -7,7 +7,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
-import { getWrapperDisplayName } from '@wordpress/element';
+import { createHigherOrderComponent } from '@wordpress/element';
import { addFilter } from '@wordpress/hooks';
import { TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
@@ -47,8 +47,8 @@ export function addAttribute( settings ) {
*
* @return {string} Wrapped component.
*/
-export function withInspectorControl( BlockEdit ) {
- const WrappedBlockEdit = ( props ) => {
+export const withInspectorControl = createHigherOrderComponent( ( BlockEdit ) => {
+ return ( props ) => {
const hasCustomClassName = hasBlockSupport( props.name, 'customClassName', true ) && props.isSelected;
return [
@@ -66,10 +66,7 @@ export function withInspectorControl( BlockEdit ) {
,
];
};
- WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'customClassName' );
-
- return WrappedBlockEdit;
-}
+}, 'withInspectorControl' );
/**
* Override props assigned to save component to inject anchor ID, if block
diff --git a/components/higher-order/if-condition/index.js b/components/higher-order/if-condition/index.js
index efab3a30359ca1..0ae3099810a1c4 100644
--- a/components/higher-order/if-condition/index.js
+++ b/components/higher-order/if-condition/index.js
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { getWrapperDisplayName } from '@wordpress/element';
+import { createHigherOrderComponent } from '@wordpress/element';
/**
* Higher-order component creator, creating a new component which renders if
@@ -11,18 +11,15 @@ import { getWrapperDisplayName } from '@wordpress/element';
*
* @return {Function} Higher-order component.
*/
-const ifCondition = ( predicate ) => ( WrappedComponent ) => {
- const EnhancedComponent = ( props ) => {
+const ifCondition = ( predicate ) => createHigherOrderComponent(
+ ( WrappedComponent ) => ( props ) => {
if ( ! predicate( props ) ) {
return null;
}
return ;
- };
-
- EnhancedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'ifCondition' );
-
- return EnhancedComponent;
-};
+ },
+ 'ifCondition'
+);
export default ifCondition;
diff --git a/components/higher-order/with-api-data/index.js b/components/higher-order/with-api-data/index.js
index 19c4e4910c19f4..29a24791ad854a 100644
--- a/components/higher-order/with-api-data/index.js
+++ b/components/higher-order/with-api-data/index.js
@@ -6,7 +6,7 @@ import { mapValues, reduce, forEach, noop } from 'lodash';
/**
* WordPress dependencies
*/
-import { Component, getWrapperDisplayName } from '@wordpress/element';
+import { Component, createHigherOrderComponent } from '@wordpress/element';
/**
* Internal dependencies
@@ -14,7 +14,7 @@ import { Component, getWrapperDisplayName } from '@wordpress/element';
import request, { getCachedResponse } from './request';
import { getRoute } from './routes';
-export default ( mapPropsToData ) => ( WrappedComponent ) => {
+export default ( mapPropsToData ) => createHigherOrderComponent( ( WrappedComponent ) => {
class APIDataComponent extends Component {
constructor( props, context ) {
super( ...arguments );
@@ -221,8 +221,6 @@ export default ( mapPropsToData ) => ( WrappedComponent ) => {
}
}
- APIDataComponent.displayName = getWrapperDisplayName( WrappedComponent, 'apiData' );
-
APIDataComponent.contextTypes = {
getAPISchema: noop,
getAPIPostTypeRestBaseMapping: noop,
@@ -230,4 +228,4 @@ export default ( mapPropsToData ) => ( WrappedComponent ) => {
};
return APIDataComponent;
-};
+}, 'withAPIData' );
diff --git a/components/higher-order/with-filters/index.js b/components/higher-order/with-filters/index.js
index 522e7bb358a20c..278bb325c76abf 100644
--- a/components/higher-order/with-filters/index.js
+++ b/components/higher-order/with-filters/index.js
@@ -6,7 +6,7 @@ import { debounce, uniqueId } from 'lodash';
/**
* WordPress dependencies
*/
-import { Component, getWrapperDisplayName } from '@wordpress/element';
+import { Component, createHigherOrderComponent } from '@wordpress/element';
import { addAction, applyFilters, removeAction } from '@wordpress/hooks';
const ANIMATION_FRAME_PERIOD = 16;
@@ -22,8 +22,8 @@ const ANIMATION_FRAME_PERIOD = 16;
* @return {Function} Higher-order component factory.
*/
export default function withFilters( hookName ) {
- return ( OriginalComponent ) => {
- class FilteredComponent extends Component {
+ return createHigherOrderComponent( ( OriginalComponent ) => {
+ return class FilteredComponent extends Component {
/** @inheritdoc */
constructor( props ) {
super( props );
@@ -62,9 +62,6 @@ export default function withFilters( hookName ) {
render() {
return ;
}
- }
- FilteredComponent.displayName = getWrapperDisplayName( OriginalComponent, 'filters' );
-
- return FilteredComponent;
- };
+ };
+ }, 'withFilters' );
}
diff --git a/components/higher-order/with-state/index.js b/components/higher-order/with-state/index.js
index b2c47819ed259f..4328407b268313 100644
--- a/components/higher-order/with-state/index.js
+++ b/components/higher-order/with-state/index.js
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { Component, getWrapperDisplayName } from '@wordpress/element';
+import { Component, createHigherOrderComponent } from '@wordpress/element';
/**
* A Higher Order Component used to provide and manage internal component state
@@ -11,9 +11,9 @@ import { Component, getWrapperDisplayName } from '@wordpress/element';
*
* @return {Component} Wrapped component.
*/
-function withState( initialState = {} ) {
- return ( OriginalComponent ) => {
- class WrappedComponent extends Component {
+export default function withState( initialState = {} ) {
+ return createHigherOrderComponent( ( OriginalComponent ) => {
+ return class WrappedComponent extends Component {
constructor() {
super( ...arguments );
@@ -31,12 +31,6 @@ function withState( initialState = {} ) {
/>
);
}
- }
-
- WrappedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'state' );
-
- return WrappedComponent;
- };
+ };
+ } );
}
-
-export default withState;
diff --git a/data/index.js b/data/index.js
index a6db5e8e908707..3b0f9638636163 100644
--- a/data/index.js
+++ b/data/index.js
@@ -9,7 +9,7 @@ import memoize from 'memize';
/**
* WordPress dependencies
*/
-import { Component, getWrapperDisplayName } from '@wordpress/element';
+import { Component, createHigherOrderComponent } from '@wordpress/element';
/**
* Internal dependencies
@@ -231,8 +231,8 @@ export function dispatch( reducerKey ) {
*
* @return {Component} Enhanced component with merged state data props.
*/
-export const withSelect = ( mapStateToProps ) => ( WrappedComponent ) => {
- class ComponentWithSelect extends Component {
+export const withSelect = ( mapStateToProps ) => createHigherOrderComponent( ( WrappedComponent ) => {
+ return class ComponentWithSelect extends Component {
constructor() {
super( ...arguments );
@@ -286,12 +286,8 @@ export const withSelect = ( mapStateToProps ) => ( WrappedComponent ) => {
render() {
return ;
}
- }
-
- ComponentWithSelect.displayName = getWrapperDisplayName( WrappedComponent, 'select' );
-
- return ComponentWithSelect;
-};
+ };
+}, 'withSelect' );
/**
* Higher-order component used to add dispatch props using registered action
@@ -305,8 +301,8 @@ export const withSelect = ( mapStateToProps ) => ( WrappedComponent ) => {
*
* @return {Component} Enhanced component with merged dispatcher props.
*/
-export const withDispatch = ( mapDispatchToProps ) => ( WrappedComponent ) => {
- class ComponentWithDispatch extends Component {
+export const withDispatch = ( mapDispatchToProps ) => createHigherOrderComponent( ( WrappedComponent ) => {
+ return class ComponentWithDispatch extends Component {
constructor() {
super( ...arguments );
@@ -345,12 +341,8 @@ export const withDispatch = ( mapDispatchToProps ) => ( WrappedComponent ) => {
render() {
return ;
}
- }
-
- ComponentWithDispatch.displayName = getWrapperDisplayName( WrappedComponent, 'dispatch' );
-
- return ComponentWithDispatch;
-};
+ };
+}, 'withDispatch' );
/**
* Returns true if the given argument appears to be a dispatchable action.
diff --git a/docs/deprecated.md b/docs/deprecated.md
index 2961419094e322..3e66262ce46a95 100644
--- a/docs/deprecated.md
+++ b/docs/deprecated.md
@@ -1,5 +1,9 @@
Gutenberg's deprecation policy is intended to support backwards-compatibility for two minor releases, when possible. The current deprecations are listed below and are grouped by _the version at which they will be removed completely_. If your plugin depends on these behaviors, you must update to the recommended alternative before the noted version.
+## 2.7.0
+
+- `wp.element.getWrapperDisplayName` function removed. Please use `wp.element.createHigherOrderComponent` instead.
+
## 2.6.0
- `wp.blocks.getBlockDefaultClassname` function removed. Please use `wp.blocks.getBlockDefaultClassName` instead.
diff --git a/edit-post/hooks/validate-use-once/index.js b/edit-post/hooks/validate-use-once/index.js
index 0efdbb5b1c1f77..6317a28971aff9 100644
--- a/edit-post/hooks/validate-use-once/index.js
+++ b/edit-post/hooks/validate-use-once/index.js
@@ -10,7 +10,7 @@ import { createBlock, getBlockType, findTransform, getBlockTransforms } from '@w
import { Button } from '@wordpress/components';
import { withSelect, withDispatch } from '@wordpress/data';
import { Warning } from '@wordpress/editor';
-import { compose, getWrapperDisplayName } from '@wordpress/element';
+import { compose, createHigherOrderComponent } from '@wordpress/element';
import { addFilter } from '@wordpress/hooks';
import { __ } from '@wordpress/i18n';
@@ -49,8 +49,8 @@ const enhance = compose(
} ) ),
);
-function withUseOnceValidation( BlockEdit ) {
- const WrappedBlockEdit = ( {
+const withUseOnceValidation = createHigherOrderComponent( ( BlockEdit ) => {
+ return enhance( ( {
originalBlockUid,
selectFirst,
...props
@@ -93,12 +93,8 @@ function withUseOnceValidation( BlockEdit ) {
{ __( 'This block may not be used more than once.' ) }
,
];
- };
-
- WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'useOnceValidation' );
-
- return enhance( WrappedBlockEdit );
-}
+ } );
+}, 'withUseOnceValidation' );
/**
* Given a base block name, returns the default block type to which to offer
diff --git a/editor/components/default-block-appender/test/__snapshots__/index.js.snap b/editor/components/default-block-appender/test/__snapshots__/index.js.snap
index ee1a646214cf18..f29565682dc3b5 100644
--- a/editor/components/default-block-appender/test/__snapshots__/index.js.snap
+++ b/editor/components/default-block-appender/test/__snapshots__/index.js.snap
@@ -36,7 +36,7 @@ exports[`DefaultBlockAppender should append a default block when input focused 1
value="Write your story"
/>
-
@@ -60,7 +60,7 @@ exports[`DefaultBlockAppender should match snapshot 1`] = `
value="Write your story"
/>
-
@@ -84,7 +84,7 @@ exports[`DefaultBlockAppender should optionally show without prompt 1`] = `
value=""
/>
-
diff --git a/element/index.js b/element/index.js
index 5f296bac93a6c6..d03da01bf1a15f 100644
--- a/element/index.js
+++ b/element/index.js
@@ -11,6 +11,11 @@ import {
isEmpty,
} from 'lodash';
+/**
+ * WordPress dependencies
+ */
+import { deprecated } from '@wordpress/utils';
+
/**
* Internal dependencies
*/
@@ -164,11 +169,38 @@ export { flowRight as compose };
* @return {string} Wrapped display name.
*/
export function getWrapperDisplayName( BaseComponent, wrapperName ) {
+ deprecated( 'getWrapperDisplayName', {
+ version: '2.7',
+ alternative: 'wp.element.createHigherOrderComponent',
+ plugin: 'Gutenberg',
+ } );
+
const { displayName = BaseComponent.name || 'Component' } = BaseComponent;
return `${ upperFirst( camelCase( wrapperName ) ) }(${ displayName })`;
}
+/**
+ * Given a function mapping a component to an enhanced component and modifier
+ * name, returns the enhanced component augmented with a generated displayName.
+ *
+ * @param {Function} mapComponentToEnhancedComponent Function mapping component
+ * to enhanced component.
+ * @param {string} modifierName Seed name from which to
+ * generated display name.
+ *
+ * @return {WPComponent} Component class with generated display name assigned.
+ */
+export function createHigherOrderComponent( mapComponentToEnhancedComponent, modifierName ) {
+ return ( OriginalComponent ) => {
+ const EnhancedComponent = mapComponentToEnhancedComponent( OriginalComponent );
+ const { displayName = OriginalComponent.name || 'Component' } = OriginalComponent;
+ EnhancedComponent.displayName = `${ upperFirst( camelCase( modifierName ) ) }(${ displayName })`;
+
+ return EnhancedComponent;
+ };
+}
+
/**
* Component used as equivalent of Fragment with unescaped HTML, in cases where
* it is desirable to render dangerous HTML without needing a wrapper element.
diff --git a/element/test/index.js b/element/test/index.js
index 7c0e2ed7e190c1..ee7396c5b5e2d8 100644
--- a/element/test/index.js
+++ b/element/test/index.js
@@ -9,10 +9,10 @@ import { shallow } from 'enzyme';
import {
Component,
createElement,
+ createHigherOrderComponent,
concatChildren,
renderToString,
switchChildrenNodeName,
- getWrapperDisplayName,
RawHTML,
} from '../';
@@ -123,42 +123,64 @@ describe( 'element', () => {
} );
} );
- describe( 'getWrapperDisplayName()', () => {
+ describe( 'createHigherOrderComponent', () => {
it( 'should use default name for anonymous function', () => {
- expect( getWrapperDisplayName( () =>
, 'test' ) ).toBe( 'Test(Component)' );
+ const TestComponent = createHigherOrderComponent(
+ OriginalComponent => OriginalComponent,
+ 'withTest'
+ )( () => );
+
+ expect( TestComponent.displayName ).toBe( 'WithTest(Component)' );
} );
it( 'should use camel case starting with upper for wrapper prefix ', () => {
- expect( getWrapperDisplayName( () => , 'one-two_threeFOUR' ) ).toBe( 'OneTwoThreeFour(Component)' );
+ const TestComponent = createHigherOrderComponent(
+ OriginalComponent => OriginalComponent,
+ 'with-one-two_threeFOUR'
+ )( () => );
+
+ expect( TestComponent.displayName ).toBe( 'WithOneTwoThreeFour(Component)' );
} );
it( 'should use function name', () => {
function SomeComponent() {
return ;
}
+ const TestComponent = createHigherOrderComponent(
+ OriginalComponent => OriginalComponent,
+ 'withTest'
+ )( SomeComponent );
- expect( getWrapperDisplayName( SomeComponent, 'test' ) ).toBe( 'Test(SomeComponent)' );
+ expect( TestComponent.displayName ).toBe( 'WithTest(SomeComponent)' );
} );
it( 'should use component class name', () => {
- class SomeComponent extends Component {
+ class SomeAnotherComponent extends Component {
render() {
return ;
}
}
+ const TestComponent = createHigherOrderComponent(
+ OriginalComponent => OriginalComponent,
+ 'withTest'
+ )( SomeAnotherComponent );
- expect( getWrapperDisplayName( SomeComponent, 'test' ) ).toBe( 'Test(SomeComponent)' );
+ expect( TestComponent.displayName ).toBe( 'WithTest(SomeAnotherComponent)' );
} );
it( 'should use displayName property', () => {
- class SomeComponent extends Component {
+ class SomeYetAnotherComponent extends Component {
render() {
return ;
}
}
- SomeComponent.displayName = 'CustomDisplayName';
+ SomeYetAnotherComponent.displayName = 'CustomDisplayName';
+ const TestComponent = createHigherOrderComponent(
+ OriginalComponent => OriginalComponent,
+ 'withTest'
+ )( SomeYetAnotherComponent );
- expect( getWrapperDisplayName( SomeComponent, 'test' ) ).toBe( 'Test(CustomDisplayName)' );
+ expect( TestComponent.displayName ).toBe( 'WithTest(CustomDisplayName)' );
} );
} );
diff --git a/lib/client-assets.php b/lib/client-assets.php
index 1694f971df4a10..ed348f0a6ad743 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-element',
gutenberg_url( 'element/build/index.js' ),
- array( 'react', 'react-dom' ),
+ array( 'react', 'react-dom', 'wp-utils' ),
filemtime( gutenberg_dir_path() . 'element/build/index.js' )
);
wp_register_script(
diff --git a/viewport/if-viewport-matches.js b/viewport/if-viewport-matches.js
index 4fb9c4daf190d0..6df11907fcbaf9 100644
--- a/viewport/if-viewport-matches.js
+++ b/viewport/if-viewport-matches.js
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { compose, getWrapperDisplayName } from '@wordpress/element';
+import { compose, createHigherOrderComponent } from '@wordpress/element';
import { ifCondition } from '@wordpress/components';
/**
@@ -19,17 +19,14 @@ import withViewportMatch from './with-viewport-match';
*
* @return {Function} Higher-order component.
*/
-const ifViewportMatches = ( query ) => ( WrappedComponent ) => {
- const EnhancedComponent = compose( [
+const ifViewportMatches = ( query ) => createHigherOrderComponent(
+ compose( [
withViewportMatch( {
isViewportMatch: query,
} ),
ifCondition( ( props ) => props.isViewportMatch ),
- ] )( WrappedComponent );
-
- EnhancedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'ifViewportMatches' );
-
- return EnhancedComponent;
-};
+ ] ),
+ 'ifViewportMatches'
+);
export default ifViewportMatches;
diff --git a/viewport/with-viewport-match.js b/viewport/with-viewport-match.js
index 129708a59ecfa0..238d2082ec730c 100644
--- a/viewport/with-viewport-match.js
+++ b/viewport/with-viewport-match.js
@@ -6,31 +6,27 @@ import { mapValues } from 'lodash';
/**
* WordPress dependencies
*/
-import { getWrapperDisplayName } from '@wordpress/element';
+import { createHigherOrderComponent } from '@wordpress/element';
import { withSelect } from '@wordpress/data';
/**
* Higher-order component creator, creating a new component which renders with
- * the given prop names, where the value passed to the underlying compoennt is
+ * the given prop names, where the value passed to the underlying component is
* the result of the query assigned as the object's value.
*
* @param {Object} queries Object of prop name to viewport query.
- * @param {string} propName Optional prop name to which result is assigned.
*
* @see isViewportMatch
*
* @return {Function} Higher-order component.
*/
-const withViewportMatch = ( queries ) => ( WrappedComponent ) => {
- const EnhancedComponent = withSelect( ( select ) => {
+const withViewportMatch = ( queries ) => createHigherOrderComponent(
+ withSelect( ( select ) => {
return mapValues( queries, ( query ) => {
return select( 'core/viewport' ).isViewportMatch( query );
} );
- } )( WrappedComponent );
-
- EnhancedComponent.displayName = getWrapperDisplayName( WrappedComponent, 'withViewportMatch' );
-
- return EnhancedComponent;
-};
+ } ),
+ 'withViewportMatch'
+);
export default withViewportMatch;