a-plus-forms
Advanced tools
Comparing version 0.2.2 to 0.3.0
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _react = require('react'); | ||
@@ -14,2 +16,4 @@ | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var DefaultLayout = function DefaultLayout(_ref) { | ||
@@ -35,8 +39,29 @@ var input = _ref.input, | ||
null, | ||
'error' | ||
error | ||
) : null | ||
); | ||
}; | ||
// just a dummy validator for simple function based validators | ||
var DefaultValidator = function () { | ||
function DefaultValidator(schema) { | ||
_classCallCheck(this, DefaultValidator); | ||
this.schema = schema; | ||
} | ||
_createClass(DefaultValidator, [{ | ||
key: 'errorsFor', | ||
value: function errorsFor(data) { | ||
return this.schema(data); | ||
} | ||
}]); | ||
return DefaultValidator; | ||
}(); | ||
exports.default = { | ||
DefaultValidator: DefaultValidator, | ||
defaultLayout: DefaultLayout | ||
}; |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var _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; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
@@ -24,6 +24,8 @@ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _state = require('./state'); | ||
var _state2 = _interopRequireDefault(_state); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } | ||
@@ -36,5 +38,3 @@ | ||
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; } | ||
/* eslint no-use-before-define: off */ | ||
exports.default = function () { | ||
@@ -57,4 +57,3 @@ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var StateStrategy = options.nested ? NestedStateStrategy : ReactStateStrategy; | ||
_this.stateStrategy = new StateStrategy(_this); | ||
_this.stateManager = new _state2.default(_this, { nested: options.nested }); | ||
return _this; | ||
@@ -68,3 +67,4 @@ } | ||
APFProps: this.props, | ||
APFState: options.nested && this | ||
APFState: options.nested && this.stateManager, | ||
APFError: options.nested && _typeof(this.props.error) === 'object' && this.props.error || undefined | ||
}; | ||
@@ -76,3 +76,3 @@ } | ||
if (this.context.APFState) { | ||
this.context.APFState.stateStrategy.register(this); | ||
this.context.APFState.register(this); | ||
} | ||
@@ -90,3 +90,3 @@ | ||
if (this.context.APFState) { | ||
this.context.APFState.stateStrategy.unregister(this); | ||
this.context.APFState.unregister(this); | ||
} | ||
@@ -106,7 +106,8 @@ } | ||
defaultValue = _props.defaultValue, | ||
props = _objectWithoutProperties(_props, ['defaultValue']); // eslint-disable-line | ||
error = _props.error, | ||
props = _objectWithoutProperties(_props, ['defaultValue', 'error']); // eslint-disable-line | ||
Object.assign(props, { value: this.value, onChange: this.onChange }); | ||
return _react2.default.createElement(_layout2.default, { input: Input, props: props, layout: options.layout }); | ||
return _react2.default.createElement(_layout2.default, { input: Input, props: props, error: this.error, layout: options.layout }); | ||
} | ||
@@ -121,10 +122,27 @@ }, { | ||
get: function get() { | ||
return this.stateStrategy.value; | ||
return this.stateManager.value; | ||
}, | ||
set: function set(value) { | ||
if (this.stateStrategy.value !== value) { | ||
this.stateStrategy.value = value; | ||
if (this.stateManager.value !== value) { | ||
this.stateManager.value = value; | ||
this.props.onChange(value); | ||
} | ||
} | ||
}, { | ||
key: 'error', | ||
get: function get() { | ||
var _context$APFError = this.context.APFError, | ||
APFError = _context$APFError === undefined ? {} : _context$APFError; | ||
var _props2 = this.props, | ||
propsError = _props2.error, | ||
name = _props2.name; | ||
var error = propsError || APFError[name]; | ||
if (options.nested && typeof error !== 'string') { | ||
return error && error[''] || null; // delegate to the sub-fields | ||
} | ||
return error; | ||
} | ||
}]); | ||
@@ -136,91 +154,10 @@ | ||
}, _class.contextTypes = { | ||
APFState: _propTypes2.default.object | ||
APFState: _propTypes2.default.object, | ||
APFError: _propTypes2.default.object | ||
}, _class.childContextTypes = { | ||
APFState: _propTypes2.default.object, // nested field anchor | ||
APFProps: _propTypes2.default.object // original field props | ||
APFProps: _propTypes2.default.object, // original field props, | ||
APFError: _propTypes2.default.object // nested field errors | ||
}, _temp; | ||
}; | ||
}; | ||
// a generic input field state strategy | ||
var ReactStateStrategy = function () { | ||
function ReactStateStrategy(component) { | ||
_classCallCheck(this, ReactStateStrategy); | ||
this.component = component; | ||
this.component.state = { value: undefined }; | ||
} | ||
_createClass(ReactStateStrategy, [{ | ||
key: 'value', | ||
get: function get() { | ||
return this.component.state.value; | ||
}, | ||
set: function set(value) { | ||
this.component.setState({ value: value }); | ||
} | ||
}]); | ||
return ReactStateStrategy; | ||
}(); | ||
// a compount input state strategy | ||
// NOTE: a nested field can receive initial values _before_ sub-fields | ||
// start to register. which, will create a un-sync situation | ||
// to solve the problem, nested field strategy saves any incoming values | ||
// in the `seedValues` property and then pipes them into fields as they | ||
// register | ||
var NestedStateStrategy = function () { | ||
function NestedStateStrategy(component) { | ||
_classCallCheck(this, NestedStateStrategy); | ||
this.fields = []; | ||
this.seedValues = {}; | ||
this.component = component; | ||
} | ||
_createClass(NestedStateStrategy, [{ | ||
key: 'register', | ||
value: function register(field) { | ||
this.fields.push(field); | ||
if (field.name && field.name in this.seedValues) { | ||
field.value = this.seedValues[field.name]; | ||
delete this.seedValues[field.name]; | ||
} | ||
} | ||
}, { | ||
key: 'unregister', | ||
value: function unregister(field) { | ||
this.fields.splice(this.fields.indexOf(field), 1); | ||
} | ||
}, { | ||
key: 'value', | ||
get: function get() { | ||
return this.fields.reduce(function (data, field) { | ||
return Object.assign(data, field.name ? _defineProperty({}, field.name, field.value) : {}); | ||
}, {}); | ||
}, | ||
set: function set(data) { | ||
var _this2 = this; | ||
if (this.fields.length === 0) { | ||
this.seedValues = _extends({}, data); // stashing the initial value | ||
} | ||
Object.keys(data || {}).forEach(function (name) { | ||
var field = _this2.fields.find(function (field) { | ||
return field.name === name; | ||
}); | ||
if (field) field.value = data[name]; | ||
}); | ||
} | ||
}]); | ||
return NestedStateStrategy; | ||
}(); | ||
}; |
@@ -16,2 +16,6 @@ 'use strict'; | ||
var _propTypes = require('prop-types'); | ||
var _propTypes2 = _interopRequireDefault(_propTypes); | ||
var _field = require('./field'); | ||
@@ -21,6 +25,10 @@ | ||
var _validator = require('../validator'); | ||
var _config = require('../config'); | ||
var _validator2 = _interopRequireDefault(_validator); | ||
var _config2 = _interopRequireDefault(_config); | ||
var _error = require('./error'); | ||
var _error2 = _interopRequireDefault(_error); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -39,2 +47,5 @@ | ||
}); | ||
var isPromisish = function isPromisish(smth) { | ||
return smth && typeof smth.then === 'function' && typeof smth.catch === 'function'; | ||
}; | ||
@@ -55,12 +66,31 @@ var Form = (_temp2 = _class = function (_React$Component) { | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref2 = Form.__proto__ || Object.getPrototypeOf(Form)).call.apply(_ref2, [this].concat(args))), _this), _this.onSubmit = function (event) { | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref2 = Form.__proto__ || Object.getPrototypeOf(Form)).call.apply(_ref2, [this].concat(args))), _this), _this.state = { errors: null }, _this.onSubmit = function (event) { | ||
event.preventDefault(); | ||
if (_this.isValid()) { | ||
var data = _this.props.preSubmit(_this.value); | ||
_this.validate().then(function (errors) { | ||
if (!errors) { | ||
var result = _this.props.onSubmit(_this.value); | ||
_this.props.onSubmit(data); | ||
_this.props.postSubmit(data); | ||
if (isPromisish(result)) { | ||
result.catch(function (error) { | ||
if (error instanceof _error2.default) { | ||
_this.handleErrors(error.errors); | ||
} else { | ||
throw error; | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
}, _this.handleErrors = function (errors) { | ||
_this.setState({ errors: errors }); | ||
if (errors) { | ||
_this.props.onError(errors, _this.value); | ||
} | ||
}, _this.validator = new _validator2.default(), _temp), _possibleConstructorReturn(_this, _ret); | ||
return errors; | ||
}, _this.setStateRef = function (e) { | ||
_this.stateContainer = e; | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
} | ||
@@ -71,3 +101,7 @@ | ||
value: function componentWillMount() { | ||
this.updateValidator(this.props); | ||
var APFValidator = this.context.APFValidator; | ||
var schema = this.props.schema; | ||
this.validator = new (APFValidator || _config2.default.DefaultValidator)(schema); | ||
} | ||
@@ -77,30 +111,25 @@ }, { | ||
value: function componentWillReceiveProps(props) { | ||
this.updateValidator(props); | ||
var schema = props.schema; | ||
this.validator.schema = schema; | ||
} | ||
}, { | ||
key: 'isValid', | ||
value: function isValid() { | ||
var data = this.props.preValidate(this.value); | ||
var errors = this.validator.errorsFor(data); | ||
key: 'validate', | ||
value: function validate() { | ||
var _this2 = this; | ||
if (errors) { | ||
this.props.onError(errors, data); | ||
return false; | ||
var errors = this.validator.errorsFor(this.value); | ||
if (isPromisish(errors)) { | ||
return errors.then(this.handleErrors); | ||
} | ||
return true; | ||
return { then: function then(cb) { | ||
return cb(_this2.handleErrors(errors)); | ||
} }; | ||
} | ||
}, { | ||
key: 'updateValidator', | ||
value: function updateValidator(_ref3) { | ||
var validate = _ref3.validate, | ||
schema = _ref3.schema; | ||
this.validator.update({ validate: validate, schema: schema }); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var _this2 = this; | ||
var _props = this.props, | ||
@@ -110,10 +139,13 @@ children = _props.children, | ||
onChange = _props.onChange; | ||
var errors = this.state.errors; | ||
var setRef = function setRef(e) { | ||
_this2.stateContainer = e; | ||
}; | ||
return _react2.default.createElement( | ||
StateContainer, | ||
{ defaultValue: defaultValue, onChange: onChange, ref: setRef }, | ||
{ | ||
error: errors, | ||
defaultValue: defaultValue, | ||
onChange: onChange, | ||
ref: this.setStateRef | ||
}, | ||
_react2.default.createElement( | ||
@@ -137,16 +169,11 @@ 'form', | ||
return Form; | ||
}(_react2.default.Component), _class.defaultProps = { | ||
}(_react2.default.Component), _class.contextTypes = { | ||
APFValidator: _propTypes2.default.func | ||
}, _class.defaultProps = { | ||
onSubmit: function onSubmit() {}, | ||
onChange: function onChange() {}, | ||
onError: function onError() {}, | ||
validate: function validate() {}, | ||
preValidate: function preValidate(data) { | ||
return data; | ||
}, | ||
preSubmit: function preSubmit(data) { | ||
return data; | ||
}, | ||
postSubmit: function postSubmit() {}, | ||
schema: function schema() {}, | ||
defaultValue: {} | ||
}, _temp2); | ||
exports.default = Form; |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.default = exports.LayoutProvider = undefined; | ||
exports.default = undefined; | ||
@@ -13,3 +13,3 @@ var _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; }; | ||
var _class, _temp, _class2, _temp2; | ||
var _class, _temp; | ||
@@ -39,38 +39,7 @@ var _react = require('react'); | ||
/** | ||
* This is the standard interface to feed different field | ||
* layouts into the forms in different contexts | ||
*/ | ||
var LayoutProvider = exports.LayoutProvider = (_temp = _class = function (_React$Component) { | ||
_inherits(LayoutProvider, _React$Component); | ||
function LayoutProvider() { | ||
_classCallCheck(this, LayoutProvider); | ||
return _possibleConstructorReturn(this, (LayoutProvider.__proto__ || Object.getPrototypeOf(LayoutProvider)).apply(this, arguments)); | ||
} | ||
_createClass(LayoutProvider, [{ | ||
key: 'getChildContext', | ||
value: function getChildContext() { | ||
return { APFPLayout: this.props.layout }; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
return this.props.children; | ||
} | ||
}]); | ||
return LayoutProvider; | ||
}(_react2.default.Component), _class.childContextTypes = { | ||
APFPLayout: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.object]).isRequired | ||
}, _temp); | ||
/** | ||
* This is the actual layout strategy component | ||
*/ | ||
var LayoutHandler = (_temp = _class = function (_React$Component) { | ||
_inherits(LayoutHandler, _React$Component); | ||
var LayoutHandler = (_temp2 = _class2 = function (_React$Component2) { | ||
_inherits(LayoutHandler, _React$Component2); | ||
function LayoutHandler() { | ||
@@ -109,9 +78,11 @@ _classCallCheck(this, LayoutHandler); | ||
value: function layoutProps() { | ||
var _props$props2 = this.props.props, | ||
var _props = this.props, | ||
_props$props2 = _props.props, | ||
id = _props$props2.id, | ||
className = _props$props2.className, | ||
rest = _objectWithoutProperties(_props$props2, ['id', 'className']); // eslint-disable-line | ||
rest = _objectWithoutProperties(_props$props2, ['id', 'className']), | ||
error = _props.error; // eslint-disable-line | ||
return rest; | ||
return _extends({}, rest, { error: error }); | ||
} | ||
@@ -124,6 +95,6 @@ | ||
value: function chooseLayout() { | ||
var _props = this.props, | ||
layout = _props.layout, | ||
props = _props.props; | ||
var APFPLayout = this.context.APFPLayout; | ||
var _props2 = this.props, | ||
layout = _props2.layout, | ||
props = _props2.props; | ||
var APFLayout = this.context.APFLayout; | ||
@@ -135,4 +106,4 @@ | ||
return layout || null; // the field options layout | ||
} else if (APFPLayout) { | ||
return APFPLayout; // the context layout | ||
} else if (APFLayout) { | ||
return APFLayout; // the context layout | ||
} | ||
@@ -157,4 +128,5 @@ | ||
return LayoutHandler; | ||
}(_react2.default.Component), _class2.contextTypes = { | ||
APFPLayout: _propTypes2.default.any }, _temp2); | ||
}(_react2.default.Component), _class.contextTypes = { | ||
APFLayout: _propTypes2.default.any | ||
}, _temp); | ||
exports.default = LayoutHandler; |
@@ -6,13 +6,4 @@ 'use strict'; | ||
}); | ||
exports.default = exports.config = exports.optionizer = exports.trimmer = exports.Radios = exports.Select = exports.Slider = exports.Checkbox = exports.Textarea = exports.HiddenInput = exports.PasswordInput = exports.NumberInput = exports.SearchInput = exports.EmailInput = exports.TextInput = exports.LayoutProvider = exports.Form = exports.field = undefined; | ||
exports.default = exports.config = exports.optionizer = exports.trimmer = exports.Radios = exports.Select = exports.Slider = exports.Checkbox = exports.Textarea = exports.HiddenInput = exports.PasswordInput = exports.NumberInput = exports.SearchInput = exports.EmailInput = exports.TextInput = exports.ValidatorProvider = exports.LayoutProvider = exports.Error = exports.Form = exports.field = undefined; | ||
var _layout = require('./core/layout'); | ||
Object.defineProperty(exports, 'LayoutProvider', { | ||
enumerable: true, | ||
get: function get() { | ||
return _layout.LayoutProvider; | ||
} | ||
}); | ||
var _field2 = require('./core/field'); | ||
@@ -26,2 +17,14 @@ | ||
var _error = require('./core/error'); | ||
var _error2 = _interopRequireDefault(_error); | ||
var _layout = require('./providers/layout'); | ||
var _layout2 = _interopRequireDefault(_layout); | ||
var _validator = require('./providers/validator'); | ||
var _validator2 = _interopRequireDefault(_validator); | ||
var _text = require('./inputs/text'); | ||
@@ -87,2 +90,5 @@ | ||
exports.Form = _form2.default; | ||
exports.Error = _error2.default; | ||
exports.LayoutProvider = _layout2.default; | ||
exports.ValidatorProvider = _validator2.default; | ||
exports.TextInput = _text2.default; | ||
@@ -89,0 +95,0 @@ exports.EmailInput = _email2.default; |
@@ -63,8 +63,3 @@ 'use strict'; | ||
return _react2.default.createElement(_text2.default, _extends({}, rest, { | ||
type: 'number', | ||
layout: null, | ||
value: '' + value, | ||
onChange: this.onChange | ||
})); | ||
return _react2.default.createElement(_text2.default, _extends({}, rest, { type: 'number', layout: null, value: '' + value, onChange: this.onChange })); | ||
} | ||
@@ -71,0 +66,0 @@ }]); |
{ | ||
"name": "a-plus-forms", | ||
"version": "0.2.2", | ||
"version": "0.3.0", | ||
"description": "A+ forms. Would use again", | ||
@@ -13,6 +13,12 @@ "files": [ | ||
"build": "babel src --out-dir dist/", | ||
"precommit": "npm run lint", | ||
"precommit": "lint-staged", | ||
"prepush": "npm run test", | ||
"prepare": "NODE_ENV=production npm run build" | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"eslint --fix", | ||
"git add" | ||
] | ||
}, | ||
"repository": { | ||
@@ -35,29 +41,28 @@ "type": "git", | ||
"babel-core": "^6.25.0", | ||
"babel-eslint": "^7.2.3", | ||
"babel-eslint": "8.0.1", | ||
"babel-plugin-transform-decorators-legacy": "^1.3.4", | ||
"babel-preset-env": "^1.6.0", | ||
"babel-preset-es2015": "^6.24.0", | ||
"babel-preset-react": "^6.23.0", | ||
"babel-preset-stage-1": "^6.22.0", | ||
"babel-register": "^6.26.0", | ||
"chai": "^4.0.2", | ||
"chai-enzyme": "^0.8.0", | ||
"enzyme": "^2.9.1", | ||
"eslint": "^3.8.1", | ||
"chai-enzyme": "v1.0.0-beta.0", | ||
"enzyme": "^3.1.0", | ||
"enzyme-adapter-react-16": "^1.0.1", | ||
"eslint": "^4.9.0", | ||
"eslint-config-shortlyster": "^2.2.0", | ||
"eslint-plugin-flowtype": "^2.34.1", | ||
"flow-bin": "^0.49.1", | ||
"flow-runtime": "^0.13.0", | ||
"flow-bin": "^0.57.3", | ||
"flow-runtime": "0.14.0", | ||
"husky": "^0.14.3", | ||
"jsdom": "^11.1.0", | ||
"mocha": "^3.4.2", | ||
"react-addons-test-utils": "^15.6.0", | ||
"sinon": "^2.3.6", | ||
"lint-staged": "^4.2.3", | ||
"mocha": "4.0.1", | ||
"prop-types": "^15.6.0", | ||
"react": "^16.0.0", | ||
"react-dom": "^16.0.0", | ||
"react-test-renderer": "^16.0.0", | ||
"sinon": "4.0.1", | ||
"sinon-chai": "^2.11.0" | ||
}, | ||
"peerDependencies": { | ||
"ajv": "^5.2.1", | ||
"prop-types": "^15.5.8", | ||
"react": "^15.6.1", | ||
"react-dom": "^15.6.1" | ||
} | ||
} |
91010
0
27
1528
27