function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }

import React from 'react';
import PropTypes from 'prop-types';
import { omit } from 'lodash';
import { Icon, InputError, InputHelper, Label } from "./..";
/**
 * @category controls
 * @component input
 * @variations collab-ui-react
 */

var determineErrorType = function determineErrorType(array) {
  return array.reduce(function (agg, e) {
    return agg === 'error' ? agg : e.type || '';
  }, '');
};

var filterErrorsByType = function filterErrorsByType(array, value) {
  return array.reduce(function (agg, e) {
    return e.type === value ? agg.concat(e.error) : agg;
  }, []);
};
/** Text input with integrated label to enforce consistency in layout, error display, label placement, and required field marker. */


var Input =
/*#__PURE__*/
function (_React$Component) {
  _inheritsLoose(Input, _React$Component);

  function Input() {
    var _this;

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
    _this.state = {
      isEditing: false,
      value: _this.props.value
    };

    _this.setValue = function (value) {
      _this.setState({
        value: value
      });
    };

    _this.handleKeyDown = function (e) {
      var onKeyDown = _this.props.onKeyDown;
      onKeyDown && onKeyDown(e);
    };

    _this.handleFocus = function (e) {
      var _this$props = _this.props,
          onFocus = _this$props.onFocus,
          disabled = _this$props.disabled;

      if (disabled) {
        e.stopPropagation();
        return;
      }

      if (onFocus) {
        onFocus(e);
      }

      _this.setState({
        isEditing: true
      });
    };

    _this.handleMouseDown = function (e) {
      var _this$props2 = _this.props,
          onMouseDown = _this$props2.onMouseDown,
          disabled = _this$props2.disabled;

      if (disabled) {
        e.stopPropagation();
        return;
      }

      if (onMouseDown) {
        onMouseDown(e);
      }

      _this.setState({
        isEditing: true
      });
    };

    _this.handleChange = function (e) {
      var onChange = _this.props.onChange;
      var value = e.target.value;
      e.persist();

      _this.setState(function () {
        onChange && onChange(e);
        return {
          value: value
        };
      });
    };

    _this.handleBlur = function (e) {
      var onDoneEditing = _this.props.onDoneEditing;
      var value = e.target.value;
      e.stopPropagation();
      e.preventDefault();

      if (e.keyCode === 27 || e.keyCode === 13 || e.type === 'blur') {
        _this.setState({
          isEditing: false
        });

        if (onDoneEditing) {
          onDoneEditing(value);
        }
      }
    };

    _this.handleClear = function (e) {
      var value = '';
      e.target.value = value;
      e.persist();

      _this.input.focus();

      _this.handleChange(e);
    };

    _this.setInputRef = function (input) {
      var _this$props3 = _this.props,
          clear = _this$props3.clear,
          inputRef = _this$props3.inputRef;
      if (clear) _this.input = input;
      if (inputRef) return inputRef(input);
    };

    return _this;
  }

  var _proto = Input.prototype;

  _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
    var value = this.props.value;
    value !== prevProps.value && this.setValue(value);
  };

  _proto.render = function render() {
    var _this$props4 = this.props,
        children = _this$props4.children,
        className = _this$props4.className,
        clear = _this$props4.clear,
        clearAriaLabel = _this$props4.clearAriaLabel,
        defaultValue = _this$props4.defaultValue,
        disabled = _this$props4.disabled,
        errorArr = _this$props4.errorArr,
        htmlId = _this$props4.htmlId,
        id = _this$props4.id,
        inputClassName = _this$props4.inputClassName,
        inputHelpText = _this$props4.inputHelpText,
        inputSize = _this$props4.inputSize,
        label = _this$props4.label,
        nestedLevel = _this$props4.nestedLevel,
        placeholder = _this$props4.placeholder,
        readOnly = _this$props4.readOnly,
        secondaryLabel = _this$props4.secondaryLabel,
        type = _this$props4.type,
        props = _objectWithoutProperties(_this$props4, ["children", "className", "clear", "clearAriaLabel", "defaultValue", "disabled", "errorArr", "htmlId", "id", "inputClassName", "inputHelpText", "inputSize", "label", "nestedLevel", "placeholder", "readOnly", "secondaryLabel", "type"]);

    var value = this.state.value;
    var otherProps = omit(_extends({}, props), ['inputRef', 'onChange', 'onDoneEditing', 'onFocus', 'onKeyDown', 'onMouseDown', 'ref', 'value']);
    var errorType = errorArr.length > 0 && determineErrorType(errorArr) || '';
    var errors = errorType && filterErrorsByType(errorArr, errorType) || [];

    var secondaryLabelWrapper = function secondaryLabelWrapper() {
      return React.createElement("div", {
        className: "cui-label__secondary-label-container"
      }, inputElement, React.createElement(Label, {
        className: "cui-label__secondary-label",
        label: secondaryLabel,
        htmlFor: htmlId
      }));
    };

    var clearButton = clear && !disabled && value && React.createElement(Icon, {
      name: "clear-active_16",
      onClick: this.handleClear,
      ariaLabel: clearAriaLabel || 'clear input'
    });

    var iconContainer = function iconContainer() {
      return React.createElement("div", {
        className: 'cui-input__icon-container' + (clear ? ' cui-input__icon--right' : '')
      }, inputElement, children, clearButton);
    };

    var inputElement = React.createElement("input", _extends({
      className: 'cui-input' + ("" + (inputClassName ? " " + inputClassName : '')) + ("" + (readOnly ? ' read-only' : '')) + ("" + (disabled ? ' disabled' : '')) + ("" + (value ? " dirty" : '')),
      type: type,
      onKeyDown: this.handleKeyDown,
      onBlur: this.handleBlur,
      onFocus: this.handleFocus,
      onMouseDown: this.handleMouseDown,
      placeholder: placeholder,
      value: value || defaultValue,
      onChange: this.handleChange,
      ref: this.setInputRef,
      disabled: disabled,
      readOnly: readOnly,
      tabIndex: 0
    }, htmlId && {
      id: htmlId
    }, otherProps));

    var getInputWrapper = function getInputWrapper() {
      if (clear || children) return iconContainer();
      if (secondaryLabel) return secondaryLabelWrapper();
      return inputElement;
    };

    return React.createElement("div", {
      className: "cui-input-group" + (" " + inputSize) + ("" + (inputSize ? ' columns' : '')) + ("" + (readOnly ? ' read-only' : '')) + ("" + (disabled ? ' disabled' : '')) + ("" + (errorType ? " " + errorType : '')) + ("" + (nestedLevel && " cui-input--nested-" + nestedLevel || '')) + ("" + (className ? " " + className : ''))
    }, label && React.createElement(Label, {
      className: "cui-label",
      label: label,
      htmlFor: htmlId || id
    }), getInputWrapper(), inputHelpText && React.createElement(InputHelper, {
      message: inputHelpText
    }), errors && errors.map(function (e, i) {
      return React.createElement(InputError, {
        error: e,
        key: "input-error-" + i
      });
    }));
  };

  return Input;
}(React.Component);

Input.displayName = 'Input';
Input.defaultProps = {
  children: '',
  className: '',
  clear: false,
  clearAriaLabel: null,
  defaultValue: '',
  disabled: false,
  errorArr: [],
  inputClassName: '',
  inputHelpText: '',
  inputRef: null,
  inputSize: '',
  label: '',
  name: null,
  nestedLevel: 0,
  onChange: null,
  onDoneEditing: null,
  onFocus: null,
  onKeyDown: null,
  onMouseDown: null,
  placeholder: '',
  readOnly: false,
  secondaryLabel: '',
  type: 'text',
  value: ''
};
Input.propTypes = {
  /** Child component to display next to the input */
  children: PropTypes.node,

  /** Div Input ClassName */
  className: PropTypes.string,

  /** Clear */
  clear: PropTypes.bool,

  /** Optional aria label on the clear button */
  clearAriaLabel: PropTypes.string,

  /** Default Value same as value but used when onChange isn't */
  defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

  /*** optional disabled prop type */
  disabled: PropTypes.bool,

  /** Includes Array of Objects with error and type
   [{error: '', type: ''}] to display
   error message and assign class
   */
  errorArr: PropTypes.array,

  /** Unique HTML ID. Used for tying label to HTML input. Handy hook for automated testing. */
  htmlId: PropTypes.string,

  /** Unique HTML ID. Used for tying label to HTML input. */
  id: PropTypes.string,

  /** Div Input ClassName */
  inputClassName: PropTypes.string,

  /** Help Text to show form validation rules */
  inputHelpText: PropTypes.string,

  /*** optional ref prop type */
  inputRef: PropTypes.func,

  /** Overall input group size. */
  inputSize: PropTypes.string,

  /** Input label */
  label: PropTypes.string,

  /*** optional name prop type */
  name: PropTypes.string,

  /*** optional nextLevel prop type */
  nestedLevel: PropTypes.number,

  /** Function to call onChange */
  onChange: PropTypes.func,

  /*** optional function for blur prop type */
  onDoneEditing: PropTypes.func,

  /*** optional function for focus prop type */
  onFocus: PropTypes.func,

  /*** optional function for key up event */
  onKeyDown: PropTypes.func,

  /*** optional function for mouse down event */
  onMouseDown: PropTypes.func,

  /** Placeholder to display when empty */
  placeholder: PropTypes.string,

  /*** optional read-only prop type */
  readOnly: PropTypes.bool,

  /** Secondary Input label */
  secondaryLabel: PropTypes.string,

  /** Input type */
  type: PropTypes.oneOf(['text', 'number', 'password', 'email']),

  /** Value */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
};
export default Input;
/**
* @name Default Input
* @description Inputs are useful.
*
* @category controls
* @component input
* @section default
*
* @js

export default class Default extends React.PureComponent {

  render() {
    return (
      <div className='row'>
      <Input
        name='defaultInput'
        label='Default Input'
        htmlId='defaultInput'
        inputSize='small-5'
        placeholder='Placeholder Text'
      />
    </div>
    );
  }
}

**/

/**
* @name Input Type = Number
* @description Inputs are useful.
*
* @category controls
* @component input
* @section number
*
* @js

export default class Default extends React.PureComponent {
  render() {
    return (
      <div className='row'>
      <Input
        name='input2'
        label='Number Input'
        htmlId='input2'
        type='number'
      />
    </div>
    );
  }
}

**/

/**
* @name Input Type = Password
* @description Inputs are useful.
*
* @category controls
* @component input
* @section Type Attribute
*
* @js

export default class Default extends React.PureComponent {
  render() {
    return (
      <div className='row'>
      <Input
        name='input3'
        label='Password Input'
        htmlId='input3'
        type='password'
      />
    </div>
    );
  }
}

**/

/**
* @name Input Size
* @description Inputs are useful.
*
* @category controls
* @component input
* @section inputSize Attribute
*
* @js

export default function InputSize() {
  return (
    <div className='row'>
      <Input
        name='input4'
        label='Large Input'
        htmlId='input4'
        inputSize='medium-12'
      />
    </div>
  );
}

**/

/**
* @name Input Secondary Label
* @description Inputs are useful.
*
* @category controls
* @component input
* @section secondary-label
*
* @js

export default function InputSecondary() {
  return (
    <div className='row'>
      <Input
        name='inputSecondaryLabel'
        label='Input with Secondary Label'
        htmlId='inputSecondaryLabel'
        inputSize='small-5'
        secondaryLabel='Secondary Label'
      />
    </div>
  );
}

**/

/**
* @name Input Required
* @description Inputs are useful.
*
* @category controls
* @component input
* @section Required Attribute
*
* @js

export default function InputRequired() {
  return (
    <div className='row'>
      <Input
        name='input6'
        label='Required Input'
        htmlId='input6'
        required
      />
    </div>
  );
}

**/

/**
* @name Input Placeholder
* @description Inputs are useful.
*
* @category controls
* @component input
* @section placeholder Attribute
*
* @js

export default function InputPlaceholder() {
  return (
    <div className='row'>
      <Input
        name='input7'
        label='Placeholder Input'
        htmlId='input7'
        placeholder='Placeholder'
      />
    </div>
  );
}

**/

/**
* @name Input Help Text
* @description Inputs are useful.
*
* @category controls
* @component input
* @section help-text
*
* @js

export default function InputHelp() {
  return (
    <div className='row'>
      <Input
        name='inputHelpText'
        label='Help Text Input'
        htmlId='inputHelpText'
        inputSize='small-5'
        inputHelpText='Help Text'
      />
    </div>
  );
}

**/

/**
* @name Input Disabled
* @description Inputs are useful.
*
* @category controls
* @component input
* @section disabled
*
* @js

export default function InputDisabled() {
  return (
    <div className='row'>
      <Input
        name='inputDisabled'
        label='Disabled Input'
        htmlId='inputDisabled'
        inputSize='small-5'
        value='Disabled Text'
        disabled
      />
    </div>
  );
}

**/

/**
* @name Input Read Only
* @description Inputs are useful.
*
* @category controls
* @component input
* @section read-only
*
* @js

export default function InputReadonly() {
  return (
    <div className='row'>
      <Input
        name='inputReadonly'
        label='Read Only Input'
        htmlId='inputReadonly'
        inputSize='small-5'
        value='Read Only Text'
        readOnly
      />
    </div>
  );
}

**/

/**
* @name Input Nested
* @description Inputs are useful.
*
* @category controls
* @component input
* @section nested
*
* @js

export default function InputNested() {
  return (
    <div className='row' key={'input1'}>
      <Input
        name='inputParent'
        label='Parent Input Example'
        htmlId='inputParent'
        inputSize='small-5'
      />
    </div>,
    <div className='row' key={'input2'}>
      <Input
        name='inputNested1'
        label='Child Input Nested 1 Level'
        inputSize='small-5'
        htmlId='inputNested1'
        nestedLevel={1}
      />
    </div>,
    <div className='row' key={'input3'}>
      <Input
        name='inputNested2'
        label='Child Input Nested 2 Levels'
        inputSize='small-5'
        htmlId='inputNested2'
        nestedLevel={2}
      />
    </div>,
    <div className='row' key={'input4'}>
      <Input
        name='inputNested3'
        label='Child Input Nested 3 Levels'
        inputSize='small-5'
        htmlId='inputNested3'
        nestedLevel={3}
      />
    </div>
  );
}

**/

/**
* @name Input Error (Warning)
* @description Inputs are useful.
*
* @category controls
* @component input
* @section warning
*
* @js

export default function InputError() {
  return (
    <div className='row'>
      <Input
        name='inputWarning'
        label='Error (Warning) Input'
        htmlId='inputWarning'
        inputSize='small-5'
        errorArr={ [{error: 'This is where the warning message would be.', type: 'warning'}] }
      />
    </div>
  );
}

**/

/**
* @name Input Error (Error)
* @description Inputs are useful.
*
* @category controls
* @component input
* @section error
*
* @js

export default function InputError() {
  return (
    <div className='row'>
      <Input
        name='inputError'
        label='Error (Error) Input'
        htmlId='inputError'
        inputSize='small-5'
        errorArr={ [{error: 'This is where the error message would be.', type: 'error'}] }
      />
    </div>
  );
}

**/

/**
* @name Input Error (Success)
* @description Inputs are useful.
*
* @category controls
* @component input
* @section success
*
* @js

export default function InputError() {
  return (
    <div className='row'>
      <Input
        name='inputSuccess'
        label='Error (Success) Input'
        htmlId='inputSuccess'
        inputSize='small-5'
        errorArr={ [{error: 'This is where the success message would be.', type: 'success'}] }
      />
    </div>
  );
}

**/

/**
* @name Advanced Validation
* @description Example of advanced validation.
*
* @category controls
* @component input
* @section advanced-validation
*
* @js

export default class Form extends React.PureComponent {
  constructor() {
    super();

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.validateField = this.validateField.bind(this);
    this.removeElement = this.removeElement.bind(this);
    this.retrieveState = this.retrieveState.bind(this);
    this.addElement = this.addElement.bind(this);
    this.createErrorArr = this.createErrorArr.bind(this);
  }

  state = {
    testMe: '',
    testMeError: []
  }

  handleChange(value) {
    this.setState({
      testMe: value
    });
  }

  handleSubmit(event) {
    event && event.preventDefault();
    this.validateField('testMe', this.state.testMe);
  }

  retrieveState() {
    return this.state;
  }

  addElement(array, element) {
    return array.includes(element)
    ? [...array]
    : [...array, element];
  }

  removeElement(array, element) {
    return array.filter((ele) => ele !== element);
  }

  createErrorArr(validationArr, value) {
    return validationArr.reduce((agg, e) =>
      value.match(e.test)
      ? this.removeElement(agg, e)
      : this.addElement(agg, e)
    , []);
  }

  validateField(fieldName, value, cb) {
    const rules = {
      testMe: {
        validation: [
          {
            error: 'Preferred if TestMe Field is 8 characters',
            test: '^[a-zA-Z]{8,}$',
            type: 'warning'
          },
          {
            error: 'TestMe Field is too short',
            test: '^[a-zA-Z]{6,}$',
            type: 'error'
          },
          {
            error: 'TestMe Field must contain Caps',
            test: '[A-Z]',
            type: 'error'
          },
          {
            error: 'Preferred if TestMe Field has 2 caps',
            test: '[A-Z]{2}',
            type: 'warning'
          }
        ],
        errors: this.state.testMeError
      }
    };

    return (
      this.setState({
        [`${fieldName}Error`]: this.createErrorArr(rules[fieldName].validation, value)
      },
        cb
      )
    );
  }

  render() {
    return (
      <form name='testFrom' onSubmit={this.handleSubmit}>
        <div className='row'>
          <Input
            inputSize='small-5'
            htmlId='testMe'
            value={this.state.testMe}
            name='testMe'
            label='Advanced Validation'
            onChange={this.handleChange}
            inputHelpText='Field Must contain at least 6 characters and 1 capital letter'
            errorArr={this.state.testMeError}
          />
        </div>
          {this.props.children}
      </form>
    );
  }
}

**/

/**
* @name Input with clear button
* @description You can use the built in clear functionality
*
* @category controls
* @component input
* @section clear
*
* @js

export default class Clear extends React.PureComponent {
  state = {
    value: 'Press or click the clear icon to clear this input'
  };

  handleChange = (event) => {
    this.setState({value: event.target.value});
  }

  render() {
    return (
      <div className='row'>
      <Input
        name='clearInput'
        label='Input with clear'
        htmlId='clearInput'
        inputSize='small-5'
        placeholder='Placeholder Text'
        value={this.state.value}
        onChange={this.handleChange}
        clear
      />
    </div>
    );
  }
}


**/