import { useState, useEffect } from '@wordpress/element';
import {
Button,
CheckboxControl,
Spinner,
TextControl,
} from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';
export default function TaxonomySelector( { blockConfig, objectType, endpoint, onChange } ) {
const [ availableTaxonomies, setAvailableTaxonomies ] = useState( [] );
const [ termsCache, setTermsCache ] = useState( {} );
const [ loadingTax, setLoadingTax ] = useState( false );
const [ loadingTerms, setLoadingTerms ] = useState( {} );
const [ search, setSearch ] = useState( '' );
const taxonomies = blockConfig.taxonomies || {};
const taxObjectType = objectType || blockConfig.post_type || 'post';
useEffect( () => {
setLoadingTax( true );
const path = endpoint
? `wlconduit/v1/ext/${ endpoint }`
: `wlconduit/v1/taxonomies?object_type=${ taxObjectType }`;
apiFetch( { path } )
.then( ( data ) => setAvailableTaxonomies( data || [] ) )
.catch( () => setAvailableTaxonomies( [] ) )
.finally( () => setLoadingTax( false ) );
}, [ endpoint, taxObjectType ] );
function loadTerms( taxonomy, refresh = false ) {
if ( termsCache[ taxonomy ] && ! refresh ) {
return;
}
setLoadingTerms( ( prev ) => ( { ...prev, [ taxonomy ]: true } ) );
const refreshParam = refresh ? '&refresh=1' : '';
apiFetch( { path: `wlconduit/v1/terms?taxonomy=${ taxonomy }${ refreshParam }` } )
.then( ( data ) => {
setTermsCache( ( prev ) => ( { ...prev, [ taxonomy ]: data || [] } ) );
} )
.catch( () => {} )
.finally( () => {
setLoadingTerms( ( prev ) => ( { ...prev, [ taxonomy ]: false } ) );
} );
}
function toggleTaxonomy( taxSlug ) {
const updated = { ...taxonomies };
if ( updated[ taxSlug ] ) {
delete updated[ taxSlug ];
} else {
updated[ taxSlug ] = {
as_field: true,
as_filter: false,
terms: [],
};
loadTerms( taxSlug );
}
onChange( updated );
}
function updateTaxConfig( taxSlug, partial ) {
const updated = {
...taxonomies,
[ taxSlug ]: { ...taxonomies[ taxSlug ], ...partial },
};
// Load terms when enabling as filter.
if ( partial.as_filter && ! termsCache[ taxSlug ] ) {
loadTerms( taxSlug );
}
onChange( updated );
}
function toggleTerm( taxSlug, termSlug ) {
const currentTerms = taxonomies[ taxSlug ]?.terms || [];
const updatedTerms = currentTerms.includes( termSlug )
? currentTerms.filter( ( t ) => t !== termSlug )
: [ ...currentTerms, termSlug ];
updateTaxConfig( taxSlug, { terms: updatedTerms } );
}
if ( loadingTax ) {
return
Select taxonomies to include as data or expose as filters. When used as a filter, pick which terms the AI can filter by.
{ availableTaxonomies.length > 0 && (No taxonomies found for this post type.
) : ( availableTaxonomies.filter( ( tax ) => { if ( ! search ) { return true; } const term = search.toLowerCase(); return ( tax.name || '' ).toLowerCase().includes( term ) || ( tax.label || '' ).toLowerCase().includes( term ); } ).map( ( tax ) => { const isSelected = !! taxonomies[ tax.name ]; const isInternal = tax.internal || false; const config = taxonomies[ tax.name ] || {}; const terms = termsCache[ tax.name ] || []; const isLoadingTerms = loadingTerms[ tax.name ]; return (No terms found.
) : ( terms.map( ( term ) => (