/** * External dependencies */ import { Component } from '@wordpress/element'; import { createHigherOrderComponent } from '@wordpress/compose'; import { getBlockType } from '@wordpress/blocks'; import { addFilter } from '@wordpress/hooks'; /** * withDefaultAttributes HOC for editor.BlockListBlock. * * @param object BlockListBlock The BlockListBlock element. */ const withDefaultAttributes = createHigherOrderComponent( ( BlockListBlock ) => { class WrappedComponent extends Component { mounted = false; componentDidMount() { const { block, setAttributes } = this.props; if ( block.name.startsWith( 'woocommerce/' ) ) { setAttributes( this.getAttributesWithDefaults() ); } } componentDidUpdate() { if ( this.props.block.name.startsWith( 'woocommerce/' ) && ! this.mounted ) { this.mounted = true; } } getAttributesWithDefaults() { const blockType = getBlockType( this.props.block.name ); let attributes = this.props.attributes; if ( ! this.mounted && this.props.block.name.startsWith( 'woocommerce/' ) && typeof blockType.attributes !== 'undefined' && typeof blockType.defaults !== 'undefined' ) { attributes = Object.assign( {}, this.props.attributes || {} ); Object.keys( blockType.attributes ).map( ( key ) => { if ( typeof attributes[ key ] === 'undefined' && typeof blockType.defaults[ key ] !== 'undefined' ) { attributes[ key ] = blockType.defaults[ key ]; } return key; } ); } return attributes; } render() { return ( <BlockListBlock { ...this.props } attributes={ this.getAttributesWithDefaults() } /> ); } } return WrappedComponent; }, 'withDefaultAttributes' ); /** * Hook into `editor.BlockListBlock` to set default attributes (if blocks * define them separately) when a block is inserted. * * This is a workaround for Gutenberg which does not save "default" attributes * to the post, which means if defaults change, all existing blocks change too. * * See https://github.com/WordPress/gutenberg/issues/7342 * * To use this, the block name needs a `woocommerce/` prefix, and as well * as defining `attributes` during block registration, you must also declare an * array called `defaults`. Defaults should be omitted from `attributes`. */ addFilter( 'editor.BlockListBlock', 'woocommerce-blocks/block-list-block', withDefaultAttributes );