woocommerce/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout-shared/use-forced-layout/index.ts

124 lines
3.4 KiB
TypeScript
Raw Normal View History

/**
* External dependencies
*/
import { useRef, useEffect } from '@wordpress/element';
import { useRegistry, dispatch } from '@wordpress/data';
Replace Products (Beta) with Product Collection in product archive templates (#48112) * Replace Products (Beta) with Product Collection block in blockified template * Add necessary attributes that influences the look of blocks * Replace Products (Beta) with Product Collection block in product search results * Replace Products (Beta) with Product Collection block in products by attribute * Replace Products (Beta) with Product Collection block in products by category * Replace Products (Beta) with Product Collection block in products by tag * Replace Products (Beta) with Product Collection when transforming from classic product archive * Change the no results content in blockified search results template * Replace Products (Beta) with Product Collection block in product search results * Add product search in no results content of blockified product search result * Add ts-ignore before createBlocksFromInnerBlocksTemplate imports * Add changelog * Remove step of replacing Products (Beta) with Product Collection in compatibility layer tests * Remove step of replacing Products (Beta) with Product Collection in Product Collection tests * Fix lint * Update E2E tests of Product Collection * Adjust Products (Beta) E2E tests * Add Product Collection focus step in E2E tests * Improve the way PC block is focused * Further tests adjustments and new tests comparing classic template with Product Collection * Bring back the click on body * Include tips from reviewer * Enter edit mode, step that I accidentally removde * Bring the E2E test flow with updating product catalog * Change the way of removing focus from PC block in tests * Fix lint * Improve the layout of search in No Results * Use previous patterns in Product Search No Results to preserve translations * Add Search button label in product search form pattern * Fix lint * Improve comment explanation * Extract No Results content to separate pattern in order to make the content translatable * Lint fix * Add missing footer to the blockified Products by Tag template * Exclude woocommerce/patterns from phpcs rules that dont apply there * Make PC block responsive by default in product archive templates * Fix typo * Fix typo --------- Co-authored-by: Manish Menaria <the.manish.menaria@gmail.com>
2024-06-12 13:45:09 +00:00
import { useEditorContext } from '@woocommerce/base-context';
import {
createBlock,
getBlockType,
Replace Products (Beta) with Product Collection in product archive templates (#48112) * Replace Products (Beta) with Product Collection block in blockified template * Add necessary attributes that influences the look of blocks * Replace Products (Beta) with Product Collection block in product search results * Replace Products (Beta) with Product Collection block in products by attribute * Replace Products (Beta) with Product Collection block in products by category * Replace Products (Beta) with Product Collection block in products by tag * Replace Products (Beta) with Product Collection when transforming from classic product archive * Change the no results content in blockified search results template * Replace Products (Beta) with Product Collection block in product search results * Add product search in no results content of blockified product search result * Add ts-ignore before createBlocksFromInnerBlocksTemplate imports * Add changelog * Remove step of replacing Products (Beta) with Product Collection in compatibility layer tests * Remove step of replacing Products (Beta) with Product Collection in Product Collection tests * Fix lint * Update E2E tests of Product Collection * Adjust Products (Beta) E2E tests * Add Product Collection focus step in E2E tests * Improve the way PC block is focused * Further tests adjustments and new tests comparing classic template with Product Collection * Bring back the click on body * Include tips from reviewer * Enter edit mode, step that I accidentally removde * Bring the E2E test flow with updating product catalog * Change the way of removing focus from PC block in tests * Fix lint * Improve the layout of search in No Results * Use previous patterns in Product Search No Results to preserve translations * Add Search button label in product search form pattern * Fix lint * Improve comment explanation * Extract No Results content to separate pattern in order to make the content translatable * Lint fix * Add missing footer to the blockified Products by Tag template * Exclude woocommerce/patterns from phpcs rules that dont apply there * Make PC block responsive by default in product archive templates * Fix typo * Fix typo --------- Co-authored-by: Manish Menaria <the.manish.menaria@gmail.com>
2024-06-12 13:45:09 +00:00
// @ts-expect-error Type definitions for this function are missing in Gutenberg
createBlocksFromInnerBlocksTemplate,
TemplateArray,
} from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { getMissingBlocks, findBlockPosition } from './utils';
/**
* Hook to ensure FORCED blocks are rendered in the correct place.
*/
export const useForcedLayout = ( {
clientId,
registeredBlocks,
defaultTemplate = [],
}: {
// Client ID of the parent block.
clientId: string;
// An array of registered blocks that may be forced in this particular layout.
registeredBlocks: Array< string >;
// The default template for the inner blocks in this layout.
defaultTemplate: TemplateArray;
} ) => {
const currentRegisteredBlocks = useRef( registeredBlocks );
const currentDefaultTemplate = useRef( defaultTemplate );
const registry = useRegistry();
const { isPreview } = useEditorContext();
useEffect( () => {
let templateSynced = false;
if ( isPreview ) {
return;
}
const { replaceInnerBlocks } = dispatch( 'core/block-editor' );
return registry.subscribe( () => {
const currentBlock = registry
.select( 'core/block-editor' )
.getBlock( clientId );
// If the block is removed we shouldn't reinsert its inner blocks.
if ( ! currentBlock ) {
return;
}
const innerBlocks = registry
.select( 'core/block-editor' )
.getBlocks( clientId );
// If there are NO inner blocks, sync with the given template.
if (
innerBlocks.length === 0 &&
currentDefaultTemplate.current.length > 0 &&
! templateSynced
) {
const nextBlocks = createBlocksFromInnerBlocksTemplate(
currentDefaultTemplate.current
);
if ( nextBlocks.length !== 0 ) {
templateSynced = true;
replaceInnerBlocks( clientId, nextBlocks );
return;
}
}
const registeredBlockTypes = currentRegisteredBlocks.current.map(
( blockName: string ) => getBlockType( blockName )
);
const missingBlocks = getMissingBlocks(
innerBlocks,
registeredBlockTypes
);
if ( missingBlocks.length === 0 ) {
return;
}
// Initially set as -1, so we can skip checking the position multiple times. Later on in the map callback,
// we check where the forced blocks should be inserted. This gets set to >= 0 if we find a missing block,
// so we know we can skip calculating it.
let insertAtPosition = -1;
const blockConfig = missingBlocks.map( ( block ) => {
const defaultTemplatePosition =
currentDefaultTemplate.current.findIndex(
( [ blockName ] ) => blockName === block.name
);
const createdBlock = createBlock( block.name );
// As mentioned above, if this is not -1, this is the first time we're calculating the position, if it's
// already been calculated we can skip doing so.
if ( insertAtPosition === -1 ) {
insertAtPosition = findBlockPosition( {
defaultTemplatePosition,
innerBlocks,
currentDefaultTemplate,
} );
}
return createdBlock;
} );
registry.batch( () => {
registry
.dispatch( 'core/block-editor' )
.insertBlocks( blockConfig, insertAtPosition, clientId );
} );
}, 'core/block-editor' );
}, [ clientId, isPreview, registry ] );
};