UNPKG

@gravityforms/components

Version:

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

199 lines (183 loc) 6.58 kB
import { React, classnames, PropTypes } from '@gravityforms/libraries'; import { useStateWithDep } from '@gravityforms/react-utils'; import { spacerClasses, uniqueId } from '@gravityforms/utils'; import Label from '../Label'; import HelpText from '../HelpText'; const { forwardRef, useEffect, useRef, useState } = React; /** * @module Checkbox * @description A checkbox input component. * * @since 1.1.15 * * @param {object} props Component props. * @param {object} props.customAttributes Custom attributes for the component. * @param {string|Array|object} props.customClasses Custom classes for the component. * @param {boolean} props.disabled If checkbox is disabled. * @param {boolean} props.externalChecked If checkbox is checked or not, can change current checked state if changed. * @param {boolean} props.externalControl If checkbox is controlled externally. * @param {object} props.helpTextAttributes Custom attribute for the help text. * @param {string} props.id Optional id. Auto generated if not passed. * @param {boolean} props.indeterminate If checkbox is indeterminate, only works if externally controlled. * @param {boolean} props.initialChecked Whether it is checked on initial render. * @param {object} props.labelAttributes Custom attributes for the label. * @param {string} props.name The name attribute for the checkbox. * @param {Function} props.onBlur On blur function handler. * @param {Function} props.onChange On change function handler. * @param {Function} props.onFocus On focus function handler. * @param {string} props.size The checkbox size, small (`size-sm`) or medium (`size-md`). * @param {string|number|Array|object} props.spacing The spacing for the component, as a string, number, array, or object. * @param {string} props.theme The theme of the checkbox. * @param {string} props.value The checkbox value. * @param {object} props.wrapperAttributes Custom attributes for the wrapper element. * @param {string|Array|object} props.wrapperClasses Custom classes for the wrapper element. * @param {string} props.wrapperTagName Tag to use for the checkbox wrapper. Defaults to `div`. * @param {object|null} ref Ref to the component. * * @return {JSX.Element} The checkbox component. * * @example * import Checkbox from '@gravityforms/components/react/admin/elements/Checkbox'; * * return ( * <Checkbox /> * checked={ true } * labelAttributes={ { * label: 'Check me!', * } } * id="checkbox" * onChange={ () => {} } * /> * ); * */ const Checkbox = forwardRef( ( { customAttributes = {}, customClasses = [], disabled = false, externalChecked = false, externalControl = false, helpTextAttributes = {}, id = '', indeterminate = false, initialChecked = false, labelAttributes = {}, name = '', onBlur = () => {}, onChange = () => {}, onFocus = () => {}, size = 'size-sm', spacing = '', theme = 'cosmos', value = '', wrapperAttributes = {}, wrapperClasses = [], wrapperTagName = 'div', }, ref ) => { const [ inputChecked, setInputChecked ] = useState( initialChecked ); const [ controlChecked, setControlChecked ] = useStateWithDep( externalChecked ); // eslint-disable-line no-unused-vars const inputRef = useRef(); const inputId = id || uniqueId( 'checkbox' ); const helpTextId = `${ inputId }-help-text`; useEffect( () => { if ( ! inputRef.current ) { return; } // Do not set indeterminate prop if not controlled externally or if the checkbox is checked. if ( ! externalControl || controlChecked ) { return; } inputRef.current.indeterminate = indeterminate; }, [ indeterminate, inputRef, controlChecked ] ); const wrapperProps = { ...wrapperAttributes, className: classnames( { 'gform-input-wrapper': true, [ `gform-input-wrapper--theme-${ theme }` ]: true, 'gform-input-wrapper--checkbox': true, 'gform-input-wrapper--disabled': disabled, ...spacerClasses( spacing ), }, wrapperClasses ), ref, }; const inputProps = { ...customAttributes, checked: externalControl ? controlChecked : inputChecked, className: classnames( { 'gform-input--checkbox': true, [ `gform-input--${ size }` ]: true, }, customClasses ), disabled: disabled || labelAttributes?.locked === true, id: inputId, name, onBlur, onChange: ( e ) => { const { checked: inputCheckedState } = e.target; if ( ! externalControl ) { setInputChecked( inputCheckedState ); } onChange( inputCheckedState, e ); }, onFocus, ref: inputRef, type: 'checkbox', value, }; if ( helpTextAttributes.content ) { inputProps[ 'aria-describedby' ] = helpTextId; } const labelProps = { ...labelAttributes, htmlFor: inputId, }; const helpTextProps = { ...helpTextAttributes, id: helpTextId, }; const Container = wrapperTagName; return ( <Container { ...wrapperProps }> <input { ...inputProps } /> <Label { ...labelProps } /> <HelpText { ...helpTextProps } /> </Container> ); } ); Checkbox.propTypes = { customAttributes: PropTypes.object, customClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), disabled: PropTypes.bool, externalChecked: PropTypes.bool, externalControl: PropTypes.bool, helpTextAttributes: PropTypes.object, id: PropTypes.string, indeterminate: PropTypes.bool, initialChecked: PropTypes.bool, labelAttributes: PropTypes.object, name: PropTypes.string, onBlur: PropTypes.func, onChange: PropTypes.func, onFocus: PropTypes.func, size: PropTypes.string, spacing: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number, PropTypes.array, PropTypes.object, ] ), theme: PropTypes.string, value: PropTypes.string, wrapperAttributes: PropTypes.object, wrapperClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), wrapperTagName: PropTypes.string, }; Checkbox.displayName = 'Checkbox'; export default Checkbox;