modules_Fieldset_index.js

import { React, PropTypes, classnames } from '@gravityforms/libraries';
import { spacerClasses, uniqueId } from '@gravityforms/utils';
import HelpText from '../../elements/HelpText';
import Label from '../../elements/Label';

const { forwardRef } = React;

/**
 * @module Fieldset
 * @description An accessible fieldset component that groups related form controls with a legend
 * and optional help text. Uses the Label component with tagName="legend" for consistent styling
 * and HelpText for accessible descriptions via aria-describedby.
 *
 * @since 6.1.0
 *
 * @param {object}                     props                       Component props.
 * @param {JSX.Element}                props.children              React element children (form controls).
 * @param {object}                     props.customAttributes      Custom attributes for the fieldset element.
 * @param {string|Array|object}        props.customClasses         Custom classes for the fieldset element.
 * @param {boolean}                    props.disabled              Whether the fieldset is disabled.
 * @param {object}                     props.helpTextAttributes    Attributes for the optional HelpText component.
 * @param {string|Array|object}        props.helpTextCustomClasses Custom classes for the HelpText component.
 * @param {string}                     props.helpTextPosition      The position of the help text, 'above' or 'below' (default: 'below').
 * @param {string}                     props.id                    Id for the fieldset, auto-generated if not provided.
 * @param {object}                     props.legendAttributes      Attributes for the legend (uses Label component props except htmlFor).
 * @param {string|Array|object}        props.legendCustomClasses   Custom classes for the legend element.
 * @param {string|number|Array|object} props.spacing               The spacing for the component, as a string, number, array, or object.
 * @param {object|null}                ref                         Ref to the component.
 *
 * @return {JSX.Element} The Fieldset component.
 *
 * @example
 * import Fieldset from '@gravityforms/components/react/admin/modules/Fieldset';
 *
 * return (
 *     <Fieldset
 *         legendAttributes={ { label: 'Contact Information' } }
 *         helpTextAttributes={ { content: 'Please fill out all required fields.' } }
 *     >
 *         <Input label="First Name" />
 *         <Input label="Last Name" />
 *     </Fieldset>
 * );
 *
 */
const Fieldset = forwardRef( ( {
	children = null,
	customAttributes = {},
	customClasses = [],
	disabled = false,
	helpTextAttributes = {},
	helpTextCustomClasses = [],
	helpTextPosition = 'below',
	id = '',
	legendAttributes = {},
	legendCustomClasses = [],
	spacing = '',
}, ref ) => {
	const fieldsetId = id || uniqueId( 'fieldset' );
	const helpTextId = `${ fieldsetId }-help-text`;
	const hasHelpText = Boolean( helpTextAttributes.content );

	const fieldsetProps = {
		className: classnames( {
			'gform-fieldset': true,
			[ `gform-fieldset--help-text-${ helpTextPosition }` ]: true,
			'gform-fieldset--disabled': disabled,
			...spacerClasses( spacing ),
		}, customClasses ),
		disabled,
		id: fieldsetId,
		ref,
		...customAttributes,
	};

	if ( hasHelpText ) {
		fieldsetProps[ 'aria-describedby' ] = helpTextId;
	}

	const legendProps = {
		tagName: 'legend',
		customClasses: classnames( {
			'gform-fieldset__legend': true,
		}, legendCustomClasses ),
		...legendAttributes,
	};

	const helpTextProps = {
		id: helpTextId,
		customClasses: classnames( {
			'gform-fieldset__help-text': true,
		}, helpTextCustomClasses ),
		...helpTextAttributes,
	};

	const helpTextComponent = hasHelpText && <HelpText { ...helpTextProps } />;

	return (
		<fieldset { ...fieldsetProps }>
			{ legendAttributes.label && <Label { ...legendProps } /> }
			{ helpTextPosition === 'above' && helpTextComponent }
			{ children }
			{ helpTextPosition === 'below' && helpTextComponent }
		</fieldset>
	);
} );

Fieldset.propTypes = {
	children: PropTypes.oneOfType( [
		PropTypes.arrayOf( PropTypes.node ),
		PropTypes.node,
	] ),
	customAttributes: PropTypes.object,
	customClasses: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.array,
		PropTypes.object,
	] ),
	disabled: PropTypes.bool,
	helpTextAttributes: PropTypes.object,
	helpTextCustomClasses: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.array,
		PropTypes.object,
	] ),
	helpTextPosition: PropTypes.string,
	id: PropTypes.string,
	legendAttributes: PropTypes.object,
	legendCustomClasses: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.array,
		PropTypes.object,
	] ),
	spacing: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.number,
		PropTypes.array,
		PropTypes.object,
	] ),
};

Fieldset.displayName = 'Fieldset';

export default Fieldset;