@wordpress/block-library
Version:
Block library for the WordPress editor.
133 lines (121 loc) • 3.69 kB
JavaScript
import clsx from 'clsx';
import { __ } from '@wordpress/i18n';
import {
AlignmentControl,
BlockControls,
useBlockProps,
useInnerBlocksProps,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { BlockQuotation } from '@wordpress/components';
import { useDispatch, useRegistry, useSelect } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import deprecated from '@wordpress/deprecated';
import { verse } from '@wordpress/icons';
import { migrateToQuoteV2 } from './deprecated';
import { Caption } from '../utils/caption';
/**
* At the moment, deprecations don't handle create blocks from attributes
* (like when using CPT templates). For this reason, this hook is necessary
* to avoid breaking templates using the old quote block format.
*
* @param {Object} attributes Block attributes.
* @param {string} clientId Block client ID.
*/
const useMigrateOnLoad = ( attributes, clientId ) => {
const registry = useRegistry();
const { updateBlockAttributes, replaceInnerBlocks, selectBlock } =
useDispatch( blockEditorStore );
useEffect( () => {
// As soon as the block is loaded, migrate it to the new version.
if ( ! attributes.value ) {
// No need to migrate if it doesn't have the value attribute.
return;
}
const [ newAttributes, newInnerBlocks ] =
migrateToQuoteV2( attributes );
deprecated( 'Value attribute on the quote block', {
since: '6.0',
version: '6.5',
alternative: 'inner blocks',
} );
// The selection can be inside an inner block created from the block
// type template at insertion, which the migration replaces; restore
// the selection to the migrated block in that case.
const shouldReselectBlock = registry
.select( blockEditorStore )
.hasSelectedInnerBlock( clientId, true );
registry.batch( () => {
updateBlockAttributes( clientId, newAttributes );
replaceInnerBlocks( clientId, newInnerBlocks );
if ( shouldReselectBlock ) {
selectBlock( clientId );
}
} );
}, [ attributes.value ] );
};
export default function QuoteEdit( {
attributes,
setAttributes,
insertBlocksAfter,
clientId,
className,
isSelected,
} ) {
const { textAlign, allowedBlocks } = attributes;
const { hasInnerBlocks } = useSelect(
( select ) => {
const { getBlockCount } = select( blockEditorStore );
return {
hasInnerBlocks: getBlockCount( clientId ) > 0,
};
},
[ clientId ]
);
useMigrateOnLoad( attributes, clientId );
const blockProps = useBlockProps( {
className: clsx( className, {
[ `has-text-align-${ textAlign }` ]: textAlign,
} ),
} );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
__experimentalCaptureToolbars: true,
renderAppender: hasInnerBlocks ? false : undefined,
allowedBlocks,
} );
return (
<>
<BlockControls group="block">
<AlignmentControl
value={ textAlign }
onChange={ ( nextAlign ) => {
setAttributes( { textAlign: nextAlign } );
} }
/>
</BlockControls>
<BlockQuotation { ...innerBlocksProps }>
{ innerBlocksProps.children }
<Caption
attributeKey="citation"
tagName="cite"
style={ { display: 'block' } }
isSelected={ isSelected }
attributes={ attributes }
setAttributes={ setAttributes }
icon={ verse }
label={ __( 'Quote citation' ) }
placeholder={
// translators: placeholder text used for the
// citation
__( 'Add citation' )
}
addLabel={ __( 'Add citation' ) }
removeLabel={ __( 'Remove citation' ) }
excludeElementClassName
className="wp-block-quote__citation"
insertBlocksAfter={ insertBlocksAfter }
/>
</BlockQuotation>
</>
);
}