@wordpress/block-library
Version:
Block library for the WordPress editor.
182 lines (161 loc) • 4.12 kB
JavaScript
/**
* WordPress dependencies
*/
import { useEntityBlockEditor, store as coreStore } from '@wordpress/core-data';
import {
InnerBlocks,
useInnerBlocksProps,
useSettings,
store as blockEditorStore,
useBlockEditingMode,
} from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { useMemo } from '@wordpress/element';
import { parse } from '@wordpress/blocks';
function useRenderAppender( hasInnerBlocks ) {
const blockEditingMode = useBlockEditingMode();
// Disable appending when the editing mode is 'contentOnly'. This is so that the user can't
// append into a template part when editing a page in the site editor. See
// DisableNonPageContentBlocks. Ideally instead of (mis)using editing mode there would be a
// block editor API for achieving this.
if ( blockEditingMode === 'contentOnly' ) {
return false;
}
if ( ! hasInnerBlocks ) {
return InnerBlocks.ButtonBlockAppender;
}
}
function useLayout( layout ) {
const themeSupportsLayout = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return getSettings()?.supportsLayout;
}, [] );
const [ defaultLayout ] = useSettings( 'layout' );
if ( themeSupportsLayout ) {
return layout?.inherit ? defaultLayout || {} : layout;
}
}
function NonEditableTemplatePartPreview( {
postId: id,
layout,
tagName: TagName,
blockProps,
} ) {
useBlockEditingMode( 'disabled' );
const { content, editedBlocks } = useSelect(
( select ) => {
if ( ! id ) {
return {};
}
const { getEditedEntityRecord } = select( coreStore );
const editedRecord = getEditedEntityRecord(
'postType',
'wp_template_part',
id,
{ context: 'view' }
);
return {
editedBlocks: editedRecord.blocks,
content: editedRecord.content,
};
},
[ id ]
);
const blocks = useMemo( () => {
if ( ! id ) {
return undefined;
}
if ( editedBlocks ) {
return editedBlocks;
}
if ( ! content || typeof content !== 'string' ) {
return [];
}
return parse( content );
}, [ id, editedBlocks, content ] );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
value: blocks,
onInput: () => {},
onChange: () => {},
renderAppender: false,
layout: useLayout( layout ),
} );
return <TagName { ...innerBlocksProps } />;
}
function EditableTemplatePartInnerBlocks( {
postId: id,
hasInnerBlocks,
layout,
tagName: TagName,
blockProps,
} ) {
const onNavigateToEntityRecord = useSelect(
( select ) =>
select( blockEditorStore ).getSettings().onNavigateToEntityRecord,
[]
);
const [ blocks, onInput, onChange ] = useEntityBlockEditor(
'postType',
'wp_template_part',
{ id }
);
const innerBlocksProps = useInnerBlocksProps( blockProps, {
value: blocks,
onInput,
onChange,
renderAppender: useRenderAppender( hasInnerBlocks ),
layout: useLayout( layout ),
} );
const blockEditingMode = useBlockEditingMode();
const customProps =
blockEditingMode === 'contentOnly' && onNavigateToEntityRecord
? {
onDoubleClick: () =>
onNavigateToEntityRecord( {
postId: id,
postType: 'wp_template_part',
} ),
}
: {};
return <TagName { ...innerBlocksProps } { ...customProps } />;
}
export default function TemplatePartInnerBlocks( {
postId: id,
hasInnerBlocks,
layout,
tagName: TagName,
blockProps,
} ) {
const { canViewTemplatePart, canEditTemplatePart } = useSelect(
( select ) => {
return {
canViewTemplatePart: !! select( coreStore ).canUser( 'read', {
kind: 'postType',
name: 'wp_template_part',
id,
} ),
canEditTemplatePart: !! select( coreStore ).canUser( 'update', {
kind: 'postType',
name: 'wp_template_part',
id,
} ),
};
},
[ id ]
);
if ( ! canViewTemplatePart ) {
return null;
}
const TemplatePartInnerBlocksComponent = canEditTemplatePart
? EditableTemplatePartInnerBlocks
: NonEditableTemplatePartPreview;
return (
<TemplatePartInnerBlocksComponent
postId={ id }
hasInnerBlocks={ hasInnerBlocks }
layout={ layout }
tagName={ TagName }
blockProps={ blockProps }
/>
);
}