@wordpress/block-editor
Version:
128 lines (120 loc) • 3.65 kB
JavaScript
/**
* WordPress dependencies
*/
import { store as blocksStore } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import { SearchControl, Button } from '@wordpress/components';
import { __, _n, sprintf } from '@wordpress/i18n';
import { useEffect, useState } from '@wordpress/element';
import { useDebounce } from '@wordpress/compose';
import { speak } from '@wordpress/a11y';
/**
* Internal dependencies
*/
import BlockManagerCategory from './category';
/**
* Provides a list of blocks with checkboxes.
*
* @param {Object} props Props.
* @param {Array} props.blockTypes An array of blocks.
* @param {Array} props.selectedBlockTypes An array of selected blocks.
* @param {Function} props.onChange Function to be called when the selected blocks change.
*/
export default function BlockManager( {
blockTypes,
selectedBlockTypes,
onChange,
} ) {
const debouncedSpeak = useDebounce( speak, 500 );
const [ search, setSearch ] = useState( '' );
const { categories, isMatchingSearchTerm } = useSelect( ( select ) => {
return {
categories: select( blocksStore ).getCategories(),
isMatchingSearchTerm: select( blocksStore ).isMatchingSearchTerm,
};
}, [] );
function enableAllBlockTypes() {
onChange( blockTypes );
}
const filteredBlockTypes = blockTypes.filter( ( blockType ) => {
return ! search || isMatchingSearchTerm( blockType, search );
} );
const numberOfHiddenBlocks = blockTypes.length - selectedBlockTypes.length;
// Announce search results on change
useEffect( () => {
if ( ! search ) {
return;
}
const count = filteredBlockTypes.length;
const resultsFoundMessage = sprintf(
/* translators: %d: number of results. */
_n( '%d result found.', '%d results found.', count ),
count
);
debouncedSpeak( resultsFoundMessage );
}, [ filteredBlockTypes?.length, search, debouncedSpeak ] );
return (
<div className="block-editor-block-manager__content">
{ !! numberOfHiddenBlocks && (
<div className="block-editor-block-manager__disabled-blocks-count">
{ sprintf(
/* translators: %d: number of blocks. */
_n(
'%d block is hidden.',
'%d blocks are hidden.',
numberOfHiddenBlocks
),
numberOfHiddenBlocks
) }
<Button
__next40pxDefaultSize
variant="link"
onClick={ enableAllBlockTypes }
>
{ __( 'Reset' ) }
</Button>
</div>
) }
<SearchControl
__nextHasNoMarginBottom
label={ __( 'Search for a block' ) }
placeholder={ __( 'Search for a block' ) }
value={ search }
onChange={ ( nextSearch ) => setSearch( nextSearch ) }
className="block-editor-block-manager__search"
/>
<div
tabIndex="0"
role="region"
aria-label={ __( 'Available block types' ) }
className="block-editor-block-manager__results"
>
{ filteredBlockTypes.length === 0 && (
<p className="block-editor-block-manager__no-results">
{ __( 'No blocks found.' ) }
</p>
) }
{ categories.map( ( category ) => (
<BlockManagerCategory
key={ category.slug }
title={ category.title }
blockTypes={ filteredBlockTypes.filter(
( blockType ) =>
blockType.category === category.slug
) }
selectedBlockTypes={ selectedBlockTypes }
onChange={ onChange }
/>
) ) }
<BlockManagerCategory
title={ __( 'Uncategorized' ) }
blockTypes={ filteredBlockTypes.filter(
( { category } ) => ! category
) }
selectedBlockTypes={ selectedBlockTypes }
onChange={ onChange }
/>
</div>
</div>
);
}