/**
* WordPress dependencies
*/
import { privateApis, Spinner } from '@wordpress/components';
import { useCallback, useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
import type { DataFormControlProps } from '../../types';
import { unlock } from '../../lock-unlock';
import getCustomValidity from './utils/get-custom-validity';
import useElements from '../../hooks/use-elements';
const { ValidatedFormTokenField } = unlock( privateApis );
export default function ArrayControl< Item >( {
data,
field,
onChange,
hideLabelFromVision,
markWhenOptional,
validity,
}: DataFormControlProps< Item > ) {
const { label, placeholder, getValue, setValue, isValid } = field;
const value = getValue( { item: data } );
const { elements, isLoading } = useElements( {
elements: field.elements,
getElements: field.getElements,
} );
// Convert stored values to element objects for the token field
const arrayValueAsElements = useMemo(
() =>
Array.isArray( value )
? value.map( ( token ) => {
const element = elements?.find(
( suggestion ) => suggestion.value === token
);
return element || { value: token, label: token };
} )
: [],
[ value, elements ]
);
const onChangeControl = useCallback(
( tokens: ( string | { value: string; label?: string } )[] ) => {
const valueTokens = tokens.map( ( token ) => {
if ( typeof token === 'object' && 'value' in token ) {
return token.value;
}
// If it's a string, it's either a new suggestion value or user input
return token;
} );
onChange( setValue( { item: data, value: valueTokens } ) );
},
[ onChange, setValue, data ]
);
if ( isLoading ) {
return ;
}
return (
element.value ) }
__experimentalValidateInput={ ( token: string ) => {
// If elements validation is required, check if token is valid
if ( field.isValid?.elements && elements ) {
return elements.some(
( element ) =>
element.value === token || element.label === token
);
}
// For non-elements validation, allow all tokens
return true;
} }
__experimentalExpandOnFocus={ elements && elements.length > 0 }
__experimentalShowHowTo={ ! field.isValid?.elements }
displayTransform={ ( token: any ) => {
// For existing tokens (element objects), display their label
if ( typeof token === 'object' && 'label' in token ) {
return token.label;
}
// For suggestions (value strings), find the corresponding element and show its label
if ( typeof token === 'string' && elements ) {
const element = elements.find(
( el ) => el.value === token
);
return element?.label || token;
}
return token;
} }
__experimentalRenderItem={ ( { item }: { item: any } ) => {
// Custom rendering for suggestion items (item is a value string)
if ( typeof item === 'string' && elements ) {
const element = elements.find(
( el ) => el.value === item
);
return { element?.label || item };
}
return { item };
} }
/>
);
}