2017-08-31 16:00:45 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Input
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-09-26 16:36:28 +02:00
|
|
|
import React from 'react';
|
2017-09-12 17:57:15 +02:00
|
|
|
import moment from 'moment';
|
2017-09-19 13:51:40 +02:00
|
|
|
import PropTypes from 'prop-types';
|
2017-09-12 17:57:15 +02:00
|
|
|
import { get, isEmpty, map, mapKeys, isObject, reject, includes } from 'lodash';
|
2017-08-31 16:00:45 +02:00
|
|
|
import { FormattedMessage } from 'react-intl';
|
2017-09-12 17:57:15 +02:00
|
|
|
import DateTime from 'react-datetime';
|
|
|
|
import DateTimeStyle from 'react-datetime/css/react-datetime.css';
|
2017-08-31 16:00:45 +02:00
|
|
|
import styles from './styles.scss';
|
|
|
|
|
|
|
|
class Input extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
errors: [],
|
|
|
|
hasInitialValue: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
2017-09-12 17:57:15 +02:00
|
|
|
if (this.props.value && !isEmpty(this.props.value)) {
|
|
|
|
this.setState({ hasInitialValue: true });
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isEmpty(this.props.errors)) {
|
|
|
|
this.setState({ errors: this.props.errors });
|
|
|
|
}
|
2017-08-31 16:00:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
2017-09-12 17:57:15 +02:00
|
|
|
// Check if errors have been updated during validations
|
|
|
|
if (this.props.didCheckErrors !== nextProps.didCheckErrors) {
|
|
|
|
|
|
|
|
// Remove from the state errors that are already set
|
|
|
|
const errors = isEmpty(nextProps.errors) ? [] : nextProps.errors;
|
|
|
|
this.setState({ errors });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleBlur = ({ target }) => {
|
|
|
|
// prevent error display if input is initially empty
|
|
|
|
if (!isEmpty(target.value) || this.state.hasInitialValue) {
|
|
|
|
// validates basic string validations
|
|
|
|
// add custom logic here such as alerts...
|
|
|
|
const errors = this.validate(target.value);
|
|
|
|
|
|
|
|
this.setState({ errors, hasInitialValue: true });
|
|
|
|
}
|
2017-08-31 16:00:45 +02:00
|
|
|
}
|
|
|
|
|
2017-09-12 17:57:15 +02:00
|
|
|
validate = (value) => {
|
|
|
|
let errors = [];
|
|
|
|
// handle i18n
|
2017-09-19 13:51:40 +02:00
|
|
|
const requiredError = { id: `${this.props.pluginID}.error.validation.required` };
|
2017-09-12 17:57:15 +02:00
|
|
|
mapKeys(this.props.validations, (validationValue, validationKey) => {
|
|
|
|
switch (validationKey) {
|
|
|
|
case 'max':
|
|
|
|
if (parseInt(value, 10) > validationValue) {
|
2017-09-19 13:51:40 +02:00
|
|
|
errors.push({ id: `${this.props.pluginID}.error.validation.max` });
|
2017-09-12 17:57:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'maxLength':
|
|
|
|
if (value.length > validationValue) {
|
2017-09-19 13:51:40 +02:00
|
|
|
errors.push({ id: `${this.props.pluginID}.error.validation.maxLength` });
|
2017-09-12 17:57:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'min':
|
|
|
|
if (parseInt(value, 10) < validationValue) {
|
2017-09-19 13:51:40 +02:00
|
|
|
errors.push({ id: `${this.props.pluginID}.error.validation.min` });
|
2017-09-12 17:57:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'minLength':
|
|
|
|
if (value.length < validationValue) {
|
2017-09-19 13:51:40 +02:00
|
|
|
errors.push({ id: `${this.props.pluginID}.error.validation.minLength` });
|
2017-09-12 17:57:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'required':
|
|
|
|
if (value.length === 0) {
|
2017-09-19 13:51:40 +02:00
|
|
|
errors.push({ id: `${this.props.pluginID}.error.validation.required` });
|
2017-09-12 17:57:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'regex':
|
|
|
|
if (!new RegExp(validationValue).test(value)) {
|
2017-09-19 13:51:40 +02:00
|
|
|
errors.push({ id: `${this.props.pluginID}.error.validation.regex` });
|
2017-09-12 17:57:15 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errors = [];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (includes(errors, requiredError)) {
|
|
|
|
errors = reject(errors, (error) => error !== requiredError);
|
|
|
|
}
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-31 16:00:45 +02:00
|
|
|
handleChangeCheckbox = (e) => {
|
|
|
|
const target = {
|
|
|
|
type: e.target.type,
|
|
|
|
value: !this.props.value,
|
|
|
|
name: e.target.name,
|
|
|
|
};
|
|
|
|
|
2017-10-12 17:07:02 +02:00
|
|
|
this.props.onChange({ target });
|
2017-08-31 16:00:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
renderErrors = (errorStyles) => { // eslint-disable-line consistent-return
|
|
|
|
if (!this.props.noErrorsDescription) {
|
|
|
|
const divStyle = errorStyles || styles.errorContainer;
|
|
|
|
return (
|
|
|
|
map(this.state.errors, (error, key) => {
|
|
|
|
const displayError = isObject(error) && error.id
|
|
|
|
? <FormattedMessage {...error} />
|
|
|
|
: error;
|
|
|
|
return (
|
|
|
|
<div key={key} className={`form-control-feedback ${divStyle}`}>{displayError}</div>
|
|
|
|
);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
renderInputCheckbox = (requiredClass, inputDescription) => {
|
|
|
|
const title = !isEmpty(this.props.title) ? <div className={styles.inputTitle}><FormattedMessage id={this.props.title} /></div> : '';
|
|
|
|
const spacer = !inputDescription ? <div /> : <div style={{ marginBottom: '.5rem'}}></div>;
|
|
|
|
|
|
|
|
return (
|
2017-09-19 17:19:35 +02:00
|
|
|
<div className={`${styles.inputCheckbox} ${requiredClass} ${this.props.customBootstrapClass || 'col-md-3'}`}>
|
2017-08-31 16:00:45 +02:00
|
|
|
<div className="form-check">
|
|
|
|
{title}
|
2017-09-14 11:10:05 +02:00
|
|
|
<FormattedMessage id={this.props.label} defaultMessage={this.props.label}>
|
2017-08-31 16:00:45 +02:00
|
|
|
{(message) => (
|
2017-09-12 17:57:15 +02:00
|
|
|
<label className={`${styles.checkboxLabel} form-check-label`} htmlFor={this.props.label}>
|
|
|
|
<input className="form-check-input" type="checkbox" defaultChecked={this.props.value} onChange={this.handleChangeCheckbox} name={this.props.name} />
|
2017-08-31 16:00:45 +02:00
|
|
|
{message}
|
|
|
|
</label>
|
|
|
|
)}
|
|
|
|
</FormattedMessage>
|
|
|
|
<div className={styles.inputCheckboxDescriptionContainer}>
|
|
|
|
<small>{inputDescription}</small>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{spacer}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2017-10-12 19:11:14 +02:00
|
|
|
renderInputSelect = (requiredClass, inputDescription, bootStrapClassDanger, handleBlur) => {
|
|
|
|
let spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
|
|
|
|
|
|
|
|
if (!this.props.noErrorsDescription && !isEmpty(this.state.errors)) {
|
|
|
|
spacer = <div />;
|
|
|
|
}
|
|
|
|
|
2017-08-31 16:00:45 +02:00
|
|
|
return (
|
2017-10-12 19:11:14 +02:00
|
|
|
<div className={`${styles.input} ${requiredClass} ${this.props.customBootstrapClass || 'col-md-6'} ${bootStrapClassDanger}`}>
|
2017-09-12 17:57:15 +02:00
|
|
|
<label htmlFor={this.props.label}>
|
2017-10-12 19:11:14 +02:00
|
|
|
<FormattedMessage id={`${this.props.label}`} />
|
2017-08-31 16:00:45 +02:00
|
|
|
</label>
|
|
|
|
<select
|
|
|
|
className="form-control"
|
2017-09-12 17:57:15 +02:00
|
|
|
id={this.props.label}
|
|
|
|
name={this.props.name}
|
2017-10-12 17:07:02 +02:00
|
|
|
onChange={this.props.onChange}
|
2017-08-31 16:00:45 +02:00
|
|
|
value={this.props.value}
|
2017-09-12 17:57:15 +02:00
|
|
|
disabled={this.props.disabled}
|
2017-10-12 19:11:14 +02:00
|
|
|
onBlur={handleBlur}
|
|
|
|
tabIndex={this.props.tabIndex}
|
2017-08-31 16:00:45 +02:00
|
|
|
>
|
|
|
|
{map(this.props.selectOptions, (option, key) => (
|
2017-10-12 19:11:14 +02:00
|
|
|
option.name ?
|
|
|
|
<FormattedMessage id={option.name} defaultMessage={option.name} values={{ option: option.name }} key={key}>
|
|
|
|
{(message) => (
|
|
|
|
<option value={option.value}>
|
|
|
|
{message}
|
|
|
|
</option>
|
|
|
|
)}
|
|
|
|
</FormattedMessage> :
|
|
|
|
<option value={option.value} key={key}>{option.name}</option>
|
2017-08-31 16:00:45 +02:00
|
|
|
))}
|
|
|
|
</select>
|
|
|
|
<div className={styles.inputDescriptionContainer}>
|
|
|
|
<small>{inputDescription}</small>
|
|
|
|
</div>
|
2017-10-12 19:11:14 +02:00
|
|
|
{this.renderErrors()}
|
2017-08-31 16:00:45 +02:00
|
|
|
{spacer}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-09-19 17:19:35 +02:00
|
|
|
renderInputTextArea = (requiredClass, bootStrapClassDanger, inputDescription, handleBlur) => {
|
2017-08-31 16:00:45 +02:00
|
|
|
let spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
|
|
|
|
|
|
|
|
if (!this.props.noErrorsDescription && !isEmpty(this.state.errors)) {
|
|
|
|
spacer = <div />;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2017-09-19 17:19:35 +02:00
|
|
|
<div className={`${styles.inputTextArea} ${this.props.customBootstrapClass || 'col-md-6'} ${requiredClass} ${bootStrapClassDanger}`}>
|
2017-09-12 17:57:15 +02:00
|
|
|
<label htmlFor={this.props.label}>
|
2017-09-14 11:10:05 +02:00
|
|
|
<FormattedMessage id={`${this.props.label}`} defaultMessage={this.props.label} />
|
2017-08-31 16:00:45 +02:00
|
|
|
</label>
|
2017-09-14 11:10:05 +02:00
|
|
|
<FormattedMessage id={this.props.placeholder || this.props.label} defaultMessage={this.props.label}>
|
2017-08-31 16:00:45 +02:00
|
|
|
{(placeholder) => (
|
|
|
|
<textarea
|
|
|
|
className="form-control"
|
2017-10-12 17:07:02 +02:00
|
|
|
onChange={this.props.onChange}
|
2017-08-31 16:00:45 +02:00
|
|
|
value={this.props.value}
|
2017-09-12 17:57:15 +02:00
|
|
|
name={this.props.name}
|
|
|
|
id={this.props.label}
|
|
|
|
onBlur={handleBlur}
|
2017-10-12 17:07:02 +02:00
|
|
|
onFocus={this.props.onFocus}
|
2017-08-31 16:00:45 +02:00
|
|
|
placeholder={placeholder}
|
2017-09-12 17:57:15 +02:00
|
|
|
disabled={this.props.disabled}
|
2017-08-31 16:00:45 +02:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</FormattedMessage>
|
|
|
|
<div className={styles.inputTextAreaDescriptionContainer}>
|
|
|
|
<small>{inputDescription}</small>
|
|
|
|
</div>
|
|
|
|
{this.renderErrors(styles.errorContainerTextArea)}
|
|
|
|
{spacer}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2017-09-19 17:19:35 +02:00
|
|
|
renderInputDate = (requiredClass, inputDescription) => {
|
2017-09-12 17:57:15 +02:00
|
|
|
let spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
|
|
|
|
|
|
|
|
if (!this.props.noErrorsDescription && !isEmpty(this.state.errors)) {
|
|
|
|
spacer = <div />;
|
|
|
|
}
|
|
|
|
|
|
|
|
const value = isObject(this.props.value) && this.props.value._isAMomentObject === true ?
|
|
|
|
this.props.value :
|
|
|
|
moment(this.props.value);
|
|
|
|
|
|
|
|
return (
|
2017-09-19 19:04:39 +02:00
|
|
|
<div className={`${styles.inputDate} ${styles.input} ${this.props.customBootstrapClass || 'col-md-4'} ${requiredClass}`}>
|
2017-09-12 17:57:15 +02:00
|
|
|
<label htmlFor={this.props.label}>
|
2017-09-14 11:10:05 +02:00
|
|
|
<FormattedMessage id={`${this.props.label}`} defaultMessage={this.props.label} />
|
2017-09-12 17:57:15 +02:00
|
|
|
</label>
|
|
|
|
<DateTime
|
|
|
|
value={value}
|
|
|
|
dateFormat='YYYY-MM-DD'
|
|
|
|
timeFormat='HH:mm:ss'
|
|
|
|
utc={true}
|
|
|
|
inputProps={{
|
|
|
|
placeholder: this.props.placeholder,
|
2017-09-19 19:04:39 +02:00
|
|
|
className: 'form-control',
|
2017-09-12 17:57:15 +02:00
|
|
|
name: this.props.name,
|
|
|
|
id: this.props.label,
|
|
|
|
}}
|
2017-10-12 17:07:02 +02:00
|
|
|
onChange={(moment) => this.props.onChange({ target: {
|
2017-09-12 17:57:15 +02:00
|
|
|
name: this.props.name,
|
|
|
|
value: moment
|
|
|
|
}})}
|
|
|
|
/>
|
|
|
|
<div className={styles.inputDescriptionContainer}>
|
|
|
|
<small>{inputDescription}</small>
|
|
|
|
</div>
|
|
|
|
{this.renderErrors(styles.errorContainerTextArea)}
|
|
|
|
{spacer}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2017-08-31 16:00:45 +02:00
|
|
|
renderFormattedInput = (handleBlur, inputValue, placeholder) => (
|
2017-09-14 11:10:05 +02:00
|
|
|
<FormattedMessage id={`${placeholder}`} defaultMessage={placeholder}>
|
2017-08-31 16:00:45 +02:00
|
|
|
{(message) => (
|
|
|
|
<input
|
2017-09-12 17:57:15 +02:00
|
|
|
name={this.props.name}
|
|
|
|
id={this.props.label}
|
2017-08-31 16:00:45 +02:00
|
|
|
onBlur={handleBlur}
|
2017-10-12 17:07:02 +02:00
|
|
|
onFocus={this.props.onFocus}
|
|
|
|
onChange={this.props.onChange}
|
2017-08-31 16:00:45 +02:00
|
|
|
value={inputValue}
|
|
|
|
type={this.props.type}
|
|
|
|
className={`form-control ${this.state.errors? 'form-control-danger' : ''}`}
|
|
|
|
placeholder={message}
|
|
|
|
autoComplete="off"
|
2017-09-12 17:57:15 +02:00
|
|
|
disabled={this.props.disabled}
|
2017-08-31 16:00:45 +02:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</FormattedMessage>
|
|
|
|
)
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const inputValue = this.props.value || '';
|
|
|
|
// override default onBlur
|
2017-10-12 17:07:02 +02:00
|
|
|
const handleBlur = this.props.onBlur || this.handleBlur;
|
2017-08-31 16:00:45 +02:00
|
|
|
// override bootStrapClass
|
|
|
|
// set error class with override possibility
|
|
|
|
const bootStrapClassDanger = !this.props.deactivateErrorHighlight && !isEmpty(this.state.errors) ? 'has-danger' : '';
|
2017-09-12 17:57:15 +02:00
|
|
|
const placeholder = this.props.placeholder || this.props.label;
|
2017-08-31 16:00:45 +02:00
|
|
|
|
2017-09-12 17:57:15 +02:00
|
|
|
const label = this.props.label ?
|
2017-09-14 11:10:05 +02:00
|
|
|
<label htmlFor={this.props.label}><FormattedMessage id={`${this.props.label}`} defaultMessage={this.props.label} /></label>
|
2017-09-12 17:57:15 +02:00
|
|
|
: <label htmlFor={this.props.label} />;
|
2017-08-31 16:00:45 +02:00
|
|
|
|
|
|
|
const requiredClass = get(this.props.validations, 'required') && this.props.addRequiredInputDesign ?
|
|
|
|
styles.requiredClass : '';
|
|
|
|
|
|
|
|
|
|
|
|
const input = placeholder ? this.renderFormattedInput(handleBlur, inputValue, placeholder)
|
|
|
|
: <input
|
2017-09-12 17:57:15 +02:00
|
|
|
name={this.props.name}
|
|
|
|
id={this.props.label}
|
2017-08-31 16:00:45 +02:00
|
|
|
onBlur={handleBlur}
|
2017-10-12 17:07:02 +02:00
|
|
|
onFocus={this.props.onFocus}
|
|
|
|
onChange={this.props.onChange}
|
2017-08-31 16:00:45 +02:00
|
|
|
value={inputValue}
|
|
|
|
type={this.props.type}
|
|
|
|
className={`form-control ${this.state.errors? 'form-control-danger' : ''}`}
|
|
|
|
placeholder={placeholder}
|
2017-09-12 17:57:15 +02:00
|
|
|
disabled={this.props.disabled}
|
2017-08-31 16:00:45 +02:00
|
|
|
/>;
|
|
|
|
|
2017-10-12 19:11:14 +02:00
|
|
|
const link = !isEmpty(this.props.linkContent) ? <a href={this.props.linkContent.link} target="_blank"><FormattedMessage id={this.props.linkContent.description} /></a> : '';
|
|
|
|
|
|
|
|
let inputDescription = !isEmpty(this.props.inputDescription) ? <FormattedMessage id={this.props.inputDescription} /> : '';
|
|
|
|
|
|
|
|
if (!isEmpty(this.props.linkContent) && !isEmpty(this.props.inputDescription)) {
|
|
|
|
inputDescription = <FormattedMessage id='input.description' defaultMessage={`{description}, {link}`} values={{link, description: <FormattedMessage id={this.props.inputDescription} /> }} />;
|
|
|
|
}
|
2017-08-31 16:00:45 +02:00
|
|
|
|
|
|
|
let spacer = !isEmpty(this.props.inputDescription) ? <div className={styles.spacer} /> : <div />;
|
|
|
|
|
|
|
|
if (!this.props.noErrorsDescription && !isEmpty(this.state.errors)) {
|
|
|
|
spacer = <div />;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (this.props.type) {
|
|
|
|
case 'select':
|
2017-10-12 19:11:14 +02:00
|
|
|
return this.renderInputSelect(requiredClass, inputDescription, bootStrapClassDanger, handleBlur);
|
2017-08-31 16:00:45 +02:00
|
|
|
case 'textarea':
|
2017-09-19 17:19:35 +02:00
|
|
|
return this.renderInputTextArea(requiredClass, bootStrapClassDanger, inputDescription, handleBlur);
|
2017-08-31 16:00:45 +02:00
|
|
|
case 'checkbox':
|
|
|
|
return this.renderInputCheckbox(requiredClass, inputDescription);
|
2017-09-12 17:57:15 +02:00
|
|
|
case 'date':
|
2017-09-19 17:19:35 +02:00
|
|
|
return this.renderInputDate(requiredClass, inputDescription);
|
2017-08-31 16:00:45 +02:00
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
2017-09-12 17:57:15 +02:00
|
|
|
const addonInput = this.props.addon ?
|
|
|
|
<div className={`input-group ${styles.input}`} style={{ marginBottom: '1rem'}}>
|
|
|
|
<span className={`input-group-addon ${styles.addon}`}><FormattedMessage id={this.props.addon} /></span>
|
|
|
|
{input}
|
|
|
|
</div> : input;
|
2017-08-31 16:00:45 +02:00
|
|
|
return (
|
2017-09-19 17:19:35 +02:00
|
|
|
<div className={`${styles.input} ${this.props.customBootstrapClass || 'col-md-6'} ${requiredClass} ${bootStrapClassDanger}`}>
|
2017-08-31 16:00:45 +02:00
|
|
|
{label}
|
2017-09-12 17:57:15 +02:00
|
|
|
|
|
|
|
{addonInput}
|
2017-08-31 16:00:45 +02:00
|
|
|
<div className={styles.inputDescriptionContainer}>
|
|
|
|
<small>{inputDescription}</small>
|
|
|
|
</div>
|
|
|
|
{this.renderErrors()}
|
|
|
|
{spacer}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Input.propTypes = {
|
2017-09-19 13:51:40 +02:00
|
|
|
addon: PropTypes.oneOfType([
|
|
|
|
PropTypes.bool,
|
|
|
|
PropTypes.string,
|
2017-09-12 17:57:15 +02:00
|
|
|
]),
|
2017-09-19 13:51:40 +02:00
|
|
|
addRequiredInputDesign: PropTypes.bool,
|
|
|
|
customBootstrapClass: PropTypes.string,
|
|
|
|
deactivateErrorHighlight: PropTypes.bool,
|
|
|
|
didCheckErrors: PropTypes.bool,
|
|
|
|
disabled: PropTypes.bool,
|
|
|
|
errors: PropTypes.array,
|
|
|
|
inputDescription: PropTypes.string,
|
|
|
|
label: PropTypes.string.isRequired,
|
|
|
|
name: PropTypes.string.isRequired,
|
|
|
|
noErrorsDescription: PropTypes.bool,
|
2017-10-12 17:07:02 +02:00
|
|
|
onBlur: PropTypes.oneOfType([
|
|
|
|
PropTypes.func,
|
|
|
|
PropTypes.bool,
|
|
|
|
]),
|
|
|
|
onChange: PropTypes.func.isRequired,
|
|
|
|
onFocus: PropTypes.func,
|
2017-09-19 13:51:40 +02:00
|
|
|
placeholder: PropTypes.string,
|
|
|
|
pluginID: PropTypes.string,
|
|
|
|
selectOptions: PropTypes.array,
|
|
|
|
selectOptionsFetchSucceeded: PropTypes.bool,
|
|
|
|
title: PropTypes.string,
|
|
|
|
type: PropTypes.string.isRequired,
|
|
|
|
validations: PropTypes.object.isRequired,
|
|
|
|
value: PropTypes.oneOfType([
|
|
|
|
PropTypes.string,
|
|
|
|
PropTypes.bool,
|
|
|
|
PropTypes.number,
|
2017-08-31 16:00:45 +02:00
|
|
|
]),
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Input;
|