mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
151 lines
4.2 KiB
JavaScript
151 lines
4.2 KiB
JavaScript
import React, { Component } from 'react';
|
|
import { bool, func, object, shape, string } from 'prop-types';
|
|
import { Field } from 'react-final-form';
|
|
import classNames from 'classnames';
|
|
import { ValidationError, ExpandingTextarea } from '../../components';
|
|
|
|
import css from './FieldTextInput.css';
|
|
|
|
const CONTENT_MAX_LENGTH = 5000;
|
|
|
|
class FieldTextInputComponent extends Component {
|
|
render() {
|
|
/* eslint-disable no-unused-vars */
|
|
const {
|
|
rootClassName,
|
|
className,
|
|
inputRootClass,
|
|
customErrorText,
|
|
id,
|
|
label,
|
|
input,
|
|
meta,
|
|
onUnmount,
|
|
isUncontrolled,
|
|
inputRef,
|
|
...rest
|
|
} = this.props;
|
|
/* eslint-enable no-unused-vars */
|
|
|
|
if (label && !id) {
|
|
throw new Error('id required when a label is given');
|
|
}
|
|
|
|
const { valid, invalid, touched, error } = meta;
|
|
const isTextarea = input.type === 'textarea';
|
|
|
|
const errorText = customErrorText || error;
|
|
|
|
// Error message and input error styles are only shown if the
|
|
// field has been touched and the validation has failed.
|
|
const hasError = !!customErrorText || !!(touched && invalid && error);
|
|
|
|
const fieldMeta = { touched: hasError, error: errorText };
|
|
|
|
// Textarea doesn't need type.
|
|
const { type, ...inputWithoutType } = input;
|
|
// Uncontrolled input uses defaultValue instead of value.
|
|
const { value: defaultValue, ...inputWithoutValue } = input;
|
|
// Use inputRef if it is passed as prop.
|
|
const refMaybe = inputRef ? { ref: inputRef } : {};
|
|
|
|
const inputClasses =
|
|
inputRootClass ||
|
|
classNames(css.input, {
|
|
[css.inputSuccess]: valid,
|
|
[css.inputError]: hasError,
|
|
[css.textarea]: isTextarea,
|
|
});
|
|
const maxLength = CONTENT_MAX_LENGTH;
|
|
const inputProps = isTextarea
|
|
? {
|
|
className: inputClasses,
|
|
id,
|
|
rows: 1,
|
|
maxLength,
|
|
...refMaybe,
|
|
...inputWithoutType,
|
|
...rest,
|
|
}
|
|
: isUncontrolled
|
|
? {
|
|
className: inputClasses,
|
|
id,
|
|
type,
|
|
defaultValue,
|
|
...refMaybe,
|
|
...inputWithoutValue,
|
|
...rest,
|
|
}
|
|
: { className: inputClasses, id, type, ...refMaybe, ...input, ...rest };
|
|
|
|
const classes = classNames(rootClassName || css.root, className);
|
|
return (
|
|
<div className={classes}>
|
|
{label ? <label htmlFor={id}>{label}</label> : null}
|
|
{isTextarea ? <ExpandingTextarea {...inputProps} /> : <input {...inputProps} />}
|
|
<ValidationError fieldMeta={fieldMeta} />
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
FieldTextInputComponent.defaultProps = {
|
|
rootClassName: null,
|
|
className: null,
|
|
inputRootClass: null,
|
|
onUnmount: null,
|
|
customErrorText: null,
|
|
id: null,
|
|
label: null,
|
|
isUncontrolled: false,
|
|
inputRef: null,
|
|
};
|
|
|
|
FieldTextInputComponent.propTypes = {
|
|
rootClassName: string,
|
|
className: string,
|
|
inputRootClass: string,
|
|
|
|
onUnmount: func,
|
|
|
|
// Error message that can be manually passed to input field,
|
|
// overrides default validation message
|
|
customErrorText: string,
|
|
|
|
// Label is optional, but if it is given, an id is also required so
|
|
// the label can reference the input in the `for` attribute
|
|
id: string,
|
|
label: string,
|
|
|
|
// Uncontrolled input uses defaultValue prop, but doesn't pass value from form to the field.
|
|
// https://reactjs.org/docs/uncontrolled-components.html#default-values
|
|
isUncontrolled: bool,
|
|
// a ref object passed for input element.
|
|
inputRef: object,
|
|
|
|
// Generated by final-form's Field component
|
|
input: shape({
|
|
onChange: func.isRequired,
|
|
// Either 'textarea' or something that is passed to the input element
|
|
type: string.isRequired,
|
|
}).isRequired,
|
|
meta: object.isRequired,
|
|
};
|
|
|
|
class FieldTextInput extends Component {
|
|
componentWillUnmount() {
|
|
// Unmounting happens too late if it is done inside Field component
|
|
// (Then Form has already registered its (new) fields and
|
|
// changing the value without corresponding field is prohibited in Final Form
|
|
if (this.props.onUnmount) {
|
|
this.props.onUnmount();
|
|
}
|
|
}
|
|
|
|
render() {
|
|
return <Field component={FieldTextInputComponent} {...this.props} />;
|
|
}
|
|
}
|
|
|
|
export default FieldTextInput;
|