UNPKG

sc-react-ions

Version:

An open source set of React components that implement Ambassador's Design and UX patterns.

239 lines (184 loc) 8.03 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _debounce = require('lodash/debounce'); var _debounce2 = _interopRequireDefault(_debounce); var _validation = require('../../utilities/validation'); var _form = require('../../utilities/form'); var _immutable = require('immutable'); var _style = require('./style.scss'); var _style2 = _interopRequireDefault(_style); var _OptClass = require('../internal/OptClass'); var _OptClass2 = _interopRequireDefault(_OptClass); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var FormGroup = function (_React$Component) { _inherits(FormGroup, _React$Component); function FormGroup(props) { _classCallCheck(this, FormGroup); var _this = _possibleConstructorReturn(this, (FormGroup.__proto__ || Object.getPrototypeOf(FormGroup)).call(this, props)); _this.state = { fieldErrors: (0, _immutable.Map)() }; _this.componentWillReceiveProps = function (nextProps) { var nextPropsSchema = (0, _immutable.fromJS)(nextProps.schema); var thisPropsSchema = (0, _immutable.fromJS)(_this.props.schema); if (!(0, _immutable.is)(nextPropsSchema, thisPropsSchema)) { _this.setState({ fields: (0, _immutable.fromJS)(nextProps.schema) }); } }; _this.componentWillMount = function () { _this.setState({ fields: (0, _immutable.fromJS)(_this.props.schema) }); }; _this._mapFieldErrors = function () { return _this.state.fieldErrors.merge(_this.props.fieldErrors); }; _this.handleSubmit = function (event) { event.preventDefault(); var fieldErrors = (0, _validation.validate)(_this._formValidation, (0, _form.formSchemaToKeyVal)(_this.state.fields)); // Required to send error prop to ValidatedField component _this.setState({ fieldErrors: fieldErrors }); if (fieldErrors && fieldErrors.size && typeof _this.props.errorCallback === 'function') { return _this.props.errorCallback(fieldErrors); } if (typeof _this.props.submitCallback === 'function') { _this.props.submitCallback(event, _this.state.fields.toJS()); } }; _this.handleChange = function (event) { var name = event.target.name; var val = event.target.value; var option = event.target.option; // Handle checkbox values if (event.target.type === 'checkbox') { val = event.target.checked; } _this.setState(function (prevState) { var fields = prevState.fields.setIn([name, 'value'], val); if (option) { fields = fields.setIn([name, 'option'], option); } var fieldErrors = prevState.fieldErrors.set(name, ''); return { fields: fields, fieldErrors: fieldErrors }; }, function () { if (_this.props.changeCallback) { _this.props.changeCallback(_this.state.fields.toJS(), _this.props.fieldErrors.merge(_this.state.fieldErrors)); } }); }; _this.getElements = function (children, recursiveCall) { // Reset validation each time this called on the form group if (!recursiveCall) { _this._formValidation = (0, _immutable.Map)(); } var fieldErrors = _this._mapFieldErrors(); return _react2.default.Children.map(children, function (child) { if (!child) return child; var childProps = {}; if (child.props) { var name = child.props.name; var error = fieldErrors.get(name); var value = _this.state.fields.getIn([name, 'value']); var valueIsImmutable = _immutable.Iterable.isIterable(value); var valueProp = valueIsImmutable ? value.toJS() : value; if (child.props.validation) { _this._formValidation = _this._formValidation.set(name, (0, _immutable.Map)({ validators: (0, _immutable.fromJS)(child.props.validation) })); } if (_this.state.fields.has(name) && _react2.default.isValidElement(child)) { childProps = { changeCallback: _this.props.debounceTime ? _this.debounce : _this.handleChange, value: valueProp, error: error }; } childProps.children = _this.getElements(child.props.children, true); return _react2.default.cloneElement(child, childProps); } return child; }); }; _this.renderForm = function () { var elements = _this.getElements(_this.props.children); var formGroupClass = (0, _OptClass2.default)(_style2.default, 'form-group', _this.props.optClass); var formWrapper = void 0; if (!_this.props.nested) { formWrapper = _react2.default.createElement( 'form', { className: formGroupClass, onSubmit: _this.handleSubmit }, _react2.default.createElement( 'fieldset', { className: _style2.default.fieldset }, elements ) ); } else { var fieldsetClass = (0, _OptClass2.default)(_style2.default, 'fieldset', _this.props.optClass); formWrapper = _react2.default.createElement( 'fieldset', { className: fieldsetClass }, elements ); } return formWrapper; }; _this.render = function () { return _this.renderForm(); }; _this.debounce = (0, _debounce2.default)(_this.handleChange, _this.props.debounceTime); _this._formValidation = null; return _this; } // Errors can be passed in via props if external validation is used or // errors can be captured from state if internal validation is used return FormGroup; }(_react2.default.Component); FormGroup.propTypes = { /** * A configuration object of name/value pairs * that correspond to the form fields names. */ schema: _propTypes2.default.object, /** * A callback function to be called when a form value changes. */ changeCallback: _propTypes2.default.func, /** * A callback function to be called when the form is submitted. */ submitCallback: _propTypes2.default.func, /** * Optional CSS class(es) to be used for local styles (string or array of strings) */ optClass: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.string]), /** * Option to turn off form wrapper (for nested components) */ nested: _propTypes2.default.bool, /** * Option to turn off debounce when something in the form group changes */ debounceTime: _propTypes2.default.number, /** * A key value pair eg: { 'message': 'this is an error message' }, were the * key repesents the `name` of the given field to validate */ fieldErrors: _propTypes2.default.object }; FormGroup.defaultProps = { debounceTime: 0, fieldErrors: (0, _immutable.Map)() }; exports.default = FormGroup;