@wordpress/block-library
Version:
Block library for the WordPress editor.
132 lines (128 loc) • 4.13 kB
JavaScript
/**
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useInstanceId } from '@wordpress/compose';
import { useEffect } from '@wordpress/element';
import {
BlockControls,
InspectorControls,
useBlockProps,
useSetting,
store as blockEditorStore,
useInnerBlocksProps,
} from '@wordpress/block-editor';
import { SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import QueryToolbar from './query-toolbar';
import QueryInspectorControls from './inspector-controls';
import { DEFAULTS_POSTS_PER_PAGE } from '../constants';
const TEMPLATE = [ [ 'core/post-template' ] ];
export default function QueryContent( {
attributes,
setAttributes,
openPatternSelectionModal,
name,
clientId,
} ) {
const {
queryId,
query,
displayLayout,
tagName: TagName = 'div',
layout = {},
} = attributes;
const { __unstableMarkNextChangeAsNotPersistent } =
useDispatch( blockEditorStore );
const instanceId = useInstanceId( QueryContent );
const { themeSupportsLayout } = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return { themeSupportsLayout: getSettings()?.supportsLayout };
}, [] );
const defaultLayout = useSetting( 'layout' ) || {};
const usedLayout = ! layout?.type
? { ...defaultLayout, ...layout, type: 'default' }
: { ...defaultLayout, ...layout };
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps, {
template: TEMPLATE,
__experimentalLayout: themeSupportsLayout ? usedLayout : undefined,
} );
const { postsPerPage } = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return {
postsPerPage:
+getSettings().postsPerPage || DEFAULTS_POSTS_PER_PAGE,
};
}, [] );
// There are some effects running where some initialization logic is
// happening and setting some values to some attributes (ex. queryId).
// These updates can cause an `undo trap` where undoing will result in
// resetting again, so we need to mark these changes as not persistent
// with `__unstableMarkNextChangeAsNotPersistent`.
// Changes in query property (which is an object) need to be in the same callback,
// because updates are batched after the render and changes in different query properties
// would cause to override previous wanted changes.
useEffect( () => {
const newQuery = {};
if ( ! query.perPage && postsPerPage ) {
newQuery.perPage = postsPerPage;
}
if ( !! Object.keys( newQuery ).length ) {
__unstableMarkNextChangeAsNotPersistent();
updateQuery( newQuery );
}
}, [ query.perPage ] );
// We need this for multi-query block pagination.
// Query parameters for each block are scoped to their ID.
useEffect( () => {
if ( ! Number.isFinite( queryId ) ) {
__unstableMarkNextChangeAsNotPersistent();
setAttributes( { queryId: instanceId } );
}
}, [ queryId, instanceId ] );
const updateQuery = ( newQuery ) =>
setAttributes( { query: { ...query, ...newQuery } } );
const updateDisplayLayout = ( newDisplayLayout ) =>
setAttributes( {
displayLayout: { ...displayLayout, ...newDisplayLayout },
} );
return (
<>
<QueryInspectorControls
attributes={ attributes }
setQuery={ updateQuery }
setDisplayLayout={ updateDisplayLayout }
/>
<BlockControls>
<QueryToolbar
name={ name }
clientId={ clientId }
attributes={ attributes }
setQuery={ updateQuery }
setDisplayLayout={ updateDisplayLayout }
openPatternSelectionModal={ openPatternSelectionModal }
/>
</BlockControls>
<InspectorControls __experimentalGroup="advanced">
<SelectControl
label={ __( 'HTML element' ) }
options={ [
{ label: __( 'Default (<div>)' ), value: 'div' },
{ label: '<main>', value: 'main' },
{ label: '<section>', value: 'section' },
{ label: '<aside>', value: 'aside' },
] }
value={ TagName }
onChange={ ( value ) =>
setAttributes( { tagName: value } )
}
/>
</InspectorControls>
<TagName { ...innerBlocksProps } />
</>
);
}