mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	Merge pull request #585 from strapi/add/input-checkbox
Created InputCheckbox and InputChecboxWithErrors components
This commit is contained in:
		
						commit
						dbfc51d659
					
				@ -0,0 +1,133 @@
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * InputCheckbox
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
import { isEmpty, isFunction, isObject } from 'lodash';
 | 
			
		||||
import cn from 'classnames';
 | 
			
		||||
 | 
			
		||||
import styles from './styles.scss';
 | 
			
		||||
 | 
			
		||||
class InputCheckbox extends React.Component {
 | 
			
		||||
  handleChange = () => {
 | 
			
		||||
    const target = {
 | 
			
		||||
      name: this.props.name,
 | 
			
		||||
      type: 'checkbox',
 | 
			
		||||
      value: !this.props.value,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this.props.onChange({ target });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
    const {
 | 
			
		||||
      autoFocus,
 | 
			
		||||
      className,
 | 
			
		||||
      disabled,
 | 
			
		||||
      label,
 | 
			
		||||
      name,
 | 
			
		||||
      onBlur,
 | 
			
		||||
      onFocus,
 | 
			
		||||
      style,
 | 
			
		||||
      tabIndex,
 | 
			
		||||
      value,
 | 
			
		||||
    } = this.props;
 | 
			
		||||
    const checkbox = (
 | 
			
		||||
      <input
 | 
			
		||||
        autoFocus={autoFocus}
 | 
			
		||||
        className="form-check-input"
 | 
			
		||||
        checked={value}
 | 
			
		||||
        disabled={disabled}
 | 
			
		||||
        id={name}
 | 
			
		||||
        onBlur={onBlur}
 | 
			
		||||
        onChange={this.handleChange}
 | 
			
		||||
        onFocus={onFocus}
 | 
			
		||||
        tabIndex={tabIndex}
 | 
			
		||||
        type="checkbox"
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let content = <div />;
 | 
			
		||||
 | 
			
		||||
    if (typeof(label) === 'string') {
 | 
			
		||||
      content = (
 | 
			
		||||
        <label className={cn('form-check-label', disabled && styles.disabled)} htmlFor={name}>
 | 
			
		||||
          {checkbox}
 | 
			
		||||
          {label}
 | 
			
		||||
        </label>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isFunction(label)) {
 | 
			
		||||
      content = (
 | 
			
		||||
        <label className={cn('form-check-label', disabled && styles.disabled)} htmlFor={name}>
 | 
			
		||||
          {checkbox}
 | 
			
		||||
          {label()}
 | 
			
		||||
        </label>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isObject(label) && label.id) {
 | 
			
		||||
      content = (
 | 
			
		||||
        <FormattedMessage id={label.id} defaultMessage={label.id} values={label.params}>
 | 
			
		||||
          {(message) => (
 | 
			
		||||
            <label className={cn('form-check-label', disabled && styles.disabled)} htmlFor={name}>
 | 
			
		||||
              {checkbox}
 | 
			
		||||
              {message}
 | 
			
		||||
            </label>
 | 
			
		||||
          )}
 | 
			
		||||
        </FormattedMessage>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
      <div className={cn(
 | 
			
		||||
          'form-check',
 | 
			
		||||
          styles.inputCheckbox,
 | 
			
		||||
          !isEmpty(className) && className,
 | 
			
		||||
        )}
 | 
			
		||||
        style={style}
 | 
			
		||||
      >
 | 
			
		||||
        {content}
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
InputCheckbox.defaultProps = {
 | 
			
		||||
  autoFocus: false,
 | 
			
		||||
  className: '',
 | 
			
		||||
  disabled: false,
 | 
			
		||||
  label: '',
 | 
			
		||||
  onBlur: () => {},
 | 
			
		||||
  onFocus: () => {},
 | 
			
		||||
  style: {},
 | 
			
		||||
  tabIndex: '0',
 | 
			
		||||
  value: false,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
InputCheckbox.propTypes = {
 | 
			
		||||
  autoFocus: PropTypes.bool,
 | 
			
		||||
  className: PropTypes.string,
 | 
			
		||||
  disabled: PropTypes.bool,
 | 
			
		||||
  label: PropTypes.oneOfType([
 | 
			
		||||
    PropTypes.string,
 | 
			
		||||
    PropTypes.func,
 | 
			
		||||
    PropTypes.shape({
 | 
			
		||||
      id: PropTypes.string,
 | 
			
		||||
      params: PropTypes.object,
 | 
			
		||||
    }),
 | 
			
		||||
  ]),
 | 
			
		||||
  name: PropTypes.string.isRequired,
 | 
			
		||||
  onBlur: PropTypes.func,
 | 
			
		||||
  onChange: PropTypes.func.isRequired,
 | 
			
		||||
  onFocus: PropTypes.func,
 | 
			
		||||
  style: PropTypes.object,
 | 
			
		||||
  tabIndex: PropTypes.string,
 | 
			
		||||
  value: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default InputCheckbox;
 | 
			
		||||
@ -0,0 +1,15 @@
 | 
			
		||||
.inputCheckbox {
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  label {
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
  }
 | 
			
		||||
  input {
 | 
			
		||||
    margin-right: 1.2rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.disabled {
 | 
			
		||||
  cursor: not-allowed;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,213 @@
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * InputCheckboxWithErrors
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
import { includes, isEmpty, isObject, isFunction, mapKeys, reject } from 'lodash';
 | 
			
		||||
import cn from 'classnames';
 | 
			
		||||
 | 
			
		||||
// Design
 | 
			
		||||
import Label from 'components/Label';
 | 
			
		||||
import InputDescription from 'components/InputDescription';
 | 
			
		||||
import InputErrors from 'components/InputErrors';
 | 
			
		||||
import InputCheckbox from 'components/InputCheckbox';
 | 
			
		||||
 | 
			
		||||
import styles from './styles.scss';
 | 
			
		||||
 | 
			
		||||
class InputCheckboxWithErrors extends React.Component {
 | 
			
		||||
  state = { errors: [] };
 | 
			
		||||
 | 
			
		||||
  componentDidMount() {
 | 
			
		||||
    // Display input error if it already has some
 | 
			
		||||
    const { errors } = this.props;
 | 
			
		||||
    if (!isEmpty(errors)) {
 | 
			
		||||
      this.setState({ errors });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillReceiveProps(nextProps) {
 | 
			
		||||
    // Check if errors have been updated during validations
 | 
			
		||||
    if (nextProps.didCheckErrors !== this.props.didCheckErrors) {
 | 
			
		||||
      // Remove from the state the errors that have already been set
 | 
			
		||||
      const errors = isEmpty(nextProps.errors) ? [] : nextProps.errors;
 | 
			
		||||
      this.setState({ errors });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const {
 | 
			
		||||
      autoFocus,
 | 
			
		||||
      className,
 | 
			
		||||
      customBootstrapClass,
 | 
			
		||||
      deactivateErrorHighlight,
 | 
			
		||||
      disabled,
 | 
			
		||||
      errorsClassName,
 | 
			
		||||
      errorsStyle,
 | 
			
		||||
      inputClassName,
 | 
			
		||||
      inputDescription,
 | 
			
		||||
      inputDescriptionClassName,
 | 
			
		||||
      inputDescriptionStyle,
 | 
			
		||||
      inputStyle,
 | 
			
		||||
      label,
 | 
			
		||||
      labelClassName,
 | 
			
		||||
      labelStyle,
 | 
			
		||||
      name,
 | 
			
		||||
      noErrorsDescription,
 | 
			
		||||
      onBlur,
 | 
			
		||||
      onChange,
 | 
			
		||||
      onFocus,
 | 
			
		||||
      placeholder,
 | 
			
		||||
      style,
 | 
			
		||||
      tabIndex,
 | 
			
		||||
      title,
 | 
			
		||||
      value,
 | 
			
		||||
    } = this.props;
 | 
			
		||||
 | 
			
		||||
    const handleBlur = onBlur ? onBlur : () => {};
 | 
			
		||||
    let inputTitle = '';
 | 
			
		||||
 | 
			
		||||
    let spacer = !isEmpty(inputDescription) ? <div className={styles.spacer} /> : <div />;
 | 
			
		||||
 | 
			
		||||
    if (!noErrorsDescription && !isEmpty(this.state.errors)) {
 | 
			
		||||
      spacer = <div />;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isObject(title) && title.id) {
 | 
			
		||||
      inputTitle = (
 | 
			
		||||
        <div className={styles.inputTitle}>
 | 
			
		||||
          <FormattedMessage id={title.id} defaultMessage={title.id} values={title.params} />
 | 
			
		||||
        </div>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isFunction(title)) {
 | 
			
		||||
      inputTitle = title();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className={cn(
 | 
			
		||||
          styles.container,
 | 
			
		||||
          customBootstrapClass,
 | 
			
		||||
          !isEmpty(className) && className,
 | 
			
		||||
        )}
 | 
			
		||||
        style={style}
 | 
			
		||||
      >
 | 
			
		||||
        {inputTitle}
 | 
			
		||||
        <InputCheckbox
 | 
			
		||||
          autoFocus={autoFocus}
 | 
			
		||||
          className={inputClassName}
 | 
			
		||||
          disabled={disabled}
 | 
			
		||||
          label={label}
 | 
			
		||||
          name={name}
 | 
			
		||||
          onBlur={handleBlur}
 | 
			
		||||
          onChange={onChange}
 | 
			
		||||
          onFocus={onFocus}
 | 
			
		||||
          placeholder={placeholder}
 | 
			
		||||
          style={inputStyle}
 | 
			
		||||
          tabIndex={tabIndex}
 | 
			
		||||
          value={value}
 | 
			
		||||
        />
 | 
			
		||||
        <InputDescription
 | 
			
		||||
          className={cn(styles.inputCheckboxDescriptionContainer, inputDescriptionClassName)}
 | 
			
		||||
          message={this.props.inputDescription}
 | 
			
		||||
          style={inputDescriptionStyle}
 | 
			
		||||
        />
 | 
			
		||||
        <InputErrors
 | 
			
		||||
          className={errorsClassName}
 | 
			
		||||
          errors={this.state.errors}
 | 
			
		||||
          style={errorsStyle}
 | 
			
		||||
        />
 | 
			
		||||
      {spacer}
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
InputCheckboxWithErrors.defaultProps = {
 | 
			
		||||
  autoFocus: false,
 | 
			
		||||
  className: '',
 | 
			
		||||
  customBootstrapClass: 'col-md-3',
 | 
			
		||||
  deactivateErrorHighlight: false,
 | 
			
		||||
  didCheckErrors: false,
 | 
			
		||||
  disabled: false,
 | 
			
		||||
  onBlur: () => {},
 | 
			
		||||
  onFocus: () => {},
 | 
			
		||||
  errors: [],
 | 
			
		||||
  errorsClassName: '',
 | 
			
		||||
  errorsStyle: {},
 | 
			
		||||
  inputClassName: '',
 | 
			
		||||
  inputDescription: '',
 | 
			
		||||
  inputDescriptionClassName: '',
 | 
			
		||||
  inputDescriptionStyle: {},
 | 
			
		||||
  inputStyle: {},
 | 
			
		||||
  label: '',
 | 
			
		||||
  labelClassName: '',
 | 
			
		||||
  labelStyle: {},
 | 
			
		||||
  noErrorsDescription: false,
 | 
			
		||||
  placeholder: 'app.utils.placeholder.defaultMessage',
 | 
			
		||||
  style: {},
 | 
			
		||||
  tabIndex: '0',
 | 
			
		||||
  title: '',
 | 
			
		||||
  validations: {},
 | 
			
		||||
  value: false,
 | 
			
		||||
};
 | 
			
		||||
InputCheckboxWithErrors.propTypes = {
 | 
			
		||||
  autoFocus: PropTypes.bool,
 | 
			
		||||
  className: PropTypes.string,
 | 
			
		||||
  customBootstrapClass: PropTypes.string,
 | 
			
		||||
  deactivateErrorHighlight: PropTypes.bool,
 | 
			
		||||
  didCheckErrors: PropTypes.bool,
 | 
			
		||||
  disabled: PropTypes.bool,
 | 
			
		||||
  errors: PropTypes.array,
 | 
			
		||||
  errorsClassName: PropTypes.string,
 | 
			
		||||
  errorsStyle: PropTypes.object,
 | 
			
		||||
  inputClassName: PropTypes.string,
 | 
			
		||||
  inputDescription: PropTypes.oneOfType([
 | 
			
		||||
    PropTypes.string,
 | 
			
		||||
    PropTypes.func,
 | 
			
		||||
    PropTypes.shape({
 | 
			
		||||
      id: PropTypes.string,
 | 
			
		||||
      params: PropTypes.object,
 | 
			
		||||
    }),
 | 
			
		||||
  ]),
 | 
			
		||||
  inputDescriptionClassName: PropTypes.string,
 | 
			
		||||
  inputDescriptionStyle: PropTypes.object,
 | 
			
		||||
  inputStyle: PropTypes.object,
 | 
			
		||||
  label: PropTypes.oneOfType([
 | 
			
		||||
    PropTypes.string,
 | 
			
		||||
    PropTypes.func,
 | 
			
		||||
    PropTypes.shape({
 | 
			
		||||
      id: PropTypes.string,
 | 
			
		||||
      params: PropTypes.object,
 | 
			
		||||
    }),
 | 
			
		||||
  ]),
 | 
			
		||||
  labelClassName: PropTypes.string,
 | 
			
		||||
  labelStyle: PropTypes.object,
 | 
			
		||||
  name: PropTypes.string.isRequired,
 | 
			
		||||
  noErrorsDescription: PropTypes.bool,
 | 
			
		||||
  onBlur: PropTypes.oneOfType([
 | 
			
		||||
    PropTypes.bool,
 | 
			
		||||
    PropTypes.func,
 | 
			
		||||
  ]),
 | 
			
		||||
  onChange: PropTypes.func.isRequired,
 | 
			
		||||
  onFocus: PropTypes.func,
 | 
			
		||||
  placeholder: PropTypes.string,
 | 
			
		||||
  style: PropTypes.object,
 | 
			
		||||
  tabIndex: PropTypes.string,
 | 
			
		||||
  title: PropTypes.oneOfType([
 | 
			
		||||
    PropTypes.string,
 | 
			
		||||
    PropTypes.func,
 | 
			
		||||
    PropTypes.shape({
 | 
			
		||||
      id: PropTypes.string,
 | 
			
		||||
      params: PropTypes.object,
 | 
			
		||||
    }),
 | 
			
		||||
  ]),
 | 
			
		||||
  validations: PropTypes.object,
 | 
			
		||||
  value: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default InputCheckboxWithErrors;
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
.container {
 | 
			
		||||
  margin-bottom: 1.5rem;
 | 
			
		||||
  font-size: 1.3rem;
 | 
			
		||||
  font-family: 'Lato';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.spacer {
 | 
			
		||||
  height: .5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.inputCheckboxDescriptionContainer {
 | 
			
		||||
  width: 150%;
 | 
			
		||||
  margin-top: .2rem;
 | 
			
		||||
  padding-left: 2.5rem;
 | 
			
		||||
  line-height: 1.2rem;
 | 
			
		||||
 | 
			
		||||
  > small {
 | 
			
		||||
    color: #9EA7B8;
 | 
			
		||||
    font-family: 'Lato';
 | 
			
		||||
    font-size: 1.2rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.inputTitle {
 | 
			
		||||
  margin-bottom: 1.7rem;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
}
 | 
			
		||||
@ -7,6 +7,7 @@ import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
 | 
			
		||||
// Design
 | 
			
		||||
import InputCheckboxWithErrors from 'components/InputCheckboxWithErrors';
 | 
			
		||||
import InputEmailWithErrors from 'components/InputEmailWithErrors';
 | 
			
		||||
import InputNumberWithErrors from 'components/InputNumberWithErrors';
 | 
			
		||||
import InputSearchWithErrors from 'components/InputSearchWithErrors';
 | 
			
		||||
@ -19,6 +20,7 @@ import InputToggleWithErrors from 'components/InputToggleWithErrors';
 | 
			
		||||
const DefaultInputError = ({ type }) => <div>Your input type: <b>{type}</b> does not exist</div>
 | 
			
		||||
 | 
			
		||||
const inputs = {
 | 
			
		||||
  checkbox: InputCheckboxWithErrors,
 | 
			
		||||
  email: InputEmailWithErrors,
 | 
			
		||||
  number: InputNumberWithErrors,
 | 
			
		||||
  password: InputPasswordWithErrors,
 | 
			
		||||
@ -42,6 +44,7 @@ InputsIndex.propTypes = {
 | 
			
		||||
 | 
			
		||||
export default InputsIndex;
 | 
			
		||||
export {
 | 
			
		||||
  InputCheckboxWithErrors,
 | 
			
		||||
  InputEmailWithErrors,
 | 
			
		||||
  InputNumberWithErrors,
 | 
			
		||||
  InputPasswordWithErrors,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user