You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
InternshipProject/node_modules/rc-field-form/lib/Field.js

676 lines
21 KiB

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));
var _toArray = _interopRequireDefault(require("rc-util/lib/Children/toArray"));
var _warning = _interopRequireDefault(require("rc-util/lib/warning"));
var React = _interopRequireWildcard(require("react"));
var _FieldContext = _interopRequireWildcard(require("./FieldContext"));
var _typeUtil = require("./utils/typeUtil");
var _validateUtil = require("./utils/validateUtil");
var _valueUtil = require("./utils/valueUtil");
var _excluded = ["name"];
var EMPTY_ERRORS = [];
function requireUpdate(shouldUpdate, prev, next, prevValue, nextValue, info) {
if (typeof shouldUpdate === 'function') {
return shouldUpdate(prev, next, 'source' in info ? {
source: info.source
} : {});
}
return prevValue !== nextValue;
} // We use Class instead of Hooks here since it will cost much code by using Hooks.
var Field = /*#__PURE__*/function (_React$Component) {
(0, _inherits2.default)(Field, _React$Component);
var _super = (0, _createSuper2.default)(Field);
/**
* Follow state should not management in State since it will async update by React.
* This makes first render of form can not get correct state value.
*/
/**
* Mark when touched & validated. Currently only used for `dependencies`.
* Note that we do not think field with `initialValue` is dirty
* but this will be by `isFieldDirty` func.
*/
// ============================== Subscriptions ==============================
function Field(props) {
var _this;
(0, _classCallCheck2.default)(this, Field);
_this = _super.call(this, props); // Register on init
_this.state = {
resetCount: 0
};
_this.cancelRegisterFunc = null;
_this.mounted = false;
_this.touched = false;
_this.dirty = false;
_this.validatePromise = null;
_this.prevValidating = void 0;
_this.errors = EMPTY_ERRORS;
_this.warnings = EMPTY_ERRORS;
_this.cancelRegister = function () {
var _this$props = _this.props,
preserve = _this$props.preserve,
isListField = _this$props.isListField,
name = _this$props.name;
if (_this.cancelRegisterFunc) {
_this.cancelRegisterFunc(isListField, preserve, (0, _valueUtil.getNamePath)(name));
}
_this.cancelRegisterFunc = null;
};
_this.getNamePath = function () {
var _this$props2 = _this.props,
name = _this$props2.name,
fieldContext = _this$props2.fieldContext;
var _fieldContext$prefixN = fieldContext.prefixName,
prefixName = _fieldContext$prefixN === void 0 ? [] : _fieldContext$prefixN;
return name !== undefined ? [].concat((0, _toConsumableArray2.default)(prefixName), (0, _toConsumableArray2.default)(name)) : [];
};
_this.getRules = function () {
var _this$props3 = _this.props,
_this$props3$rules = _this$props3.rules,
rules = _this$props3$rules === void 0 ? [] : _this$props3$rules,
fieldContext = _this$props3.fieldContext;
return rules.map(function (rule) {
if (typeof rule === 'function') {
return rule(fieldContext);
}
return rule;
});
};
_this.refresh = function () {
if (!_this.mounted) return;
/**
* Clean up current node.
*/
_this.setState(function (_ref) {
var resetCount = _ref.resetCount;
return {
resetCount: resetCount + 1
};
});
};
_this.triggerMetaEvent = function (destroy) {
var onMetaChange = _this.props.onMetaChange;
onMetaChange === null || onMetaChange === void 0 ? void 0 : onMetaChange((0, _objectSpread2.default)((0, _objectSpread2.default)({}, _this.getMeta()), {}, {
destroy: destroy
}));
};
_this.onStoreChange = function (prevStore, namePathList, info) {
var _this$props4 = _this.props,
shouldUpdate = _this$props4.shouldUpdate,
_this$props4$dependen = _this$props4.dependencies,
dependencies = _this$props4$dependen === void 0 ? [] : _this$props4$dependen,
onReset = _this$props4.onReset;
var store = info.store;
var namePath = _this.getNamePath();
var prevValue = _this.getValue(prevStore);
var curValue = _this.getValue(store);
var namePathMatch = namePathList && (0, _valueUtil.containsNamePath)(namePathList, namePath); // `setFieldsValue` is a quick access to update related status
if (info.type === 'valueUpdate' && info.source === 'external' && prevValue !== curValue) {
_this.touched = true;
_this.dirty = true;
_this.validatePromise = null;
_this.errors = EMPTY_ERRORS;
_this.warnings = EMPTY_ERRORS;
_this.triggerMetaEvent();
}
switch (info.type) {
case 'reset':
if (!namePathList || namePathMatch) {
// Clean up state
_this.touched = false;
_this.dirty = false;
_this.validatePromise = null;
_this.errors = EMPTY_ERRORS;
_this.warnings = EMPTY_ERRORS;
_this.triggerMetaEvent();
onReset === null || onReset === void 0 ? void 0 : onReset();
_this.refresh();
return;
}
break;
/**
* In case field with `preserve = false` nest deps like:
* - A = 1 => show B
* - B = 1 => show C
* - Reset A, need clean B, C
*/
case 'remove':
{
if (shouldUpdate) {
_this.reRender();
return;
}
break;
}
case 'setField':
{
if (namePathMatch) {
var data = info.data;
if ('touched' in data) {
_this.touched = data.touched;
}
if ('validating' in data && !('originRCField' in data)) {
_this.validatePromise = data.validating ? Promise.resolve([]) : null;
}
if ('errors' in data) {
_this.errors = data.errors || EMPTY_ERRORS;
}
if ('warnings' in data) {
_this.warnings = data.warnings || EMPTY_ERRORS;
}
_this.dirty = true;
_this.triggerMetaEvent();
_this.reRender();
return;
} // Handle update by `setField` with `shouldUpdate`
if (shouldUpdate && !namePath.length && requireUpdate(shouldUpdate, prevStore, store, prevValue, curValue, info)) {
_this.reRender();
return;
}
break;
}
case 'dependenciesUpdate':
{
/**
* Trigger when marked `dependencies` updated. Related fields will all update
*/
var dependencyList = dependencies.map(_valueUtil.getNamePath); // No need for `namePathMath` check and `shouldUpdate` check, since `valueUpdate` will be
// emitted earlier and they will work there
// If set it may cause unnecessary twice rerendering
if (dependencyList.some(function (dependency) {
return (0, _valueUtil.containsNamePath)(info.relatedFields, dependency);
})) {
_this.reRender();
return;
}
break;
}
default:
// 1. If `namePath` exists in `namePathList`, means it's related value and should update
// For example <List name="list"><Field name={['list', 0]}></List>
// If `namePathList` is [['list']] (List value update), Field should be updated
// If `namePathList` is [['list', 0]] (Field value update), List shouldn't be updated
// 2.
// 2.1 If `dependencies` is set, `name` is not set and `shouldUpdate` is not set,
// don't use `shouldUpdate`. `dependencies` is view as a shortcut if `shouldUpdate`
// is not provided
// 2.2 If `shouldUpdate` provided, use customize logic to update the field
// else to check if value changed
if (namePathMatch || (!dependencies.length || namePath.length || shouldUpdate) && requireUpdate(shouldUpdate, prevStore, store, prevValue, curValue, info)) {
_this.reRender();
return;
}
break;
}
if (shouldUpdate === true) {
_this.reRender();
}
};
_this.validateRules = function (options) {
// We should fixed namePath & value to avoid developer change then by form function
var namePath = _this.getNamePath();
var currentValue = _this.getValue(); // Force change to async to avoid rule OOD under renderProps field
var rootPromise = Promise.resolve().then(function () {
if (!_this.mounted) {
return [];
}
var _this$props5 = _this.props,
_this$props5$validate = _this$props5.validateFirst,
validateFirst = _this$props5$validate === void 0 ? false : _this$props5$validate,
messageVariables = _this$props5.messageVariables;
var _ref2 = options || {},
triggerName = _ref2.triggerName;
var filteredRules = _this.getRules();
if (triggerName) {
filteredRules = filteredRules.filter(function (rule) {
var validateTrigger = rule.validateTrigger;
if (!validateTrigger) {
return true;
}
var triggerList = (0, _typeUtil.toArray)(validateTrigger);
return triggerList.includes(triggerName);
});
}
var promise = (0, _validateUtil.validateRules)(namePath, currentValue, filteredRules, options, validateFirst, messageVariables);
promise.catch(function (e) {
return e;
}).then(function () {
var ruleErrors = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EMPTY_ERRORS;
if (_this.validatePromise === rootPromise) {
_this.validatePromise = null; // Get errors & warnings
var nextErrors = [];
var nextWarnings = [];
ruleErrors.forEach(function (_ref3) {
var warningOnly = _ref3.rule.warningOnly,
_ref3$errors = _ref3.errors,
errors = _ref3$errors === void 0 ? EMPTY_ERRORS : _ref3$errors;
if (warningOnly) {
nextWarnings.push.apply(nextWarnings, (0, _toConsumableArray2.default)(errors));
} else {
nextErrors.push.apply(nextErrors, (0, _toConsumableArray2.default)(errors));
}
});
_this.errors = nextErrors;
_this.warnings = nextWarnings;
_this.triggerMetaEvent();
_this.reRender();
}
});
return promise;
});
_this.validatePromise = rootPromise;
_this.dirty = true;
_this.errors = EMPTY_ERRORS;
_this.warnings = EMPTY_ERRORS;
_this.triggerMetaEvent(); // Force trigger re-render since we need sync renderProps with new meta
_this.reRender();
return rootPromise;
};
_this.isFieldValidating = function () {
return !!_this.validatePromise;
};
_this.isFieldTouched = function () {
return _this.touched;
};
_this.isFieldDirty = function () {
// Touched or validate or has initialValue
if (_this.dirty || _this.props.initialValue !== undefined) {
return true;
} // Form set initialValue
var fieldContext = _this.props.fieldContext;
var _fieldContext$getInte = fieldContext.getInternalHooks(_FieldContext.HOOK_MARK),
getInitialValue = _fieldContext$getInte.getInitialValue;
if (getInitialValue(_this.getNamePath()) !== undefined) {
return true;
}
return false;
};
_this.getErrors = function () {
return _this.errors;
};
_this.getWarnings = function () {
return _this.warnings;
};
_this.isListField = function () {
return _this.props.isListField;
};
_this.isList = function () {
return _this.props.isList;
};
_this.isPreserve = function () {
return _this.props.preserve;
};
_this.getMeta = function () {
// Make error & validating in cache to save perf
_this.prevValidating = _this.isFieldValidating();
var meta = {
touched: _this.isFieldTouched(),
validating: _this.prevValidating,
errors: _this.errors,
warnings: _this.warnings,
name: _this.getNamePath()
};
return meta;
};
_this.getOnlyChild = function (children) {
// Support render props
if (typeof children === 'function') {
var meta = _this.getMeta();
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, _this.getOnlyChild(children(_this.getControlled(), meta, _this.props.fieldContext))), {}, {
isFunction: true
});
} // Filed element only
var childList = (0, _toArray.default)(children);
if (childList.length !== 1 || ! /*#__PURE__*/React.isValidElement(childList[0])) {
return {
child: childList,
isFunction: false
};
}
return {
child: childList[0],
isFunction: false
};
};
_this.getValue = function (store) {
var getFieldsValue = _this.props.fieldContext.getFieldsValue;
var namePath = _this.getNamePath();
return (0, _valueUtil.getValue)(store || getFieldsValue(true), namePath);
};
_this.getControlled = function () {
var childProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _this$props6 = _this.props,
trigger = _this$props6.trigger,
validateTrigger = _this$props6.validateTrigger,
getValueFromEvent = _this$props6.getValueFromEvent,
normalize = _this$props6.normalize,
valuePropName = _this$props6.valuePropName,
getValueProps = _this$props6.getValueProps,
fieldContext = _this$props6.fieldContext;
var mergedValidateTrigger = validateTrigger !== undefined ? validateTrigger : fieldContext.validateTrigger;
var namePath = _this.getNamePath();
var getInternalHooks = fieldContext.getInternalHooks,
getFieldsValue = fieldContext.getFieldsValue;
var _getInternalHooks = getInternalHooks(_FieldContext.HOOK_MARK),
dispatch = _getInternalHooks.dispatch;
var value = _this.getValue();
var mergedGetValueProps = getValueProps || function (val) {
return (0, _defineProperty2.default)({}, valuePropName, val);
}; // eslint-disable-next-line @typescript-eslint/no-explicit-any
var originTriggerFunc = childProps[trigger];
var control = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, childProps), mergedGetValueProps(value)); // Add trigger
control[trigger] = function () {
// Mark as touched
_this.touched = true;
_this.dirty = true;
_this.triggerMetaEvent();
var newValue;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (getValueFromEvent) {
newValue = getValueFromEvent.apply(void 0, args);
} else {
newValue = _valueUtil.defaultGetValueFromEvent.apply(void 0, [valuePropName].concat(args));
}
if (normalize) {
newValue = normalize(newValue, value, getFieldsValue(true));
}
dispatch({
type: 'updateValue',
namePath: namePath,
value: newValue
});
if (originTriggerFunc) {
originTriggerFunc.apply(void 0, args);
}
}; // Add validateTrigger
var validateTriggerList = (0, _typeUtil.toArray)(mergedValidateTrigger || []);
validateTriggerList.forEach(function (triggerName) {
// Wrap additional function of component, so that we can get latest value from store
var originTrigger = control[triggerName];
control[triggerName] = function () {
if (originTrigger) {
originTrigger.apply(void 0, arguments);
} // Always use latest rules
var rules = _this.props.rules;
if (rules && rules.length) {
// We dispatch validate to root,
// since it will update related data with other field with same name
dispatch({
type: 'validateField',
namePath: namePath,
triggerName: triggerName
});
}
};
});
return control;
};
if (props.fieldContext) {
var getInternalHooks = props.fieldContext.getInternalHooks;
var _getInternalHooks2 = getInternalHooks(_FieldContext.HOOK_MARK),
initEntityValue = _getInternalHooks2.initEntityValue;
initEntityValue((0, _assertThisInitialized2.default)(_this));
}
return _this;
}
(0, _createClass2.default)(Field, [{
key: "componentDidMount",
value: function componentDidMount() {
var _this$props7 = this.props,
shouldUpdate = _this$props7.shouldUpdate,
fieldContext = _this$props7.fieldContext;
this.mounted = true; // Register on init
if (fieldContext) {
var getInternalHooks = fieldContext.getInternalHooks;
var _getInternalHooks3 = getInternalHooks(_FieldContext.HOOK_MARK),
registerField = _getInternalHooks3.registerField;
this.cancelRegisterFunc = registerField(this);
} // One more render for component in case fields not ready
if (shouldUpdate === true) {
this.reRender();
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.cancelRegister();
this.triggerMetaEvent(true);
this.mounted = false;
}
}, {
key: "reRender",
value: function reRender() {
if (!this.mounted) return;
this.forceUpdate();
}
}, {
key: "render",
value: function render() {
var resetCount = this.state.resetCount;
var children = this.props.children;
var _this$getOnlyChild = this.getOnlyChild(children),
child = _this$getOnlyChild.child,
isFunction = _this$getOnlyChild.isFunction; // Not need to `cloneElement` since user can handle this in render function self
var returnChildNode;
if (isFunction) {
returnChildNode = child;
} else if ( /*#__PURE__*/React.isValidElement(child)) {
returnChildNode = /*#__PURE__*/React.cloneElement(child, this.getControlled(child.props));
} else {
(0, _warning.default)(!child, '`children` of Field is not validate ReactElement.');
returnChildNode = child;
}
return /*#__PURE__*/React.createElement(React.Fragment, {
key: resetCount
}, returnChildNode);
}
}]);
return Field;
}(React.Component);
Field.contextType = _FieldContext.default;
Field.defaultProps = {
trigger: 'onChange',
valuePropName: 'value'
};
function WrapperField(_ref5) {
var name = _ref5.name,
restProps = (0, _objectWithoutProperties2.default)(_ref5, _excluded);
var fieldContext = React.useContext(_FieldContext.default);
var namePath = name !== undefined ? (0, _valueUtil.getNamePath)(name) : undefined;
var key = 'keep';
if (!restProps.isListField) {
key = "_".concat((namePath || []).join('_'));
} // Warning if it's a directly list field.
// We can still support multiple level field preserve.
if (process.env.NODE_ENV !== 'production' && restProps.preserve === false && restProps.isListField && namePath.length <= 1) {
(0, _warning.default)(false, '`preserve` should not apply on Form.List fields.');
}
return /*#__PURE__*/React.createElement(Field, (0, _extends2.default)({
key: key,
name: namePath
}, restProps, {
fieldContext: fieldContext
}));
}
var _default = WrapperField;
exports.default = _default;