shineout
Version:
Shein 前端组件库
412 lines (337 loc) • 14.7 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
import _createClass from "@babel/runtime/helpers/createClass";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import React from 'react';
import immer from 'immer';
import { Component } from '../component';
import { promiseAll, isSameError } from '../utils/errors';
import shallowEqual from '../utils/shallowEqual';
import { filterProps } from '../utils/objects';
import { getUidStr } from '../utils/uid';
import { isArray } from '../utils/is';
import _validate from '../utils/validate';
import { FORCE_PASS, ERROR_TYPE, IGNORE_VALIDATE, errorSubscribe, IGNORE_BIND } from '../Datum/types';
import { formConsumer } from './formContext';
import { itemConsumer } from './Item';
import { fieldSetConsumer } from './FieldSet';
var types = ['formDatum', 'disabled', 'combineRules', 'size'];
var tryValue = function tryValue(val, def) {
return val === undefined ? def : val;
};
var beforeValueChange = function beforeValueChange(fn) {
return function (value, datum) {
if (!fn) return value;
var newValue = fn(value, datum);
return newValue === undefined ? value : newValue;
};
};
export default (function (Origin) {
var InputableInner =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(InputableInner, _Component);
function InputableInner(props) {
var _this;
_this = _Component.call(this, props) || this;
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "itemName", void 0);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "lastValue", void 0);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "updateTimer", void 0);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "datum", void 0);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "lastError", void 0);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "errorChange", void 0);
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "customValidate", void 0);
var formDatum = props.formDatum,
name = props.name,
defaultValue = props.defaultValue;
_this.state = {
error: undefined,
value: props.value || defaultValue
};
_this.itemName = getUidStr();
_this.handleChange = _this.handleChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleUpdate = _this.handleUpdate.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleDatumBind = _this.handleDatumBind.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleError = _this.handleError.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.validate = _this.validate.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.validateHook = _this.validateHook.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.lastValue = formDatum && name ? formDatum.get(name) || {} : {};
return _this;
}
var _proto = InputableInner.prototype;
_proto.componentDidMount = function componentDidMount() {
var _this2 = this;
_Component.prototype.componentDidMount.call(this); // @ts-ignore
var readOnly = this.props.readOnly;
var _this$props = this.props,
onChange = _this$props.onChange,
disabled = _this$props.disabled;
if ('value' in this.props && !onChange && disabled !== true && readOnly !== true) {
console.error('warning: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly` or `disabled`');
}
var _this$props2 = this.props,
formDatum = _this$props2.formDatum,
name = _this$props2.name,
defaultValue = _this$props2.defaultValue,
bindInputToItem = _this$props2.bindInputToItem,
popover = _this$props2.popover;
if (formDatum && name) {
if (Array.isArray(name)) {
var dv = defaultValue || [];
name.forEach(function (n, i) {
return formDatum.bind(n, _this2.handleUpdate, dv[i], _this2.validate);
}); // @ts-ignore
this.state.value = name.map(function (n) {
return formDatum.get(n);
});
formDatum.subscribe(errorSubscribe(this.errorName), this.handleUpdate);
} else {
formDatum.bind(name, this.handleUpdate, defaultValue, this.validate); // @ts-ignore
this.state.value = formDatum.get(name);
}
this.lastValue = this.state.value;
}
if (bindInputToItem && name && !popover) bindInputToItem(this.errorName);
};
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
var skip = [].concat(this.props.scuSkip || [], ['formDatum']);
var isFormDatum = this.props.formDatum && this.props.name;
if (isFormDatum) skip.push('value');
var options = {
skip: skip,
deep: ['data', 'defaultValue', 'datum', 'name', 'rule', 'style']
};
if (!isFormDatum && !shallowEqual(this.getValue(), nextState.value)) return true;
return !(shallowEqual(nextProps, this.props, options) && shallowEqual(nextState, this.state));
};
_proto.componentWillUnmount = function componentWillUnmount() {
_Component.prototype.componentWillUnmount.call(this);
var _this$props3 = this.props,
formDatum = _this$props3.formDatum,
name = _this$props3.name,
unbindInputFromItem = _this$props3.unbindInputFromItem,
reserveAble = _this$props3.reserveAble;
clearTimeout(this.updateTimer);
if (formDatum && name) {
formDatum.unbind(name, this.handleUpdate, reserveAble);
if (Array.isArray(name)) {
formDatum.unsubscribe(errorSubscribe(this.errorName), this.handleUpdate);
formDatum.setError(this.errorName);
}
}
if (unbindInputFromItem && name) unbindInputFromItem(this.errorName);
};
_proto.getValue = function getValue() {
var _this$props4 = this.props,
formDatum = _this$props4.formDatum,
name = _this$props4.name,
value = _this$props4.value,
defaultValue = _this$props4.defaultValue;
if (formDatum && name) {
if (Array.isArray(name)) {
var dv = defaultValue || [];
return name.map(function (n, i) {
return tryValue(formDatum.get(n), dv[i]);
});
}
return tryValue(formDatum.get(name), defaultValue);
}
var hasValue = 'value' in this.props || 'checked' in this.props;
return !hasValue ? this.state.value : value;
};
_proto.getError = function getError() {
var _this$props5 = this.props,
formDatum = _this$props5.formDatum,
name = _this$props5.name,
error = _this$props5.error;
if ('error' in this.props) {
return error;
}
if (formDatum && name) {
return formDatum.getError(this.errorName);
}
return this.state.error;
};
_proto.handleDatumBind = function handleDatumBind(datum) {
this.datum = datum;
};
_proto.handleError = function handleError(error) {
var _this$props6 = this.props,
formDatum = _this$props6.formDatum,
name = _this$props6.name,
onItemError = _this$props6.onItemError,
onError = _this$props6.onError;
if (formDatum && name) {
if (!isSameError(error, formDatum.getError(this.errorName, true))) {
formDatum.setError(this.errorName, error, true);
}
} else {
this.setState({
error: error
});
}
var hasError = error !== undefined;
this.errorChange = hasError !== this.lastError;
this.lastError = hasError;
if (onError) onError(error);
if (onItemError && !name) onItemError(this.itemName, error);
};
_proto.validateHook = function validateHook(customValidate) {
this.customValidate = customValidate;
};
_proto.validate = function validate(value, data, type) {
var _this3 = this;
var _this$props7 = this.props,
name = _this$props7.name,
formDatum = _this$props7.formDatum,
combineRules = _this$props7.combineRules,
bind = _this$props7.bind;
var names = Array.isArray(name) ? name : [name];
var validates = [];
var validateProps = filterProps(this.props, function (v) {
return typeof v === 'string' || typeof v === 'number';
});
if (this.datum) {
var datumValue = this.datum.formatValue(value);
value = this.datum.limit === 1 ? datumValue[0] : datumValue; // @ts-ignore
validateProps.type = 'array';
}
if (type === FORCE_PASS || value === FORCE_PASS) {
this.handleError();
return Promise.resolve(true);
}
if (value === undefined || Array.isArray(name)) value = this.getValue();
if (!Array.isArray(name)) value = [value];
if (this.customValidate) validates.push(this.customValidate());
if (formDatum && bind && type !== IGNORE_BIND) {
// console.error(new Error('Use "bind" props to combine validate is not recommend. Use Form "groups" props instead.'))
formDatum.validateFields(bind, IGNORE_BIND).catch(function () {});
}
if (!data && formDatum) data = formDatum.getValue();
var rules = this.props.rules;
names.forEach(function (n, i) {
if (formDatum && combineRules) {
rules = combineRules(n, rules);
}
if (isArray(rules) && rules.length > 0) {
validates.push(_validate(value[i], data, rules, validateProps));
}
});
return promiseAll(validates).then(function (res) {
_this3.handleError(res === true ? undefined : res);
return res;
}).catch(function (e) {
_this3.handleError(e);
return e;
});
};
_proto.handleChange = function handleChange(value) {
var _this4 = this;
var _this$props8 = this.props,
formDatum = _this$props8.formDatum,
name = _this$props8.name,
fieldSetValidate = _this$props8.fieldSetValidate,
onChange = _this$props8.onChange,
filterSameChange = _this$props8.filterSameChange;
var currentValue = this.getValue();
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
if ((args.length === 0 || filterSameChange) && shallowEqual(value, currentValue)) {
return;
}
var beforeChange = beforeValueChange(this.props.beforeChange);
if (formDatum && name) {
value = beforeChange(value, formDatum);
formDatum.set(name, value);
formDatum.removeFormError(this.errorName);
} else {
value = beforeChange(value, undefined);
this.setState({
value: value
}, function () {
_this4.validate(value).catch(function () {});
});
}
if (onChange) onChange.apply(void 0, [value].concat(args));
if (fieldSetValidate) fieldSetValidate(true);
};
_proto.handleUpdate = function handleUpdate(value, sn, type) {
var _this5 = this;
if (type === ERROR_TYPE) {
if (!isSameError(value, this.state.error)) this.setState({
error: value
});
return;
}
var _this$props9 = this.props,
name = _this$props9.name,
onChange = _this$props9.onChange,
forceChangeOnValueSet = _this$props9.forceChangeOnValueSet;
var newValue = !Array.isArray(name) ? value : immer(this.getValue(), function (draft) {
name.forEach(function (n, i) {
if (n === sn) draft[i] = value;
});
});
if (!this.errorChange && shallowEqual(newValue, this.lastValue)) return;
this.lastValue = newValue;
if (type === FORCE_PASS) {
this.handleError();
this.setState({
error: undefined
});
this.forceUpdate();
return;
}
if (onChange && forceChangeOnValueSet) onChange(newValue);
if (type !== IGNORE_VALIDATE) {
if (this.updateTimer) clearTimeout(this.updateTimer);
this.updateTimer = setTimeout(function () {
_this5.validate(newValue, undefined, type).catch(function () {});
}, 0);
}
this.forceUpdate();
};
_proto.render = function render() {
var _this$props10 = this.props,
formDatum = _this$props10.formDatum,
value = _this$props10.value,
required = _this$props10.required,
bind = _this$props10.bind,
onItemError = _this$props10.onItemError,
bindInputToItem = _this$props10.bindInputToItem,
unbindInputFromItem = _this$props10.unbindInputFromItem,
scuSkip = _this$props10.scuSkip,
defaultValue = _this$props10.defaultValue,
rules = _this$props10.rules,
reserveAble = _this$props10.reserveAble,
other = _objectWithoutPropertiesLoose(_this$props10, ["formDatum", "value", "required", "bind", "onItemError", "bindInputToItem", "unbindInputFromItem", "scuSkip", "defaultValue", "rules", "reserveAble"]);
return React.createElement(Origin, _extends({}, other, {
formDatum: formDatum,
error: this.getError(),
value: this.getValue(),
onChange: this.handleChange,
onDatumBind: this.handleDatumBind,
validateHook: this.validateHook
}));
};
_createClass(InputableInner, [{
key: "errorName",
get: function get() {
var name = this.props.name;
return Array.isArray(name) ? name.join('|') : name;
}
}]);
return InputableInner;
}(Component);
_defineProperty(InputableInner, "defaultProps", {
rules: [],
scuSkip: ['onChange', 'rules']
});
var WithFiledSetConsumer = fieldSetConsumer(InputableInner);
var WidthItemConsumer = itemConsumer(WithFiledSetConsumer);
var WidthFormConsumer = formConsumer(types)(WidthItemConsumer);
return WidthFormConsumer;
});