diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js index ad597671aba41..c2d8a919714d9 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js @@ -9,17 +9,24 @@ import { map } from 'lodash'; import { __ } from '@wordpress/i18n'; import { useSelect } from '@wordpress/data'; import { - __experimentalNavigationItem as NavigationItem, __experimentalNavigationMenu as NavigationMenu, + __experimentalNavigationItem as NavigationItem, } from '@wordpress/components'; +import { useState, useCallback } from '@wordpress/element'; /** * Internal dependencies */ import TemplateNavigationItem from '../template-navigation-item'; import { MENU_ROOT, MENU_TEMPLATE_PARTS } from '../constants'; +import SearchResults from '../search-results'; export default function TemplatePartsMenu() { + const [ search, setSearch ] = useState( '' ); + const onSearch = useCallback( ( value ) => { + setSearch( value ); + } ); + const templateParts = useSelect( ( select ) => { const unfilteredTemplateParts = select( 'core' ).getEntityRecords( 'postType', 'wp_template_part', { @@ -38,15 +45,25 @@ export default function TemplatePartsMenu() { menu={ MENU_TEMPLATE_PARTS } title={ __( 'Template Parts' ) } parentMenu={ MENU_ROOT } + hasSearch={ true } + onSearch={ onSearch } + search={ search } > - { map( templateParts, ( templatePart ) => ( - - ) ) } + { search && ( + + ) } + + { ! search && + map( templateParts, ( templatePart ) => ( + + ) ) } - { ! templateParts && } + { ! search && templateParts === null && ( + + ) } ); } diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js index e96aaef7f8d99..c3f15d44d10ed 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js @@ -12,6 +12,7 @@ import { } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { __, _x } from '@wordpress/i18n'; +import { useState, useCallback } from '@wordpress/element'; /** * Internal dependencies @@ -30,8 +31,14 @@ import { import TemplatesAllMenu from './templates-all'; import NewTemplateDropdown from '../new-template-dropdown'; import TemplateNavigationItem from '../template-navigation-item'; +import SearchResults from '../search-results'; export default function TemplatesMenu() { + const [ search, setSearch ] = useState( '' ); + const onSearch = useCallback( ( value ) => { + setSearch( value ); + } ); + const templates = useSelect( ( select ) => select( 'core' ).getEntityRecords( 'postType', 'wp_template', { @@ -51,27 +58,43 @@ export default function TemplatesMenu() { title={ __( 'Templates' ) } titleAction={ } parentMenu={ MENU_ROOT } + hasSearch={ true } + onSearch={ onSearch } + search={ search } > - { map( generalTemplates, ( template ) => ( - - ) ) } - - - + { search && ( + + ) } + + { ! search && ( + <> + + + + { map( generalTemplates, ( template ) => ( + + ) ) } + + ) } + + { ! search && templates === null && ( + + ) } + diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/search-results.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/search-results.js new file mode 100644 index 0000000000000..39e7b60cb1781 --- /dev/null +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/search-results.js @@ -0,0 +1,73 @@ +/** + * External dependencies + */ +import { map } from 'lodash'; + +/** + * WordPress dependencies + */ +import { useMemo } from '@wordpress/element'; +import { __experimentalNavigationGroup as NavigationGroup } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { normalizedSearch } from './utils'; +import { useSelect } from '@wordpress/data'; +import TemplateNavigationItem from './template-navigation-item'; + +export default function SearchResults( { items, search } ) { + const itemType = items?.length > 0 ? items[ 0 ].type : null; + + const itemInfos = useSelect( + ( select ) => { + if ( itemType === 'wp_template' ) { + const { + __experimentalGetTemplateInfo: getTemplateInfo, + } = select( 'core/editor' ); + + return items.map( ( item ) => ( { + slug: item.slug, + ...getTemplateInfo( item ), + } ) ); + } + + return items.map( ( item ) => ( { + slug: item.slug, + title: item.title?.rendered, + description: item.excerpt?.rendered, + } ) ); + }, + [ items, itemType ] + ); + + const itemsFiltered = useMemo( () => { + if ( items === null || search.length === 0 ) { + return []; + } + + return items.filter( ( { slug } ) => { + const { title, description } = itemInfos.find( + ( info ) => info.slug === slug + ); + + return ( + normalizedSearch( slug, search ) || + normalizedSearch( title, search ) || + normalizedSearch( description, search ) + ); + } ); + }, [ items, itemInfos, search ] ); + + return ( + + { map( itemsFiltered, ( item ) => ( + + ) ) } + + ); +} diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss index b8c982265b9cb..d4fe4b544deca 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss @@ -114,7 +114,6 @@ } .edit-site-navigation-panel__new-template-dropdown { - display: flex; margin: 0 0 0 $grid-unit-15; button { diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/utils.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/utils.js new file mode 100644 index 0000000000000..251b90cfe44df --- /dev/null +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/utils.js @@ -0,0 +1,11 @@ +/** + * External dependencies + */ +import { deburr } from 'lodash'; + +// @see packages/block-editor/src/components/inserter/search-items.js +export const normalizeInput = ( input ) => + deburr( input ).replace( /^\//, '' ).toLowerCase(); + +export const normalizedSearch = ( title, search ) => + -1 !== normalizeInput( title ).indexOf( normalizeInput( search ) );