@gravityforms/components
Version:
UI components for use in Gravity Forms development. Both React and vanilla js flavors.
127 lines (118 loc) • 3.65 kB
JavaScript
import { React, PropTypes } from '@gravityforms/libraries';
import Alert from '../modules/Alert';
import Box from '../elements/Box';
import Checkbox from '../elements/Checkbox';
import Heading from '../elements/Heading';
import Icon from '../elements/Icon';
import Input from '../elements/Input';
import InputGroup from '../modules/InputGroup';
import Label from '../elements/Label';
import BasicLink from '../elements/Link';
import Radio from '../elements/Radio';
import Select from '../elements/Select';
import Text from '../elements/Text';
import Textarea from '../elements/Textarea';
import Toggle from '../elements/Toggle';
const { Fragment, memo, useCallback } = React;
/**
* @module FormField
* @description Renders a form field based on passed field data from the server.
*
* @since 3.1.0
*
* @param {object} props Component props.
* @param {string} props.id Field ID.
* @param {object} props.field Field data.
* @param {Function} props.setFieldData Passed handler for field changes if the field type supports it.
*
* @return {JSX.Element} The FormField component.
*/
const FormField = memo( ( { id, field, setFieldData } ) => {
const handleChange = useCallback( ( value, e ) => {
if ( e && e.target.type === 'radio' ) {
setFieldData( e.target.name, e.target.value );
} else if ( field.props && field.props.name ) {
setFieldData( field.props.name, value );
}
}, [ field.props, setFieldData ] );
const renderNestedFields = ( fields ) => {
if ( ! fields ) {
return null;
}
return fields.map( ( nestedField, index ) => {
const fieldId = `${ id }-${ index }`;
return <FormField key={ fieldId } id={ fieldId } field={ nestedField } setFieldData={ setFieldData } />;
} );
};
let component = null;
if ( field.external ) {
const External = field.component;
const fieldProps = {
...field.props,
onChange: field?.handle_change ? handleChange : undefined,
};
component = <External { ...fieldProps } />;
} else {
const fieldProps = {
id,
...field.props,
};
switch ( field.component ) {
case 'Alert':
component = <Alert { ...fieldProps }>{ renderNestedFields( field.fields ) }</Alert>;
break;
case 'Box':
component = <Box { ...fieldProps }>{ renderNestedFields( field.fields ) }</Box>;
break;
case 'Checkbox':
component = <Checkbox { ...fieldProps } onChange={ handleChange } />;
break;
case 'Heading':
component = <Heading { ...fieldProps } />;
break;
case 'Icon':
component = <Icon { ...fieldProps } />;
break;
case 'Input':
component = <Input { ...fieldProps } onChange={ handleChange } />;
break;
case 'InputGroup':
component = <InputGroup { ...fieldProps } onChange={ handleChange } />;
break;
case 'Label':
component = <Label { ...fieldProps } />;
break;
case 'Link':
component = <BasicLink { ...fieldProps } />;
break;
case 'Radio':
component = <Radio { ...fieldProps } onChange={ handleChange } />;
break;
case 'Select':
component = <Select { ...fieldProps } onChange={ handleChange } />;
break;
case 'Text':
component = <Text { ...fieldProps } />;
break;
case 'Textarea':
component = <Textarea { ...fieldProps } onChange={ handleChange } />;
break;
case 'Toggle':
component = <Toggle { ...fieldProps } onChange={ handleChange } />;
break;
default:
component = null;
}
}
return (
<Fragment>
{ component }
</Fragment>
);
} );
FormField.propTypes = {
id: PropTypes.string,
field: PropTypes.object,
setFieldData: PropTypes.func,
};
export default FormField;