import {useEffect, useRef} from '@wordpress/element'; import '../scss/_field-control.scss'; import PremiumBadge from '../partials/premium-badge'; import ManualLink from '../partials/ManualLink'; // First element inside the field that should announce help/error text. const DESCRIBED_TARGET = '[role="group"], [role="radiogroup"], [role="switch"], [role="combobox"], input:not([type="hidden"]), select, textarea, button'; const FieldControl = ( { label, help, id, error, className = '', children, premium = false, labelClassName = '', helpClassName = '', link = '', ...props } ) => { const wrapperClasses = [ 'adpresso-field-control', className, premium && 'is-premium' ].filter( Boolean ).join( ' ' ); const helpId = help && id ? `${id}-description` : undefined; const errorId = error && id ? `${id}-error` : undefined; const innerRef = useRef( null ); // Wires help/error text to the control without every field component having to pass it through. useEffect( () => { const target = innerRef.current?.querySelector( DESCRIBED_TARGET ); if ( !target ) { return; } const ownIds = [helpId, errorId].filter( Boolean ); const otherIds = ( target.getAttribute( 'aria-describedby' ) || '' ) .split( ' ' ) .filter( ( ref ) => ref && ref !== `${id}-description` && ref !== `${id}-error` ); const describedBy = [...otherIds, ...ownIds].join( ' ' ); if ( describedBy ) { target.setAttribute( 'aria-describedby', describedBy ); } else { target.removeAttribute( 'aria-describedby' ); } if ( errorId ) { target.setAttribute( 'aria-invalid', 'true' ); } else if ( target.getAttribute( 'aria-invalid' ) === 'true' ) { target.removeAttribute( 'aria-invalid' ); } } ); return (
{label && ( )}
{children}
{error && (

{error}

)} {help && (

{help} {link && }

)}
); }; export default FieldControl;