/** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import AuthorSelect from './author-select'; import CategorySelect from './category-select'; import FormTokenField from '../form-token-field'; import RangeControl from '../range-control'; import SelectControl from '../select-control'; import { VStack } from '../v-stack'; import type { QueryControlsProps, QueryControlsWithMultipleCategorySelectionProps, QueryControlsWithSingleCategorySelectionProps, } from './types'; const DEFAULT_MIN_ITEMS = 1; const DEFAULT_MAX_ITEMS = 100; const MAX_CATEGORIES_SUGGESTIONS = 20; function isSingleCategorySelection( props: QueryControlsProps ): props is QueryControlsWithSingleCategorySelectionProps { return 'categoriesList' in props; } function isMultipleCategorySelection( props: QueryControlsProps ): props is QueryControlsWithMultipleCategorySelectionProps { return 'categorySuggestions' in props; } /** * Controls to query for posts. * * ```jsx * const MyQueryControls = () => ( * { * updateQuery( { orderBy: newOrderBy } ) * } * onOrderChange={ ( newOrder ) => { * updateQuery( { order: newOrder } ) * } * categoriesList={ categories } * selectedCategoryId={ category } * onCategoryChange={ ( newCategory ) => { * updateQuery( { category: newCategory } ) * } * onNumberOfItemsChange={ ( newNumberOfItems ) => { * updateQuery( { numberOfItems: newNumberOfItems } ) * } } * /> * ); * ``` */ export function QueryControls( { __next40pxDefaultSize = false, authorList, selectedAuthorId, numberOfItems, order, orderBy, maxItems = DEFAULT_MAX_ITEMS, minItems = DEFAULT_MIN_ITEMS, onAuthorChange, onNumberOfItemsChange, onOrderChange, onOrderByChange, // Props for single OR multiple category selection are not destructured here, // but instead are destructured inline where necessary. ...props }: QueryControlsProps ) { return ( { [ onOrderChange && onOrderByChange && ( { if ( typeof value !== 'string' ) { return; } const [ newOrderBy, newOrder ] = value.split( '/' ); if ( newOrder !== order ) { onOrderChange( newOrder as NonNullable< QueryControlsProps[ 'order' ] > ); } if ( newOrderBy !== orderBy ) { onOrderByChange( newOrderBy as NonNullable< QueryControlsProps[ 'orderBy' ] > ); } } } /> ), isSingleCategorySelection( props ) && props.categoriesList && props.onCategoryChange && ( ), isMultipleCategorySelection( props ) && props.categorySuggestions && props.onCategoryChange && ( ( { id: item.id, // Keeping the fallback to `item.value` for legacy reasons, // even if items of `selectedCategories` should not have a // `value` property. // @ts-expect-error value: item.name || item.value, } ) ) } suggestions={ Object.keys( props.categorySuggestions ) } onChange={ props.onCategoryChange } maxSuggestions={ MAX_CATEGORIES_SUGGESTIONS } /> ), onAuthorChange && ( ), onNumberOfItemsChange && ( ), ] } ); } export default QueryControls;