Add/block product categories (https://github.com/woocommerce/woocommerce-blocks/pull/613)
* Add initial work for Product Categories List block * Add empty category toggle * Add option to show list as a dropdown * Fix console warnings * Only show proptypes linter warning if the component declares proptypes * Add frontend script to render the product categories * Split wcSettings & wc_product_block_data globals so that the later can be used from the frontend * Remove wp dependencies, these are added by the webpack script now * Capture all "woo packages" into a separate script chunk These require `wcSettings`, which can't be available on the frontend - but we do need vendors on the frontend. * Rewrite component into a function * Fix validation error on editor reload
This commit is contained in:
parent
5f76139679
commit
27345f93a2
|
@ -101,7 +101,7 @@ module.exports = {
|
|||
'react/jsx-key': 'error',
|
||||
'react/jsx-tag-spacing': 'error',
|
||||
'react/no-children-prop': 'off',
|
||||
'react/prop-types': 'warn',
|
||||
'react/prop-types': [ 'warn', { 'skipUndeclared': true } ],
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
semi: 'error',
|
||||
'semi-spacing': 'error',
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { noop } from 'lodash';
|
||||
import { SelectControl } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { buildTermsTree } from './hierarchy';
|
||||
|
||||
function getCategories( { hasEmpty, isDropdown, isHierarchical } ) {
|
||||
const categories = wc_product_block_data.productCategories.filter(
|
||||
( cat ) => hasEmpty || !! cat.count
|
||||
);
|
||||
return ! isDropdown && isHierarchical ?
|
||||
buildTermsTree( categories ) :
|
||||
categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component displaying the categories as dropdown or list.
|
||||
*/
|
||||
const ProductCategoriesBlock = ( { attributes } ) => {
|
||||
const { hasCount, isDropdown } = attributes;
|
||||
const categories = getCategories( attributes );
|
||||
const parentKey = 'parent-' + categories[ 0 ].term_id;
|
||||
|
||||
const renderList = ( items ) => (
|
||||
<ul key={ parentKey }>
|
||||
{ items.map( ( cat ) => {
|
||||
const count = hasCount ? <span>({ cat.count })</span> : null;
|
||||
return [
|
||||
<li key={ cat.term_id }><a>{ cat.name }</a> { count }</li>, // eslint-disable-line
|
||||
!! cat.children &&
|
||||
!! cat.children.length &&
|
||||
renderList( cat.children ),
|
||||
];
|
||||
} ) }
|
||||
</ul>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="wc-block-product-categories">
|
||||
{ isDropdown ? (
|
||||
<SelectControl
|
||||
label={ __( 'Select a category', 'woo-gutenberg-products-block' ) }
|
||||
options={ categories.map( ( cat ) => ( {
|
||||
label: hasCount ? `${ cat.name } (${ cat.count })` : cat.name,
|
||||
value: cat.term_id,
|
||||
} ) ) }
|
||||
onChange={ noop }
|
||||
/>
|
||||
) : (
|
||||
renderList( categories )
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProductCategoriesBlock.propTypes = {
|
||||
/**
|
||||
* The attributes for this block
|
||||
*/
|
||||
attributes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ProductCategoriesBlock;
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Fragment } from '@wordpress/element';
|
||||
import { InspectorControls } from '@wordpress/editor';
|
||||
import { PanelBody, ToggleControl } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import Block from './block.js';
|
||||
|
||||
export default function( { attributes, setAttributes } ) {
|
||||
const { hasCount, hasEmpty, isDropdown, isHierarchical } = attributes;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<InspectorControls key="inspector">
|
||||
<PanelBody
|
||||
title={ __( 'Content', 'woo-gutenberg-products-block' ) }
|
||||
initialOpen
|
||||
>
|
||||
<ToggleControl
|
||||
label={ __( 'Show as dropdown', 'woo-gutenberg-products-block' ) }
|
||||
help={
|
||||
isDropdown ?
|
||||
__( 'Categories are shown in a dropdown.', 'woo-gutenberg-products-block' ) :
|
||||
__( 'Categories are shown in a list.', 'woo-gutenberg-products-block' )
|
||||
}
|
||||
checked={ isDropdown }
|
||||
onChange={ () => setAttributes( { isDropdown: ! isDropdown } ) }
|
||||
/>
|
||||
<ToggleControl
|
||||
label={ __( 'Show product count', 'woo-gutenberg-products-block' ) }
|
||||
help={
|
||||
hasCount ?
|
||||
__( 'Product count is visible.', 'woo-gutenberg-products-block' ) :
|
||||
__( 'Product count is hidden.', 'woo-gutenberg-products-block' )
|
||||
}
|
||||
checked={ hasCount }
|
||||
onChange={ () => setAttributes( { hasCount: ! hasCount } ) }
|
||||
/>
|
||||
{ ! isDropdown && (
|
||||
<ToggleControl
|
||||
label={ __( 'Show hierarchy', 'woo-gutenberg-products-block' ) }
|
||||
help={
|
||||
isHierarchical ?
|
||||
__( 'Hierarchy is visible.', 'woo-gutenberg-products-block' ) :
|
||||
__( 'Hierarchy is hidden.', 'woo-gutenberg-products-block' )
|
||||
}
|
||||
checked={ isHierarchical }
|
||||
onChange={ () => setAttributes( { isHierarchical: ! isHierarchical } ) }
|
||||
/>
|
||||
) }
|
||||
<ToggleControl
|
||||
label={ __( 'Show empty categories', 'woo-gutenberg-products-block' ) }
|
||||
help={
|
||||
hasEmpty ?
|
||||
__( 'Empty categories are visible.', 'woo-gutenberg-products-block' ) :
|
||||
__( 'Empty categories are hidden.', 'woo-gutenberg-products-block' )
|
||||
}
|
||||
checked={ hasEmpty }
|
||||
onChange={ () => setAttributes( { hasEmpty: ! hasEmpty } ) }
|
||||
/>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<Block attributes={ attributes } />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.wc-block-product-categories.wc-block-product-categories ul {
|
||||
margin-left: 20px;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block.js';
|
||||
|
||||
const containers = document.querySelectorAll(
|
||||
'.wp-block-woocommerce-product-categories'
|
||||
);
|
||||
|
||||
if ( containers.length ) {
|
||||
containers.forEach( ( el ) => {
|
||||
const data = JSON.parse( JSON.stringify( el.dataset ) );
|
||||
const attributes = {
|
||||
hasCount: data.hasCount === 'true',
|
||||
hasEmpty: data.hasEmpty === 'true',
|
||||
isDropdown: data.isDropdown === 'true',
|
||||
isHierarchical: data.isHierarchical === 'true',
|
||||
};
|
||||
|
||||
render( <Block attributes={ attributes } />, el );
|
||||
} );
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { forEach, groupBy } from 'lodash';
|
||||
|
||||
/**
|
||||
* Returns terms in a tree form.
|
||||
*
|
||||
* @param {Array} list Array of terms in flat format.
|
||||
*
|
||||
* @return {Array} Array of terms in tree format.
|
||||
*/
|
||||
export function buildTermsTree( list = [] ) {
|
||||
const termsByParent = groupBy( list, 'parent' );
|
||||
|
||||
const fillWithChildren = ( terms ) => {
|
||||
return terms.map( ( term ) => {
|
||||
const children = termsByParent[ term.term_id ];
|
||||
delete termsByParent[ term.term_id ];
|
||||
return {
|
||||
...term,
|
||||
children: children && children.length ? fillWithChildren( children ) : [],
|
||||
};
|
||||
} );
|
||||
};
|
||||
|
||||
const tree = fillWithChildren( termsByParent[ '0' ] || [] );
|
||||
delete termsByParent[ '0' ];
|
||||
|
||||
// anything left in termsByParent has no visible parent
|
||||
forEach( termsByParent, ( terms ) => {
|
||||
tree.push( ...fillWithChildren( terms || [] ) );
|
||||
} );
|
||||
|
||||
return tree;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import edit from './edit.js';
|
||||
import { IconFolder } from '../../components/icons';
|
||||
|
||||
registerBlockType( 'woocommerce/product-categories', {
|
||||
title: __( 'Product Categories List', 'woo-gutenberg-products-block' ),
|
||||
icon: {
|
||||
src: <IconFolder />,
|
||||
foreground: '#96588a',
|
||||
},
|
||||
category: 'woocommerce',
|
||||
keywords: [ __( 'WooCommerce', 'woo-gutenberg-products-block' ) ],
|
||||
description: __(
|
||||
'Show your product categories as a list or dropdown.',
|
||||
'woo-gutenberg-products-block'
|
||||
),
|
||||
supports: {
|
||||
align: [ 'wide', 'full' ],
|
||||
},
|
||||
|
||||
attributes: {
|
||||
/**
|
||||
* Whether to show the product count in each category.
|
||||
*/
|
||||
hasCount: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
source: 'attribute',
|
||||
selector: 'div',
|
||||
attribute: 'data-has-count',
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether to show empty categories in the list.
|
||||
*/
|
||||
hasEmpty: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
source: 'attribute',
|
||||
selector: 'div',
|
||||
attribute: 'data-has-empty',
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether to display product categories as a dropdown (true) or list (false).
|
||||
*/
|
||||
isDropdown: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
source: 'attribute',
|
||||
selector: 'div',
|
||||
attribute: 'data-is-dropdown',
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the product categories should display with hierarchy.
|
||||
*/
|
||||
isHierarchical: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
source: 'attribute',
|
||||
selector: 'div',
|
||||
attribute: 'data-is-hierarchical',
|
||||
},
|
||||
},
|
||||
|
||||
edit,
|
||||
|
||||
/**
|
||||
* Save the props to post content.
|
||||
*/
|
||||
save( { attributes } ) {
|
||||
const { hasCount, hasEmpty, isDropdown, isHierarchical } = attributes;
|
||||
const props = {};
|
||||
if ( hasCount ) {
|
||||
props[ 'data-has-count' ] = true;
|
||||
}
|
||||
if ( hasEmpty ) {
|
||||
props[ 'data-has-empty' ] = true;
|
||||
}
|
||||
if ( isDropdown ) {
|
||||
props[ 'data-is-dropdown' ] = true;
|
||||
}
|
||||
if ( isHierarchical ) {
|
||||
props[ 'data-is-hierarchical' ] = true;
|
||||
}
|
||||
return <div { ...props }>LOADING</div>;
|
||||
},
|
||||
} );
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Icon } from '@wordpress/components';
|
||||
|
||||
export default () => (
|
||||
<Icon
|
||||
icon={
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path fillRule="nonzero" d="M21.913 7.0946H2.0254c-1.1708 0-2.0984.9908-2.0205 2.16l.741 11.0724c.0714 1.0638.9552 1.8892 2.0206 1.8892h18.4054c1.0654 0 1.9492-.8254 2.0205-1.8892l.7411-11.0724c.0779-1.1692-.8497-2.16-2.0205-2.16zm-8.8006-4.6573h5.987c1.119 0 2.0255.9065 2.0255 2.0254v.934H2.8103V2.0255C2.8103.9064 3.7168 0 4.8357 0h6.2513c1.119 0 2.0254.9065 2.0254 2.0254v.4119zm-7.0589 11.619a.926.926 0 1 1 0-1.852h11.8297a.926.926 0 1 1 0 1.852H6.0535z" />
|
||||
</svg>
|
||||
}
|
||||
/>
|
||||
);
|
|
@ -1,6 +1,7 @@
|
|||
// Export each icon as a named component.
|
||||
export { default as IconCheckChecked } from './checkbox-checked';
|
||||
export { default as IconCheckUnchecked } from './checkbox-unchecked';
|
||||
export { default as IconFolder } from './folder';
|
||||
export { default as IconNewReleases } from './new-releases';
|
||||
export { default as IconRadioSelected } from './radio-selected';
|
||||
export { default as IconRadioUnselected } from './radio-unselected';
|
||||
|
|
|
@ -17,7 +17,7 @@ export const deprecatedConvertToShortcode = ( blockType ) => {
|
|||
const {
|
||||
align,
|
||||
contentVisibility,
|
||||
} = props.attributes; /* eslint-disable-line react/prop-types */
|
||||
} = props.attributes;
|
||||
const classes = classnames( align ? `align${ align }` : '', {
|
||||
'is-hidden-title': ! contentVisibility.title,
|
||||
'is-hidden-price': ! contentVisibility.price,
|
||||
|
|
|
@ -52,7 +52,9 @@ class WGPB_Block_Library {
|
|||
}
|
||||
self::register_blocks();
|
||||
self::register_assets();
|
||||
add_action( 'admin_print_footer_scripts', array( 'WGPB_Block_Library', 'print_script_settings' ), 1 );
|
||||
add_action( 'admin_print_footer_scripts', array( 'WGPB_Block_Library', 'print_script_wc_settings' ), 1 );
|
||||
add_action( 'admin_print_footer_scripts', array( 'WGPB_Block_Library', 'print_script_block_data' ), 1 );
|
||||
add_action( 'wp_print_footer_scripts', array( 'WGPB_Block_Library', 'print_script_block_data' ), 1 );
|
||||
add_action( 'body_class', array( 'WGPB_Block_Library', 'add_theme_body_class' ), 1 );
|
||||
}
|
||||
|
||||
|
@ -122,30 +124,28 @@ class WGPB_Block_Library {
|
|||
// Shared libraries and components across all blocks.
|
||||
self::register_script( 'wc-blocks', plugins_url( 'build/blocks.js', WGPB_PLUGIN_FILE ), array(), false );
|
||||
self::register_script( 'wc-vendors', plugins_url( 'build/vendors.js', WGPB_PLUGIN_FILE ), array(), false );
|
||||
self::register_script( 'wc-packages', plugins_url( 'build/packages.js', WGPB_PLUGIN_FILE ), array(), false );
|
||||
self::register_script( 'wc-frontend', plugins_url( 'build/frontend.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors' ) );
|
||||
|
||||
// Individual blocks.
|
||||
self::register_script( 'wc-handpicked-products', plugins_url( 'build/handpicked-products.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-best-sellers', plugins_url( 'build/product-best-sellers.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-category', plugins_url( 'build/product-category.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-new', plugins_url( 'build/product-new.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-on-sale', plugins_url( 'build/product-on-sale.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-top-rated', plugins_url( 'build/product-top-rated.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-products-attribute', plugins_url( 'build/products-attribute.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-featured-product', plugins_url( 'build/featured-product.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-handpicked-products', plugins_url( 'build/handpicked-products.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-best-sellers', plugins_url( 'build/product-best-sellers.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-category', plugins_url( 'build/product-category.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-new', plugins_url( 'build/product-new.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-on-sale', plugins_url( 'build/product-on-sale.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-top-rated', plugins_url( 'build/product-top-rated.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-products-attribute', plugins_url( 'build/products-attribute.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-featured-product', plugins_url( 'build/featured-product.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
self::register_script( 'wc-product-categories', plugins_url( 'build/product-categories.js', WGPB_PLUGIN_FILE ), array( 'wc-vendors', 'wc-packages', 'wc-blocks' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output useful globals before printing any script tags.
|
||||
*
|
||||
* These are used by @woocommerce/components & the block library to set up defaults
|
||||
* based on user-controlled settings from WordPress.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* based on user-controlled settings from WordPress. Only use this in wp-admin.
|
||||
*/
|
||||
public static function print_script_settings() {
|
||||
public static function print_script_wc_settings() {
|
||||
global $wp_locale;
|
||||
$code = get_woocommerce_currency();
|
||||
$product_counts = wp_count_posts( 'product' );
|
||||
$code = get_woocommerce_currency();
|
||||
|
||||
// NOTE: wcSettings is not used directly, it's only for @woocommerce/components
|
||||
//
|
||||
|
@ -174,7 +174,29 @@ class WGPB_Block_Library {
|
|||
);
|
||||
// NOTE: wcSettings is not used directly, it's only for @woocommerce/components.
|
||||
$settings = apply_filters( 'woocommerce_components_settings', $settings );
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var wcSettings = wcSettings || JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( $settings ) ); ?>' ) );
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output block-related data on a global object.
|
||||
*
|
||||
* This is used to map site settings & data into JS-accessible variables.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public static function print_script_block_data() {
|
||||
$product_counts = wp_count_posts( 'product' );
|
||||
$product_categories = get_terms(
|
||||
'product_cat',
|
||||
array(
|
||||
'hide_empty' => false,
|
||||
'pad_counts' => true,
|
||||
)
|
||||
);
|
||||
// Global settings used in each block.
|
||||
$block_settings = array(
|
||||
'min_columns' => wc_get_theme_support( 'product_blocks::min_columns', 1 ),
|
||||
|
@ -188,10 +210,10 @@ class WGPB_Block_Library {
|
|||
'min_height' => wc_get_theme_support( 'featured_block::min_height', 500 ),
|
||||
'default_height' => wc_get_theme_support( 'featured_block::default_height', 500 ),
|
||||
'isLargeCatalog' => $product_counts->publish > 200,
|
||||
'productCategories' => $product_categories,
|
||||
);
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var wcSettings = wcSettings || JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( $settings ) ); ?>' ) );
|
||||
var wc_product_block_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( $block_settings ) ); ?>' ) );
|
||||
</script>
|
||||
<?php
|
||||
|
@ -329,6 +351,15 @@ class WGPB_Block_Library {
|
|||
'style' => 'wc-block-style',
|
||||
)
|
||||
);
|
||||
register_block_type(
|
||||
'woocommerce/product-categories',
|
||||
array(
|
||||
'editor_script' => 'wc-product-categories',
|
||||
'editor_style' => 'wc-block-editor',
|
||||
'style' => 'wc-block-style',
|
||||
'script' => 'wc-frontend',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,10 +27,12 @@ const GutenbergBlocksConfig = {
|
|||
entry: {
|
||||
// Shared blocks code
|
||||
blocks: './assets/js/index.js',
|
||||
frontend: [ './assets/js/blocks/product-categories/frontend.js' ],
|
||||
// Blocks
|
||||
'handpicked-products': './assets/js/blocks/handpicked-products/index.js',
|
||||
'product-best-sellers': './assets/js/blocks/product-best-sellers/index.js',
|
||||
'product-category': './assets/js/blocks/product-category/index.js',
|
||||
'product-categories': './assets/js/blocks/product-categories/index.js',
|
||||
'product-new': './assets/js/blocks/product-new/index.js',
|
||||
'product-on-sale': './assets/js/blocks/product-on-sale/index.js',
|
||||
'product-top-rated': './assets/js/blocks/product-top-rated/index.js',
|
||||
|
@ -50,6 +52,13 @@ const GutenbergBlocksConfig = {
|
|||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
packages: {
|
||||
test: /[\\/]node_modules[\\/]@woocommerce/,
|
||||
name: 'packages',
|
||||
chunks: 'all',
|
||||
enforce: true,
|
||||
priority: 10, // Higher priority to ensure @woocommerce/* packages are caught here.
|
||||
},
|
||||
commons: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
name: 'vendors',
|
||||
|
|
Loading…
Reference in New Issue