UNPKG

@gravityforms/components

Version:

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

243 lines (226 loc) 7.33 kB
import { React, PropTypes, classnames } from '@gravityforms/libraries'; import { spacerClasses, uniqueId } from '@gravityforms/utils'; import Label from '../Label'; import HelpText from '../HelpText'; const { useState, forwardRef } = React; /** * @module Range * @description A multi type input component that supports standard text, email, tel. * * @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 input is disabled. * @param {object} props.helpTextAttributes Custom attribute for the help text. * @param {string} props.helpTextPosition The position of the help text. * @param {string} props.id Optional id. Auto generated if not passed. * @param {object} props.labelAttributes Any custom attributes for the label. * @param {number} props.max Maximum value for the range. * @param {number} props.min Minimum value for the range. * @param {string} props.name The name attribute for the input. * @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 {boolean} props.showValueInput Whether to display the value input or not. * @param {string|number|Array|object} props.spacing The spacing for the component, as a string, number, array, or object. * @param {number} props.step The step size of the range. * @param {string} props.theme The theme of the range. * @param {number} props.value The input value. * @param {string} props.valueInputPosition The position of the value input, one of `before` or `after`. * @param {string} props.valueInputSuffix Suffix for the value input. * @param {object} props.wrapperAttributes Custom attributes for the wrapper element. * @param {string|Array|object} props.wrapperClasses Custom classes for the wrapper element. * @param {object} props.wrapperTagName Tag to use for the input wrapper. Defaults to `div`. * @param {object|null} ref Ref to the component. * * @return {JSX.Element} The range component. * * @example * import Range from '@gravityforms/components/react/admin/elements/Range'; * * return ( * <Range * max={ 100 } * min={ 0 } * name="range-name" * onChange={ () => {} } * step={ 5 } * value={ 50 } * /> * ); * */ const Range = forwardRef( ( { customAttributes = {}, customClasses = [], disabled = false, helpTextAttributes = { size: 'text-xs', weight: 'regular', }, helpTextPosition = 'below', id = '', labelAttributes = { size: 'text-sm', weight: 'medium', }, max = 0, min = 0, name = '', onBlur = () => {}, onChange = () => {}, onFocus = () => {}, showValueInput = false, spacing = '', step = 1, theme = 'cosmos', value = 0, valueInputPosition = 'before', valueInputSuffix = '', wrapperAttributes = {}, wrapperClasses = [], wrapperTagName = 'div', }, ref ) => { const [ inputValue, setInputValue ] = useState( value ); const inputId = id || uniqueId( 'input' ); const helpTextId = `${ inputId }-help-text`; const wrapperProps = { ...wrapperAttributes, className: classnames( { 'gform-input-wrapper': true, [ `gform-input-wrapper--theme-${ theme }` ]: true, 'gform-input-wrapper--input': true, 'gform-input-wrapper--disabled': disabled, ...spacerClasses( spacing ), }, wrapperClasses ), ref, }; const inputProps = { ...customAttributes, className: classnames( { 'gform-input': true, 'gform-input--range': true, 'gform-input--theme-cosmos': true, }, customClasses ), id: inputId, max, min, step, name, onBlur, onChange: ( e ) => { const { value: newInputValue } = e.target; setInputValue( newInputValue ); onChange( newInputValue, e ); }, onFocus, type: 'range', value: inputValue, }; if ( disabled ) { inputProps.disabled = true; } const labelProps = { ...labelAttributes, htmlFor: inputId, }; const helpTextProps = { ...helpTextAttributes, id: helpTextId, }; const inputWrapperProps = { className: classnames( { 'gform-input-range-wrapper': true, } ), }; const Container = wrapperTagName; /** * @function getValueInput * @description Get the value input for the range component. * * @since 1.1.15 * * @return {JSX.Element} The value input react markup. */ const getValueInput = () => { const valueInputProps = { className: classnames( { 'gform-input--range-value-input': true, } ), disabled, max, min, onChange: ( e ) => { const { value: newInputValue } = e.target; setInputValue( newInputValue ); }, type: 'number', value: inputValue, }; const containerProps = { className: classnames( { 'gform-input-range-value-wrapper': true, } ), }; return ( <div { ...containerProps }> <input { ...valueInputProps } /> { valueInputSuffix && <div className="gform-input--range__suffix">{ valueInputSuffix }</div> } </div> ); }; return ( <Container { ...wrapperProps }> <Label { ...labelProps } /> { helpTextPosition === 'above' && <HelpText { ...helpTextProps } /> } <div { ...inputWrapperProps } > { showValueInput && valueInputPosition === 'before' && getValueInput() } <input { ...inputProps } /> { showValueInput && valueInputPosition === 'after' && getValueInput() } </div> { helpTextPosition === 'below' && <HelpText { ...helpTextProps } /> } </Container> ); } ); Range.propTypes = { customAttributes: PropTypes.object, customClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), disabled: PropTypes.bool, helpTextAttributes: PropTypes.object, helpTextPosition: PropTypes.string, id: PropTypes.string, labelAttributes: PropTypes.object, max: PropTypes.number, min: PropTypes.number, name: PropTypes.string, onBlur: PropTypes.func, onChange: PropTypes.func, onFocus: PropTypes.func, showValueInput: PropTypes.bool, spacing: PropTypes.oneOfType( [ PropTypes.string, PropTypes.number, PropTypes.array, PropTypes.object, ] ), step: PropTypes.number, theme: PropTypes.string, value: PropTypes.number, valueInputPosition: PropTypes.oneOf( [ 'before', 'after' ] ), valueInputSuffix: PropTypes.string, wrapperAttributes: PropTypes.object, wrapperClasses: PropTypes.oneOfType( [ PropTypes.string, PropTypes.array, PropTypes.object, ] ), wrapperTagName: PropTypes.string, }; Range.displayName = 'Range'; export default Range;