/** * External dependencies */ import { ComponentType, useEffect, useMemo, useState } from 'react'; import { WP_REST_API_Category } from 'wp-types'; import { ProductResponseItem } from '@woocommerce/types'; import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies */ import { EditorBlock } from './types'; interface WithUpdateButtonRequiredAttributes { editMode: boolean; } interface WithUpdateButtonAttributes< T > { attributes: WithUpdateButtonRequiredAttributes & EditorBlock< T >[ 'attributes' ]; } interface WithUpdateButtonCategoryProps< T > extends WithUpdateButtonAttributes< T > { category: WP_REST_API_Category; product: never; } interface WithUpdateButtonProductProps< T > extends WithUpdateButtonAttributes< T > { category: never; product: ProductResponseItem; } type WithUpdateButtonProps< T extends EditorBlock< T > > = | ( T & WithUpdateButtonCategoryProps< T > ) | ( T & WithUpdateButtonProductProps< T > ); export const withUpdateButtonAttributes = < T extends EditorBlock< T > >( Component: ComponentType< T > ) => ( props: WithUpdateButtonProps< T > ) => { const [ doUrlUpdate, setDoUrlUpdate ] = useState( false ); const { attributes, category, clientId, product } = props; const item = category || product; const { editMode } = attributes; const permalink = ( item as WP_REST_API_Category )?.link || ( item as ProductResponseItem )?.permalink; const Block = useSelect( ( select ) => { return select( 'core/block-editor' ).getBlock( clientId ); } ); const InnerButton = Block?.innerBlocks[ 0 ]; const buttonBlockId = InnerButton?.clientId || ''; const currentButtonAttributes = useMemo( () => InnerButton?.attributes || {}, [ InnerButton ] ); const { url } = currentButtonAttributes; const { updateBlockAttributes } = useDispatch( 'core/block-editor' ); useEffect( () => { if ( doUrlUpdate && buttonBlockId && ! editMode && permalink && url && permalink !== url ) { updateBlockAttributes( buttonBlockId, { url: permalink, } ); setDoUrlUpdate( false ); } }, [ buttonBlockId, doUrlUpdate, editMode, permalink, updateBlockAttributes, url, ] ); const triggerUrlUpdate = () => setDoUrlUpdate( true ); return ; };