woocommerce/plugins/woocommerce-blocks/assets/js/blocks/classic-template/product-search-results.ts

187 lines
5.0 KiB
TypeScript

/**
* External dependencies
*/
import { isWpVersion } from '@woocommerce/settings';
import { __, sprintf } from '@wordpress/i18n';
import {
INNER_BLOCKS_TEMPLATE as productCollectionInnerBlocksTemplate,
DEFAULT_ATTRIBUTES as productCollectionDefaultAttributes,
DEFAULT_QUERY as productCollectionDefaultQuery,
} from '@woocommerce/blocks/product-collection/constants';
import {
createBlock,
// @ts-expect-error Type definitions for this function are missing in Guteberg
createBlocksFromInnerBlocksTemplate,
type BlockInstance,
type InnerBlockTemplate,
} from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { createArchiveTitleBlock, createRowBlock } from './utils';
import { OnClickCallbackParameter, type InheritedAttributes } from './types';
const createNoResultsParagraph = () =>
createBlock( 'core/paragraph', {
content: __(
'No products were found matching your selection.',
'woocommerce'
),
} );
const createProductSearch = () =>
createBlock( 'core/search', {
buttonPosition: 'button-outside',
buttonText: __( 'Search', 'woocommerce' ),
buttonUseIcon: false,
showLabel: false,
placeholder: __( 'Search products…', 'woocommerce' ),
query: { post_type: 'product' },
} );
const extendInnerBlocksWithNoResultsContent = (
innerBlocks: InnerBlockTemplate[],
inheritedAttributes: InheritedAttributes
) => {
// InnerBlockTemplate is an array block representation so properties
// like name or attributes need to be accessed with array indexes.
const nameArrayIndex = 0;
const attributesArrayIndex = 1;
const noResultsContent = [
createNoResultsParagraph(),
createProductSearch(),
];
const noResultsBlockName = 'woocommerce/product-collection-no-results';
const noResultsBlockIndex = innerBlocks.findIndex(
( block ) => block[ nameArrayIndex ] === noResultsBlockName
);
const noResultsBlock = innerBlocks[ noResultsBlockIndex ];
const attributes = {
...( noResultsBlock[ attributesArrayIndex ] || {} ),
...inheritedAttributes,
};
const extendedNoResults = [
noResultsBlockName,
attributes,
noResultsContent,
];
return [
...innerBlocks.slice( 0, noResultsBlockIndex ),
extendedNoResults,
...innerBlocks.slice( noResultsBlockIndex + 1 ),
];
};
const createProductCollectionBlock = (
inheritedAttributes: InheritedAttributes
) => {
const productCollectionInnerBlocksWithNoResults =
extendInnerBlocksWithNoResultsContent(
productCollectionInnerBlocksTemplate,
inheritedAttributes
);
return createBlock(
'woocommerce/product-collection',
{
...productCollectionDefaultAttributes,
...inheritedAttributes,
query: {
...productCollectionDefaultQuery,
inherit: true,
},
},
createBlocksFromInnerBlocksTemplate(
productCollectionInnerBlocksWithNoResults
)
);
};
const getBlockifiedTemplate = ( inheritedAttributes: InheritedAttributes ) =>
[
createArchiveTitleBlock( 'search-title', inheritedAttributes ),
createBlock( 'woocommerce/store-notices', inheritedAttributes ),
createRowBlock(
[
createBlock( 'woocommerce/product-results-count' ),
createBlock( 'woocommerce/catalog-sorting' ),
],
inheritedAttributes
),
createProductCollectionBlock( inheritedAttributes ),
].filter( Boolean ) as BlockInstance[];
const isConversionPossible = () => {
// Blockification is possible for the WP version 6.1 and above,
// which are the versions the Products block supports.
return isWpVersion( '6.1', '>=' );
};
const getDescriptionAllowingConversion = ( templateTitle: string ) =>
sprintf(
/* translators: %s is the template title */
__(
'Transform this template into multiple blocks so you can add, remove, reorder, and customize your %s template.',
'woocommerce'
),
templateTitle
);
const getDescriptionDisallowingConversion = ( templateTitle: string ) =>
sprintf(
/* translators: %s is the template title */
__(
'This block serves as a placeholder for your %s. It will display the actual product image, title, price in your store. You can move this placeholder around and add more blocks around to customize the template.',
'woocommerce'
),
templateTitle
);
const getDescription = ( templateTitle: string, canConvert: boolean ) => {
if ( canConvert ) {
return getDescriptionAllowingConversion( templateTitle );
}
return getDescriptionDisallowingConversion( templateTitle );
};
const onClickCallback = ( {
clientId,
attributes,
getBlocks,
replaceBlock,
selectBlock,
}: OnClickCallbackParameter ) => {
replaceBlock( clientId, getBlockifiedTemplate( attributes ) );
const blocks = getBlocks();
const groupBlock = blocks.find(
( block ) =>
block.name === 'core/group' &&
block.innerBlocks.some(
( innerBlock ) =>
innerBlock.name === 'woocommerce/store-notices'
)
);
if ( groupBlock ) {
selectBlock( groupBlock.clientId );
}
};
const getButtonLabel = () => __( 'Transform into blocks', 'woocommerce' );
const blockifyConfig = {
getButtonLabel,
onClickCallback,
getBlockifiedTemplate,
};
export { isConversionPossible, getDescription, blockifyConfig };