optimizely-oui
Version:
Optimizely's Component Library.
185 lines (173 loc) • 5.61 kB
JavaScript
import React from "react";
import Label from "../Label";
import classNames from "classnames";
import PropTypes from "prop-types";
/**
* Generates a `textarea` element.
* @param {Object} props - Properties passed to component
* @returns {ReactElement}
*/
class Textarea extends React.Component {
blur() {
if (this._textarea) {
this._textarea.blur();
}
}
renderTextarea({
className,
defaultValue,
displayError,
focus,
isDisabled,
isOptional,
isReadOnly,
isRequired,
label,
maxLength,
note,
numRows,
onBlur,
onChange,
onFocus,
onInput,
onKeyDown,
placeholder,
testSection,
value,
...props
}) {
const classes = classNames({ "oui-textarea": true }, { "oui-form-bad-news": displayError }, className);
return (
/* eslint-disable react/jsx-no-bind */
<textarea
data-oui-component={true}
className={classes}
ref={c => {
this._textarea = c;
}}
value={value}
defaultValue={defaultValue}
placeholder={placeholder}
required={isRequired}
readOnly={isReadOnly}
disabled={isDisabled}
{...(typeof maxLength === "undefined" ? {} : { maxLength })}
maxLength={maxLength}
rows={numRows}
onInput={onInput}
onChange={onChange}
onBlur={onBlur}
onKeyDown={onKeyDown}
onFocus={onFocus}
autoFocus={focus}
data-test-section={testSection}
{...props}
/>
/* eslint-enable react/jsx-no-bind */
);
}
renderNote({ note, testSection }) {
return (
<div className="oui-form-note" data-test-section={testSection && testSection + "-note"}>
{note}
</div>
);
}
render() {
const {
displayError,
isOptional,
isRequired,
label,
note,
testSection,
} = this.props;
if (label) {
return (
<div data-oui-component={true} className={classNames({ "oui-form-bad-news": displayError })}>
<Label testSection={testSection && testSection + "-label"}>
<div className="oui-label">
{label}
{isOptional && <span className="oui-label__optional">(Optional)</span>}
{isRequired && <span className="oui-label--required"></span>}
</div>
{this.renderTextarea(this.props)}
</Label>
{note && this.renderNote(this.props)}
</div>
);
}
if (note) {
return [this.renderTextarea(this.props), this.renderNote(this.props)];
}
return this.renderTextarea(this.props);
}
}
Textarea.propTypes = {
/** The default value of the textarea used on initial render */
defaultValue: PropTypes.string,
/** Shows error styling if true */
displayError: PropTypes.bool,
/** Auto focus the Textaraea if true */
focus: PropTypes.bool,
/** Prevents textarea from being modified and appears disabled */
isDisabled: PropTypes.bool,
/** Adds an optional label if there is a label provided
* @param {Object} props Object of props
* @returns {Error} Error or null
*/
isOptional: function verifyIsOptionalProp(props) {
if (props.isOptional && !props.label) {
return new Error("Must include a value for the label prop to use the isOptional prop");
}
if (props.isOptional && props.isRequired) {
return new Error("Textarea cannot be both optional and required, please pick one ");
}
return null;
},
/** Prevents textarea from being modified but doesn't appear disabled */
isReadOnly: PropTypes.bool,
/** Prevents textarea from being submitted without value */
isRequired: PropTypes.bool,
/** Text that describes the textarea */
label: PropTypes.string,
/**
* Max length of the input value
*/
maxLength: PropTypes.number,
/** Form note for the input */
note: PropTypes.string,
/** Number of rows to fit in the textarea */
numRows: PropTypes.number,
/**
Function that fires when the textarea loses focus. It fires regardless of
whether the value has changed.
*/
onBlur: PropTypes.func,
/**
Function that fires when the textarea loses focus after the value
changes
*/
onChange: PropTypes.func,
/** Function that fires when the textarea gains focus */
onFocus: PropTypes.func,
/** Function that fires the the textarea value changes */
onInput: PropTypes.func,
/** Function that fires when a key is pressed down */
onKeyDown: PropTypes.func,
/** Textarea placeholder text */
placeholder: PropTypes.string,
/** Hook for automated JavaScript tests */
testSection: PropTypes.string,
/** Text within the textarea */
value: PropTypes.string,
};
Textarea.defaultProps = {
displayError: false,
focus: false,
label: null,
note: null,
numRows: 3,
isOptional: false,
};
export default Textarea;