"use strict";

exports.__esModule = true;
exports.default = void 0;

require("core-js/modules/web.dom.iterable");

require("core-js/modules/es6.array.iterator");

require("core-js/modules/es6.object.keys");

require("core-js/modules/es6.object.assign");

var _react = _interopRequireDefault(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _lodash = require("lodash");

var _ = require("./..");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

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 _objectWithoutPropertiesLoose(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]; } return target; }

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

/**
 * @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.props.defaultValue
    };

    _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();

      if (e.keyCode === 27 || e.keyCode === 13 || e.type === 'blur') {
        _this.setState({
          isEditing: false
        }, function () {
          return onDoneEditing && onDoneEditing(e, 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,
        disabled = _this$props4.disabled,
        errorArr = _this$props4.errorArr,
        htmlId = _this$props4.htmlId,
        iconNode = _this$props4.iconNode,
        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,
        theme = _this$props4.theme,
        type = _this$props4.type,
        props = _objectWithoutPropertiesLoose(_this$props4, ["children", "className", "clear", "clearAriaLabel", "disabled", "errorArr", "htmlId", "iconNode", "id", "inputClassName", "inputHelpText", "inputSize", "label", "nestedLevel", "placeholder", "readOnly", "secondaryLabel", "theme", "type"]);

    var value = this.state.value;
    var otherProps = (0, _lodash.omit)(Object.assign({}, props), ['defaultValue', '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.default.createElement("div", {
        className: "cui-label__secondary-label-container"
      }, inputElement, _react.default.createElement(_.Label, {
        className: "cui-label__secondary-label",
        htmlFor: htmlId,
        label: secondaryLabel,
        theme: theme
      }));
    };

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

    var customInputIconNode = iconNode && _react.default.cloneElement(iconNode, {
      className: iconNode.props.onClick ? '' : 'cui-input__icon'
    });

    var iconContainer = function iconContainer() {
      return _react.default.createElement("div", {
        className: "cui-input__icon-container"
      }, inputElement, children, customInputIconNode || clearButton);
    };

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

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

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

  return Input;
}(_react.default.Component);

Input.propTypes = {
  /** @prop Child component to display next to the input | '' */
  children: _propTypes.default.node,

  /** @prop Optional css class name | '' */
  className: _propTypes.default.string,

  /** @prop Clears Input values | false */
  clear: _propTypes.default.bool,

  /** @prop Optional aria label on the clear button | null */
  clearAriaLabel: _propTypes.default.string,

  /** @prop Default Value same as value but used when onChange isn't invoked | '' */
  defaultValue: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),

  /*** @prop Sets the disabled attribute of the Input | false */
  disabled: _propTypes.default.bool,

  /** @prop Array of Objects with error and type [{error: '', type: ''}] to display error message and assign class | [] */
  errorArr: _propTypes.default.array,

  /** @prop Unique HTML ID used for tying label to HTML input for automated testing | null */
  htmlId: _propTypes.default.string,

  /** Optional Icon node that overrides the default clear icon | null */
  iconNode: _propTypes.default.node,

  /** Unique HTML ID used for tying label to HTML input | null */
  id: _propTypes.default.string,

  /** @prop Input css class name string | '' */
  inputClassName: _propTypes.default.string,

  /** @prop Help Text to show form validation rules | '' */
  inputHelpText: _propTypes.default.string,

  /*** @prop Optional Input ref prop type | null */
  inputRef: _propTypes.default.func,

  /** @prop Overall input group size | '' */
  inputSize: _propTypes.default.string,

  /** @prop Input label text | '' */
  label: _propTypes.default.string,

  /*** @prop Optional Input name prop type | null */
  name: _propTypes.default.string,

  /** @prop Set the level of nested Input components | 0 */
  nestedLevel: _propTypes.default.number,

  /** @prop Callback function invoked when user types into the Input field | null */
  onChange: _propTypes.default.func,

  /*** @prop Callback function invoked when user is done editing Input field | null */
  onDoneEditing: _propTypes.default.func,

  /*** @prop Callback function invoked when user focuses on the Input field | null */
  onFocus: _propTypes.default.func,

  /*** @prop Callback function invoked when user presses any key | null */
  onKeyDown: _propTypes.default.func,

  /*** @prop Callback function invoked when user clicks on the mouse/trackpad | null */
  onMouseDown: _propTypes.default.func,

  /** @prop Placeholder text to display when Input is empty | '' */
  placeholder: _propTypes.default.string,

  /*** @prop Determines if Input can be edited | false */
  readOnly: _propTypes.default.bool,

  /** @prop Secondary Input label | '' */
  secondaryLabel: _propTypes.default.string,

  /** @prop Input color theme | '' */
  theme: _propTypes.default.string,

  /** @prop Input type | 'text' */
  type: _propTypes.default.oneOf(['text', 'number', 'password', 'email']),

  /** @prop Input value | '' */
  value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number])
};
Input.defaultProps = {
  children: '',
  className: '',
  clear: false,
  clearAriaLabel: null,
  defaultValue: '',
  disabled: false,
  errorArr: [],
  htmlId: null,
  iconNode: null,
  id: null,
  inputClassName: '',
  inputHelpText: '',
  inputRef: null,
  inputSize: '',
  label: '',
  name: null,
  nestedLevel: 0,
  onChange: null,
  onDoneEditing: null,
  onFocus: null,
  onKeyDown: null,
  onMouseDown: null,
  placeholder: '',
  readOnly: false,
  secondaryLabel: '',
  theme: '',
  type: 'text',
  value: ''
};
Input.displayName = 'Input';
var _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>
    );
  }
}


**/

/**
* @name Input with custom iconNode
* @description You can add an custom Icon node (overrides clear button if clear prop exists)
*
* @category controls
* @component input
* @section custom-icon
*
* @js


export default class CustomIconNode extends React.PureComponent {

  render() {
    const iconNode = (
      <Icon
        name="icon-info_16"
        ariaLabel={'custom icon'}
      />
    );

    return (
      <div className='row'>
      <Input
        name='inputIcon'
        label='Input with custom Icon node'
        htmlId='inputIcon'
        iconNode={iconNode}
        inputSize='small-5'
        placeholder='Placeholder Text'
      />
    </div>
    );
  }
}


**/

exports.default = _default;