UNPKG

@gravityforms/components

Version:

UI components for use in Gravity Forms development. Both React and vanilla js flavors.

164 lines (150 loc) 5.11 kB
import { React, PropTypes, classnames } from '@gravityforms/libraries'; import { ConditionalWrapper } from '@gravityforms/react-utils'; import { spacerClasses, uniqueId } from '@gravityforms/utils'; import Checkbox from '../../elements/Checkbox'; import Radio from '../../elements/Radio'; const { forwardRef, useState } = React; /** * @module InputGroup * @description A inputgroup component that wraps checkboxes or radios and handles their state changes as one * aggregate. * * @since 1.1.15 * * @param {object} props Component props. * @param {JSX.Element} props.children React element children. * @param {boolean} props.childrenBelow Render children below or above group if found? * @param {object} props.customAttributes Custom attributes for the component. * @param {string|Array|object} props.customClasses Custom classes for the component. * @param {Array} props.data The data for the inputs. * @param {string} props.id The id of the input group. * @param {string} props.initialValue The initial value of the input group if input type is radio. * @param {string} props.inputType The input type, one of `radio` or `checkbox`. * @param {Function} props.onChange On change function handler. * @param {string|number|Array|object} props.spacing The spacing for the component, as a string, number, array, or object. * @param {string} props.tagName Tagname for the container. * @param {boolean} props.useWrapper Whether to use a wrapper around the inputs or not. * @param {object} props.wrapperAttributes Custom attributes for the wrapper component. * @param {string} props.wrapperTagName Tagname for the wrapper. * @param {object|null} ref Ref to the component. * * @return {JSX.Element} The InputGroup component. * * @example * import InputGroup from '@gravityforms/components/react/admin/modules/InputGroup'; * * return ( * <InputGroup * id="setup-wizard-form-types" * data={ [ { ...input1Data }, { ...input2Data } ] } * onChange={ () => { handleInputChange(); } } * useWrapper={ true } * /> * ); * */ const InputGroup = forwardRef( ( { children = null, childrenBelow = true, customAttributes = {}, customClasses = [], data = [], id = '', initialValue = '', inputType = 'checkbox', onChange = () => {}, spacing = '', tagName = 'div', useWrapper = false, wrapperAttributes = {}, wrapperTagName = 'div', }, ref ) => { const [ value, setValue ] = useState( initialValue ); const componentProps = { className: classnames( { 'gform-input-group': true, ...spacerClasses( spacing ), }, customClasses ), ...customAttributes, }; const inputId = id || uniqueId( 'input-group' ); const InputContainer = inputType === 'checkbox' ? Checkbox : Radio; const handleOnChange = ( checked, e ) => { if ( inputType === 'radio' ) { setValue( e.target.value ); } onChange( checked, e ); }; const getWrapper = ( ch ) => { const Wrapper = wrapperTagName; const { customClasses: wrapperCustomClasses, ...restWrapperAttributes } = wrapperAttributes; const wrapperProps = { ...restWrapperAttributes, className: classnames( [ 'gform-input-group__wrapper' ], wrapperCustomClasses || [], ), }; return <Wrapper { ...wrapperProps }>{ ch }</Wrapper>; }; const Container = tagName; return ( <Container { ...componentProps } ref={ ref }> { ! childrenBelow && children } { data.map( ( props, index ) => { const inputProps = { ...props, onChange: handleOnChange, }; if ( inputType === 'radio' ) { inputProps.externalControl = true; inputProps.externalChecked = props.value === value; } return ( <ConditionalWrapper condition={ useWrapper } key={ `${ inputId }-${ index }` } wrapper={ getWrapper } > <InputContainer { ...inputProps } /> </ConditionalWrapper> ); } ) } { childrenBelow && children } </Container> ); } ); InputGroup.propTypes = { children: PropTypes.oneOfType( [ PropTypes.arrayOf( PropTypes.node ), PropTypes.node, ] ), childrenBelow: PropTypes.bool, customAttributes: PropTypes.object, customClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), data: PropTypes.array, id: PropTypes.string, inputType: PropTypes.string, onChange: PropTypes.func, spacing: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number, PropTypes.array, PropTypes.object, ] ), tagName: PropTypes.string, useWrapper: PropTypes.bool, wrapperAttributes: PropTypes.object, wrapperTagName: PropTypes.string, }; InputGroup.displayName = 'InputGroup'; export default InputGroup;