UNPKG

@react-ui-org/react-ui

Version:

React UI is a themeable UI library for React apps.

168 lines (160 loc) 4.52 kB
import PropTypes from 'prop-types'; import React, { useContext } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; import { classNames } from '../../helpers/classNames/classNames'; import { transferProps } from '../../helpers/transferProps'; import { getRootSizeClassName } from '../_helpers/getRootSizeClassName'; import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; import { FormLayoutContext } from '../FormLayout'; import styles from './TextArea.module.scss'; export const TextArea = React.forwardRef((props, ref) => { const { disabled, fullWidth, helpText, id, isLabelVisible, label, layout, required, size, validationState, validationText, variant, ...restProps } = props; const context = useContext(FormLayoutContext); return ( <label className={classNames( styles.root, fullWidth && styles.isRootFullWidth, context && styles.isRootInFormLayout, resolveContextOrProp(context && context.layout, layout) === 'horizontal' ? styles.isRootLayoutHorizontal : styles.isRootLayoutVertical, disabled && styles.isRootDisabled, required && styles.isRootRequired, getRootSizeClassName(size, styles), getRootValidationStateClassName(validationState, styles), variant === 'filled' ? styles.isRootVariantFilled : styles.isRootVariantOutline, )} htmlFor={id} id={id && `${id}__label`} > <div className={classNames( styles.label, !isLabelVisible && styles.isLabelHidden, )} id={id && `${id}__labelText`} > {label} </div> <div className={styles.field}> <div className={styles.inputContainer}> <textarea {...transferProps(restProps)} className={styles.input} disabled={disabled} id={id} ref={ref} required={required} /> {variant === 'filled' && ( <div className={styles.bottomLine} /> )} </div> {helpText && ( <div className={styles.helpText} id={id && `${id}__helpText`} > {helpText} </div> )} {validationText && ( <div className={styles.validationText} id={id && `${id}__validationText`} > {validationText} </div> )} </div> </label> ); }); TextArea.defaultProps = { disabled: false, fullWidth: false, helpText: null, id: undefined, isLabelVisible: true, layout: 'vertical', required: false, size: 'medium', validationState: null, validationText: null, variant: 'outline', }; TextArea.propTypes = { /** * If `true`, the input will be disabled. */ disabled: PropTypes.bool, /** * If `true`, the field will span the full width of its parent. */ fullWidth: PropTypes.bool, /** * Optional help text. */ helpText: PropTypes.node, /** ID of the input HTML element. It also serves as a prefix for nested elements: * * `<ID>__label` * * `<ID>__labelText` * * `<ID>__helpText` * * `<ID>__validationText` */ id: PropTypes.string, /** * If `false`, the label will be visually hidden (but remains accessible by assistive * technologies). */ isLabelVisible: PropTypes.bool, /** * Text field label. */ label: PropTypes.node.isRequired, /** * Layout of the field. * * Ignored if the component is rendered within `FormLayout` component * as the value is inherited in such case. */ layout: PropTypes.oneOf(['horizontal', 'vertical']), /** * If `true`, the input will be required. */ required: PropTypes.bool, /** * Size of the field. */ size: PropTypes.oneOf(['small', 'medium', 'large']), /** * Alter the field to provide feedback based on validation result. */ validationState: PropTypes.oneOf(['invalid', 'valid', 'warning']), /** * Validation message to be displayed. */ validationText: PropTypes.node, /** * Design variant of the field, further customizable with CSS custom properties. */ variant: PropTypes.oneOf(['filled', 'outline']), }; export const TextAreaWithGlobalProps = withGlobalProps(TextArea, 'TextArea'); export default TextAreaWithGlobalProps;