{
options.map( ( option, index ) => {
return (
@@ -220,7 +282,9 @@ class AssociationField extends Component {
- { option.title }
+
+ { option.title }
+
@@ -368,10 +432,15 @@ function handler( props ) {
switch ( type ) {
case 'FETCH_OPTIONS':
+ setState( {
+ isLoading: true
+ } );
+
// eslint-disable-next-line
const request = window.jQuery.get( window.ajaxurl, {
action: 'carbon_fields_fetch_association_options',
term: payload.queryTerm,
+ page: payload.page || 1,
container_id: props.containerId,
field_name: hierarchyResolver()
}, null, 'json' );
@@ -382,7 +451,7 @@ function handler( props ) {
request.done( ( response ) => {
if ( response && response.success ) {
setState( {
- options: response.data.options,
+ options: payload.type === 'replace' ? response.data.options : [ ...payload.options, ...response.data.options ],
totalOptionsCount: response.data.total_options
} );
} else {
@@ -391,6 +460,11 @@ function handler( props ) {
} );
request.fail( errorHandler );
+ request.always( () => {
+ setState( {
+ isLoading: false
+ } );
+ } );
break;
case 'FETCH_SELECTED_OPTIONS':
@@ -399,7 +473,7 @@ function handler( props ) {
'get',
{
container_id: props.containerId,
- options: props.value,
+ options: props.value.map( ( option ) => `${ option.id }:${ option.type }:${ option.subtype }` ).join( ';' ),
field_id: hierarchyResolver()
}
)
@@ -418,7 +492,9 @@ const applyWithState = withState( {
options: [],
selectedOptions: [],
totalOptionsCount: 0,
- queryTerm: ''
+ queryTerm: '',
+ page: 1,
+ isLoading: false
} );
const applyWithEffects = withEffects( aperture, { handler } );
diff --git a/packages/core/fields/association/style.scss b/packages/core/fields/association/style.scss
index df0d1af27..889d06c16 100644
--- a/packages/core/fields/association/style.scss
+++ b/packages/core/fields/association/style.scss
@@ -5,17 +5,49 @@
.cf-association__bar {
position: relative;
z-index: 1;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-direction: row;
+ border-color: $wp-color-gray-light-500;
+ border-style: solid;
+ border-width: 1px 1px 0;
+ box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.07 );
+
+ .cf-search-input {
+ flex: 1 1 auto;
+ }
+
+ .cf-search-input__inner {
+ border: 0;
+ box-shadow: none;
+
+ &:focus {
+ border-color: none;
+ box-shadow: none;
+ outline: none;
+ }
+ }
+
+ &:focus-within {
+ border-color: #5b9dd9;
+ box-shadow: 0 0 2px rgba( 30, 140, 190, 0.8 );
+ outline: 2px solid transparent;
+ }
}
.cf-association__counter {
- position: absolute;
- top: 50%;
- right: 8px;
font-size: 12px;
- line-height: 1;
color: $wp-color-dark-gray;
- transform: translateY(-50%);
pointer-events: none;
+ margin-right: 5px;
+ margin-left: 5px;
+}
+
+.cf-association__spinner {
+ float: none;
+ margin: 0;
+ margin-left: 5px;
}
.cf-association__cols {
@@ -23,7 +55,7 @@
position: relative;
z-index: 0;
display: flex;
- border-width: 0 1px 1px;
+ border-width: 1px;
border-style: solid;
border-color: $wp-color-gray-light-500;
@@ -83,12 +115,8 @@
}
.cf-association__option-title {
- overflow: hidden;
- font-size: $wp-font-size;
- line-height: $wp-line-height;
- color: $wp-color-base-gray;
- white-space: nowrap;
- text-overflow: ellipsis;
+ flex: 1;
+ position: relative;
margin-right: $size-base;
.cf-association__option--selected & {
@@ -96,6 +124,20 @@
}
}
+.cf-association__option-title-inner {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ font-size: $wp-font-size;
+ line-height: $wp-line-height;
+ color: $wp-color-base-gray;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ transform: translateY(-50%);
+}
+
.cf-association__option-type {
font-size: 9px;
line-height: 1;
diff --git a/packages/metaboxes/containers/index.js b/packages/metaboxes/containers/index.js
index d1d13a635..e86e3d171 100644
--- a/packages/metaboxes/containers/index.js
+++ b/packages/metaboxes/containers/index.js
@@ -45,7 +45,10 @@ export function renderContainer( container, context ) {
if ( node ) {
render(
,
- node
+ node,
+ () => {
+ node.dataset.mounted = true;
+ }
);
} else {
// eslint-disable-next-line no-console
diff --git a/packages/metaboxes/index.js b/packages/metaboxes/index.js
index 4f4fe1832..4d85d20c1 100644
--- a/packages/metaboxes/index.js
+++ b/packages/metaboxes/index.js
@@ -13,6 +13,11 @@ import initializeMonitors from './monitors';
import initializeContainers from './containers';
import isGutenberg from './utils/is-gutenberg';
+/**
+ * Public API.
+ */
+export { registerContainerType, getContainerType } from './containers/registry';
+
/**
* Sets the locale data for the package type
*/
diff --git a/packages/metaboxes/monitors/conditional-display/aperture/post-template.js b/packages/metaboxes/monitors/conditional-display/aperture/post-template.js
index a7bf4ea71..c5f0f9678 100644
--- a/packages/metaboxes/monitors/conditional-display/aperture/post-template.js
+++ b/packages/metaboxes/monitors/conditional-display/aperture/post-template.js
@@ -35,8 +35,15 @@ const INITIAL_STATE = {
* @return {Object}
*/
function getPostTemplateFromSelect( node ) {
+ let { value } = node;
+
+ // In Gutenberg for the "Default" template is used an empty string.
+ if ( value === 'default' ) {
+ value = '';
+ }
+
return {
- post_template: node.value
+ post_template: value
};
}
diff --git a/packages/metaboxes/monitors/conditional-display/conditions/post-template.js b/packages/metaboxes/monitors/conditional-display/conditions/post-template.js
new file mode 100644
index 000000000..d6e4c9fc1
--- /dev/null
+++ b/packages/metaboxes/monitors/conditional-display/conditions/post-template.js
@@ -0,0 +1,22 @@
+/**
+ * Internal dependencies.
+ */
+import base from './base';
+
+export default {
+ ...base,
+
+ /**
+ * @inheritdoc
+ */
+ isFulfiled( definition, values ) {
+ definition = { ...definition };
+
+ // In Gutenberg for the "Default" template is used an empty string.
+ if ( definition.value === 'default' ) {
+ definition.value = '';
+ }
+
+ return base.isFulfiled( definition, values );
+ }
+};
diff --git a/packages/metaboxes/monitors/conditional-display/handler/index.js b/packages/metaboxes/monitors/conditional-display/handler/index.js
index 22b324f47..f6bba8aaf 100644
--- a/packages/metaboxes/monitors/conditional-display/handler/index.js
+++ b/packages/metaboxes/monitors/conditional-display/handler/index.js
@@ -1,7 +1,6 @@
/**
* External dependencies.
*/
-import { unmountComponentAtNode } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { get, map } from 'lodash';
@@ -12,6 +11,7 @@ import { renderContainer } from '../../../containers';
import base from '../conditions/base';
import boolean from '../conditions/boolean';
import postTerm from '../conditions/post-term';
+import postTemplate from '../conditions/post-template';
import postAncestorId from '../conditions/post-ancestor-id';
import termParentId from '../conditions/term-parent-id';
import termAncestorId from '../conditions/term-ancestor-id';
@@ -28,7 +28,7 @@ const conditions = {
post_parent_id: base,
post_level: base,
post_format: base,
- post_template: base,
+ post_template: postTemplate,
term_level: base,
term_parent: termParentId,
term_ancestor: termAncestorId,
@@ -96,22 +96,25 @@ export default function handler( { containers, context } ) {
results.forEach( ( [ id, result ] ) => {
const postboxNode = document.getElementById( id );
const containerNode = document.querySelector( `.container-${ id }` );
+ const isMounted = !! containerNode.dataset.mounted;
if ( postboxNode ) {
postboxNode.hidden = ! result;
}
if ( containerNode ) {
- if ( result && ! containerNode.dataset.mounted ) {
- containerNode.dataset.mounted = true;
-
+ if ( result && ! isMounted ) {
renderContainer( containers[ id ], context );
}
- if ( ! result && containerNode.dataset.mounted ) {
+ if ( ! result && isMounted ) {
delete containerNode.dataset.mounted;
- unmountComponentAtNode( containerNode );
+ // Rely on React's internals instead of `unmountComponentAtNode`
+ // due to https://github.com/facebook/react/issues/13690.
+ // TODO: Conditionally render the fields in the container, this way
+ // we can move away from mount/unmount cycles.
+ containerNode._reactRootContainer.unmount();
}
}
} );
diff --git a/packages/metaboxes/utils/is-gutenberg.js b/packages/metaboxes/utils/is-gutenberg.js
index 63eeeb46b..2e0de431b 100644
--- a/packages/metaboxes/utils/is-gutenberg.js
+++ b/packages/metaboxes/utils/is-gutenberg.js
@@ -6,11 +6,8 @@ import { isUndefined } from 'lodash';
/**
* Returns true if Gutenberg is presented.
*
- * For some reason the Gutenberg package uses `_wpLoadGutenbergEditor`
- * while WordPress@5 uses `_wpLoadBlockEditor`.
- *
* @return {boolean}
*/
export default function isGutenberg() {
- return ! isUndefined( window._wpLoadGutenbergEditor ) || ! isUndefined( window._wpLoadBlockEditor );
+ return ! isUndefined( window._wpLoadBlockEditor );
}