New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@uform/core

Package Overview
Dependencies
Maintainers
4
Versions
120
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uform/core - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

1167

lib/index.js

@@ -1,1166 +0,1 @@

"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
var shared_1 = require("@uform/shared");
exports.FormPath = shared_1.FormPath;
var validator_1 = require("@uform/validator");
exports.setValidationLanguage = validator_1.setValidationLanguage;
exports.setValidationLocale = validator_1.setValidationLocale;
var lifecycle_1 = require("./shared/lifecycle");
var graph_1 = require("./shared/graph");
exports.FormGraph = graph_1.FormGraph;
var form_1 = require("./state/form");
var virtual_field_1 = require("./state/virtual-field");
var field_1 = require("./state/field");
var types_1 = require("./types");
__export(require("./shared/lifecycle"));
__export(require("./types"));
function createForm(options) {
if (options === void 0) { options = {}; }
function onGraphChange(_a) {
var type = _a.type, payload = _a.payload;
heart.publish(types_1.LifeCycleTypes.ON_FORM_GRAPH_CHANGE, graph);
if (type === 'GRAPH_NODE_WILL_UNMOUNT') {
validator.unregister(payload.path.toString());
}
}
function syncFieldValues(state) {
var dataPath = shared_1.FormPath.parse(state.name);
var parent = graph.getLatestParent(state.path);
var parentValue = getFormValuesIn(parent.path);
var value = getFormValuesIn(state.name);
var removed = false;
if (shared_1.isArr(parentValue) && !dataPath.existIn(parentValue, parent.path)) {
if (!parent.path
.getNearestChildPathBy(state.path)
.existIn(parentValue, parent.path)) {
graph.remove(state.path);
removed = true;
}
}
else {
shared_1.each(env.removeNodes, function (_, name) {
if (dataPath.includes(name)) {
graph.remove(state.path);
delete env.removeNodes[name];
removed = true;
}
});
}
if (removed)
return;
if (!shared_1.isEqual(value, state.value)) {
state.value = value;
}
}
function syncFieldIntialValues(state) {
var initialValue = getFormInitialValuesIn(state.name);
if (!shared_1.isEqual(initialValue, state.initialValue)) {
state.initialValue = initialValue;
if (!shared_1.isValid(state.value)) {
state.value = initialValue;
}
else if (/array/gi.test(state.dataType) &&
state.value &&
state.value.length === 0) {
state.value = initialValue;
}
}
}
function onFormChange(published) {
heart.publish(types_1.LifeCycleTypes.ON_FORM_CHANGE, state);
var valuesChanged = state.isDirty('values');
var initialValuesChanged = state.isDirty('initialValues');
var unmountedChanged = state.isDirty('unmounted');
var mountedChanged = state.isDirty('mounted');
var initializedChanged = state.isDirty('initialized');
var editableChanged = state.isDirty('editable');
if (valuesChanged || initialValuesChanged) {
var updateFields = function (field) {
if (types_1.isField(field)) {
field.setState(function (state) {
if (state.visible || state.unmounted) {
if (valuesChanged) {
syncFieldValues(state);
}
if (initialValuesChanged) {
syncFieldIntialValues(state);
}
}
else {
if (valuesChanged) {
env.hiddenPendingFields[state.name] =
env.hiddenPendingFields[state.name] || {};
env.hiddenPendingFields[state.name].values = true;
}
if (initialValuesChanged) {
env.hiddenPendingFields[state.name] =
env.hiddenPendingFields[state.name] || {};
env.hiddenPendingFields[state.name].initialValues = true;
}
}
});
}
};
if (valuesChanged || initialValuesChanged) {
if (!env.leadingStage) {
var userUpdateFieldPath = env.userUpdateFields[env.userUpdateFields.length - 1];
if (userUpdateFieldPath && graph.get(userUpdateFieldPath)) {
graph.eachParentAndChildren(userUpdateFieldPath, updateFields);
}
else {
graph.eachChildren(updateFields);
}
}
else {
graph.eachChildren(updateFields);
}
}
if (valuesChanged) {
if (shared_1.isFn(options.onChange)) {
options.onChange(shared_1.clone(published.values));
}
heart.publish(types_1.LifeCycleTypes.ON_FORM_VALUES_CHANGE, state);
}
if (initialValuesChanged) {
heart.publish(types_1.LifeCycleTypes.ON_FORM_INITIAL_VALUES_CHANGE, state);
}
}
if (editableChanged) {
graph.eachChildren(function (field) {
if (types_1.isField(field)) {
field.setState(function (state) {
state.formEditable = published.editable;
});
}
});
}
if (unmountedChanged && published.unmounted) {
heart.publish(types_1.LifeCycleTypes.ON_FORM_UNMOUNT, state);
}
if (mountedChanged && published.mounted) {
heart.publish(types_1.LifeCycleTypes.ON_FORM_MOUNT, state);
}
if (initializedChanged) {
heart.publish(types_1.LifeCycleTypes.ON_FORM_INIT, state);
}
}
function updateRecoverableShownState(parentState, childState, name) {
var lastShownState = env.lastShownStates[childState.path];
var lastStateValue = childState[name];
if (parentState[name] && lastShownState && lastShownState[name] === false) {
childState[name] = false;
delete lastShownState[name];
if (!lastShownState.hasOwnProperty('visible') &&
!lastShownState.hasOwnProperty('display')) {
delete env.lastShownStates[childState.path];
}
}
else {
childState[name] = parentState[name];
}
if (!parentState[name] && !lastStateValue) {
if (!lastShownState) {
env.lastShownStates[childState.path] = {};
}
env.lastShownStates[childState.path][name] = false;
}
}
function onFieldChange(_a) {
var field = _a.field, path = _a.path;
return function (published) {
var valueChanged = field.isDirty('value');
var initialValueChanged = field.isDirty('initialValue');
var visibleChanged = field.isDirty('visible');
var displayChanged = field.isDirty('display');
var unmountedChanged = field.isDirty('unmounted');
var mountedChanged = field.isDirty('mounted');
var initializedChanged = field.isDirty('initialized');
var warningsChanged = field.isDirty('warnings');
var errorsChanged = field.isDirty('errors');
var userUpdateFieldPath = env.userUpdateFields[env.userUpdateFields.length - 1];
var syncField = function () {
if (env.hiddenPendingFields[published.name]) {
field.setState(function (state) {
if (env.hiddenPendingFields[state.name].values) {
syncFieldValues(state);
}
if (env.hiddenPendingFields[state.name].initialValues) {
syncFieldIntialValues(state);
}
delete env.hiddenPendingFields[state.name];
});
}
};
var notifyFormValuesChange = function () {
if (shared_1.isFn(options.onChange)) {
options.onChange(state.getSourceState(function (state) { return shared_1.clone(state.values); }));
}
heart.publish(types_1.LifeCycleTypes.ON_FORM_VALUES_CHANGE, state);
};
if (initializedChanged) {
heart.publish(types_1.LifeCycleTypes.ON_FIELD_INIT, field);
var isEmptyValue_1 = !shared_1.isValid(published.value);
var isEmptyInitialValue_1 = !shared_1.isValid(published.initialValue);
if (isEmptyValue_1 || isEmptyInitialValue_1) {
field.setSourceState(function (state) {
if (isEmptyValue_1)
state.value = getFormValuesIn(state.name);
if (isEmptyInitialValue_1)
state.initialValue = getFormInitialValuesIn(state.name);
});
}
}
var wasHidden = published.visible == false || published.unmounted === true;
if (valueChanged) {
if (!wasHidden) {
userUpdating(field, function () {
setFormValuesIn(path, published.value);
});
}
heart.publish(types_1.LifeCycleTypes.ON_FIELD_VALUE_CHANGE, field);
}
if (initialValueChanged) {
if (!wasHidden) {
setFormInitialValuesIn(path, published.initialValue);
}
heart.publish(types_1.LifeCycleTypes.ON_FIELD_INITIAL_VALUE_CHANGE, field);
}
if (displayChanged || visibleChanged) {
if (visibleChanged) {
userUpdating(field, function () {
if (!published.visible) {
deleteFormValuesIn(path, true);
notifyFormValuesChange();
}
else {
setFormValuesIn(path, published.value);
syncField();
}
});
}
graph.eachChildren(path, function (childState) {
childState.setState(function (state) {
if (visibleChanged) {
updateRecoverableShownState(published, state, 'visible');
}
if (displayChanged) {
updateRecoverableShownState(published, state, 'display');
}
}, true);
});
}
if (unmountedChanged &&
(published.display !== false || published.visible === false)) {
userUpdating(field, function () {
if (published.unmounted) {
deleteFormValuesIn(path, true);
notifyFormValuesChange();
}
else {
setFormValuesIn(path, published.value);
syncField();
}
});
heart.publish(types_1.LifeCycleTypes.ON_FIELD_UNMOUNT, field);
}
if (mountedChanged && published.mounted) {
heart.publish(types_1.LifeCycleTypes.ON_FIELD_MOUNT, field);
}
if (errorsChanged) {
syncFormMessages('errors', published);
}
if (warningsChanged) {
syncFormMessages('warnings', published);
}
heart.publish(types_1.LifeCycleTypes.ON_FIELD_CHANGE, field);
if (userUpdateFieldPath && !env.leadingStage) {
if (shared_1.FormPath.parse(path).match(userUpdateFieldPath)) {
return;
}
if (shared_1.FormPath.parse(userUpdateFieldPath).includes(path)) {
return false;
}
}
};
}
function onVirtualFieldChange(_a) {
var field = _a.field, path = _a.path;
return function (published) {
var visibleChanged = field.isDirty('visible');
var displayChanged = field.isDirty('display');
var mountedChanged = field.isDirty('mounted');
var initializedChanged = field.isDirty('initialized');
if (initializedChanged) {
heart.publish(types_1.LifeCycleTypes.ON_FIELD_INIT, field);
}
if (visibleChanged || displayChanged) {
graph.eachChildren(path, function (childState) {
childState.setState(function (state) {
if (visibleChanged) {
updateRecoverableShownState(published, state, 'visible');
}
if (displayChanged) {
updateRecoverableShownState(published, state, 'display');
}
}, true);
});
}
if (mountedChanged && published.mounted) {
heart.publish(types_1.LifeCycleTypes.ON_FIELD_MOUNT, field);
}
heart.publish(types_1.LifeCycleTypes.ON_FIELD_CHANGE, field);
};
}
function registerVirtualField(_a) {
var name = _a.name, path = _a.path, props = _a.props, display = _a.display, visible = _a.visible, computeState = _a.computeState, useDirty = _a.useDirty;
var nodePath = shared_1.FormPath.parse(path || name);
var dataPath = transformDataPath(nodePath);
var field;
var createField = function (field) {
var alreadyHaveField = !!field;
field =
field ||
new virtual_field_1.VirtualFieldState({
nodePath: nodePath,
dataPath: dataPath,
computeState: computeState,
useDirty: shared_1.isValid(useDirty) ? useDirty : options.useDirty
});
field.subscription = {
notify: onVirtualFieldChange({ field: field, path: nodePath })
};
heart.publish(types_1.LifeCycleTypes.ON_FIELD_WILL_INIT, field);
if (!alreadyHaveField) {
graph.appendNode(nodePath, field);
}
field.batch(function () {
field.setState(function (state) {
state.initialized = true;
state.props = props;
if (shared_1.isValid(visible)) {
state.visible = visible;
}
if (shared_1.isValid(display)) {
state.display = display;
}
});
batchRunTaskQueue(field, nodePath);
});
return field;
};
if (graph.exist(nodePath)) {
field = graph.get(nodePath);
if (types_1.isField(field)) {
graph.replace(nodePath, field);
}
}
else {
field = createField();
}
return field;
}
function registerField(_a) {
var path = _a.path, name = _a.name, value = _a.value, initialValue = _a.initialValue, required = _a.required, rules = _a.rules, editable = _a.editable, visible = _a.visible, display = _a.display, computeState = _a.computeState, dataType = _a.dataType, useDirty = _a.useDirty, props = _a.props;
var field;
var nodePath = shared_1.FormPath.parse(path || name);
var dataPath = transformDataPath(nodePath);
var createField = function (field) {
var alreadyHaveField = !!field;
field =
field ||
new field_1.FieldState({
nodePath: nodePath,
dataPath: dataPath,
computeState: computeState,
dataType: dataType,
useDirty: shared_1.isValid(useDirty) ? useDirty : options.useDirty
});
field.subscription = {
notify: onFieldChange({ field: field, path: nodePath })
};
heart.publish(types_1.LifeCycleTypes.ON_FIELD_WILL_INIT, field);
if (!alreadyHaveField) {
graph.appendNode(nodePath, field);
}
field.batch(function () {
field.setState(function (state) {
var formValue = getFormValuesIn(dataPath);
var formInitialValue = getFormInitialValuesIn(dataPath);
if (shared_1.isValid(value)) {
state.value = value;
}
else {
state.value = existFormValuesIn(dataPath) ? formValue : initialValue;
}
state.initialValue = shared_1.isValid(initialValue)
? initialValue
: formInitialValue;
if (shared_1.isValid(visible)) {
state.visible = visible;
}
if (shared_1.isValid(display)) {
state.display = display;
}
if (shared_1.isValid(props)) {
state.props = props;
}
if (shared_1.isValid(required)) {
state.required = required;
}
if (shared_1.isValid(rules)) {
state.rules = rules;
}
if (shared_1.isValid(editable)) {
state.selfEditable = editable;
}
if (shared_1.isValid(options.editable)) {
state.formEditable = options.editable;
}
state.initialized = true;
});
batchRunTaskQueue(field, nodePath);
});
validator.register(nodePath, function (validate) {
var _a = field.getState(), value = _a.value, rules = _a.rules, editable = _a.editable, visible = _a.visible, unmounted = _a.unmounted, display = _a.display;
if (editable === false ||
visible === false ||
unmounted === true ||
display === false)
return validate(value, []);
clearTimeout(field.validateTimer);
field.validateTimer = setTimeout(function () {
field.setState(function (state) {
state.validating = true;
});
}, 60);
heart.publish(types_1.LifeCycleTypes.ON_FIELD_VALIDATE_START, field);
return validate(value, rules).then(function (_a) {
var errors = _a.errors, warnings = _a.warnings;
clearTimeout(field.validateTimer);
return new Promise(function (resolve) {
var syncState = function () {
field.setState(function (state) {
state.validating = false;
state.ruleErrors = errors;
state.ruleWarnings = warnings;
});
heart.publish(types_1.LifeCycleTypes.ON_FIELD_VALIDATE_END, field);
resolve({ errors: errors, warnings: warnings });
};
if (graph.size < 100) {
syncState();
}
else {
applyWithScheduler(syncState);
}
});
});
});
return field;
};
if (graph.exist(nodePath)) {
field = graph.get(nodePath);
if (types_1.isVirtualField(field)) {
graph.replace(nodePath, field);
}
}
else {
field = createField();
}
return field;
}
function syncFormMessages(type, fieldState) {
var name = fieldState.name, path = fieldState.path;
var messages = fieldState[type];
state.setSourceState(function (state) {
var foundField = false;
state[type] = state[type] || [];
state[type] = state[type].reduce(function (buf, item) {
if (item.path === path) {
foundField = true;
return messages.length ? buf.concat({ path: path, messages: messages }) : buf;
}
else {
return buf.concat(item);
}
}, []);
if (!foundField && messages.length) {
state[type].push({
name: name,
path: path,
messages: messages
});
}
if (state.errors.length) {
state.invalid = true;
state.valid = false;
}
else {
state.invalid = false;
state.valid = true;
}
});
}
function transformDataPath(path) {
var newPath = shared_1.FormPath.getPath(path);
return newPath.reduce(function (path, key, index) {
if (index >= newPath.length - 1)
return path.concat([key]);
var realPath = newPath.slice(0, index + 1);
var dataPath = path.concat([key]);
var selected = graph.get(realPath);
if (types_1.isVirtualField(selected)) {
return path;
}
return dataPath;
}, shared_1.FormPath.getPath(''));
}
function setFormIn(path, key, value, silent) {
state.setState(function (state) {
shared_1.FormPath.setIn(state[key], transformDataPath(path), value);
}, silent);
}
function deleteFormIn(path, key, silent) {
state.setState(function (state) {
shared_1.FormPath.deleteIn(state[key], transformDataPath(path));
}, silent);
}
function deleteFormValuesIn(path, silent) {
deleteFormIn(path, 'values', silent);
}
function setFormValuesIn(path, value, silent) {
return setFormIn(path, 'values', value, silent);
}
function setFormInitialValuesIn(path, value, silent) {
return setFormIn(path, 'initialValues', value, silent);
}
function getFormIn(path, key) {
return state.getState(function (state) {
return shared_1.FormPath.getIn(state[key], transformDataPath(path));
});
}
function getFormValuesIn(path) {
return getFormIn(path, 'values');
}
function existFormValuesIn(path) {
return state.getState(function (state) {
return shared_1.FormPath.existIn(state.values, transformDataPath(path));
});
}
function getFormInitialValuesIn(path) {
return getFormIn(path, 'initialValues');
}
function createMutators(field) {
if (!types_1.isField(field)) {
throw new Error('The `createMutators` can only accept FieldState instance.');
}
function setValue() {
var values = [];
for (var _i = 0; _i < arguments.length; _i++) {
values[_i] = arguments[_i];
}
field.setState(function (state) {
state.value = values[0];
state.values = values;
});
heart.publish(types_1.LifeCycleTypes.ON_FIELD_INPUT_CHANGE, field);
heart.publish(types_1.LifeCycleTypes.ON_FORM_INPUT_CHANGE, state);
}
function removeValue(key) {
var nodePath = field.getSourceState(function (state) { return state.path; });
if (shared_1.isValid(key)) {
var childNodePath = shared_1.FormPath.parse(nodePath).concat(key);
env.userUpdateFields.push(nodePath);
env.removeNodes[childNodePath.toString()] = true;
deleteFormValuesIn(childNodePath);
field.notify(field.getState());
env.userUpdateFields.pop();
}
else {
var parent_1 = graph.selectParent(nodePath);
env.removeNodes[nodePath.toString()] = true;
var parentNodePath = parent_1 && parent_1.getSourceState(function (state) { return state.path; });
if (parentNodePath) {
env.userUpdateFields.push(parentNodePath);
}
else {
env.userUpdateFields.push(nodePath);
}
deleteFormValuesIn(nodePath);
if (parent_1) {
parent_1.notify(parent_1.getState());
}
env.userUpdateFields.pop();
}
heart.publish(types_1.LifeCycleTypes.ON_FIELD_VALUE_CHANGE, field);
heart.publish(types_1.LifeCycleTypes.ON_FIELD_INPUT_CHANGE, field);
heart.publish(types_1.LifeCycleTypes.ON_FORM_INPUT_CHANGE, state);
}
function getValue() {
return field.getSourceState(function (state) { return state.value; });
}
return {
change: function () {
var values = [];
for (var _i = 0; _i < arguments.length; _i++) {
values[_i] = arguments[_i];
}
setValue.apply(void 0, values);
return values[0];
},
focus: function () {
field.setState(function (state) {
state.active = true;
});
},
blur: function () {
field.setState(function (state) {
state.active = false;
state.visited = true;
});
},
push: function (value) {
var arr = shared_1.toArr(getValue()).slice();
arr.push(value);
setValue(arr);
return arr;
},
pop: function () {
var arr = shared_1.toArr(getValue()).slice();
arr.pop();
setValue(arr);
return arr;
},
insert: function (index, value) {
var arr = shared_1.toArr(getValue()).slice();
arr.splice(index, 0, value);
setValue(arr);
return arr;
},
remove: function (index) {
var val = getValue();
if (shared_1.isNum(index) && shared_1.isArr(val)) {
val = [].concat(val);
val.splice(index, 1);
setValue(val);
}
else {
removeValue(index);
}
},
exist: function (index) {
var newPath = field.getSourceState(function (state) {
return shared_1.FormPath.parse(state.path);
});
var val = getValue();
return (shared_1.isValid(index) ? newPath.concat(index) : newPath).existIn(val, newPath);
},
unshift: function (value) {
var arr = shared_1.toArr(getValue()).slice();
arr.unshift(value);
setValue(arr);
return arr;
},
shift: function () {
var arr = shared_1.toArr(getValue()).slice();
arr.shift();
setValue(arr);
return arr;
},
move: function ($from, $to) {
var arr = shared_1.toArr(getValue()).slice();
var item = arr[$from];
arr.splice($from, 1);
arr.splice($to, 0, item);
setValue(arr);
return arr;
},
moveUp: function (index) {
var arr = shared_1.toArr(getValue()).slice();
var item = arr[index];
var len = arr.length;
arr.splice(index, 1);
arr.splice(index - 1 < 0 ? len - 1 : index - 1, 0, item);
setValue(arr);
return arr;
},
moveDown: function (index) {
var arr = shared_1.toArr(getValue()).slice();
var item = arr[index];
var len = arr.length;
arr.splice(index, 1);
arr.splice(index + 1 > len ? 0 : index + 1, 0, item);
setValue(arr);
return arr;
},
validate: function (opts) {
return validate(field.getSourceState(function (state) { return state.path; }), opts);
}
};
}
function clearErrors(pattern) {
if (pattern === void 0) { pattern = '*'; }
graph.eachChildren('', pattern, function (field) {
if (types_1.isField(field)) {
field.setState(function (state) {
state.ruleErrors = [];
state.ruleWarnings = [];
state.effectErrors = [];
state.effectWarnings = [];
});
}
});
}
function reset(_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.selector, selector = _c === void 0 ? '*' : _c, _d = _b.forceClear, forceClear = _d === void 0 ? false : _d, _e = _b.validate, validate = _e === void 0 ? true : _e, _f = _b.clearInitialValue, clearInitialValue = _f === void 0 ? false : _f;
return __awaiter(this, void 0, void 0, function () {
var validateResult;
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
graph.eachChildren('', selector, function (field) {
field.setState(function (state) {
state.modified = false;
state.ruleErrors = [];
state.ruleWarnings = [];
state.effectErrors = [];
state.effectWarnings = [];
if (clearInitialValue) {
state.initialValue = undefined;
}
if (forceClear || !shared_1.isValid(state.initialValue)) {
if (shared_1.isArr(state.value)) {
state.value = [];
}
else if (!shared_1.isObj(state.value)) {
state.value = undefined;
}
}
else {
var value = shared_1.clone(state.initialValue);
if (shared_1.isArr(state.value)) {
if (shared_1.isArr(value)) {
state.value = value;
}
else {
state.value = [];
}
}
else if (shared_1.isObj(state.value)) {
if (shared_1.isObj(value)) {
state.value = value;
}
else {
state.value = {};
}
}
else {
state.value = value;
}
}
});
});
if (shared_1.isFn(options.onReset)) {
options.onReset();
}
heart.publish(types_1.LifeCycleTypes.ON_FORM_RESET, state);
if (!validate) return [3, 2];
return [4, formApi.validate(selector, { throwErrors: false })];
case 1:
validateResult = _g.sent();
_g.label = 2;
case 2: return [2, validateResult];
}
});
});
}
function submit(onSubmit) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
if (state.getState(function (state) { return state.submitting; }))
return [2, env.submittingTask];
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT_START, state);
onSubmit = onSubmit || options.onSubmit;
state.setState(function (state) {
state.submitting = true;
});
env.submittingTask = function () { return __awaiter(_this, void 0, void 0, function () {
var validated, errors, payload, values, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_START, state);
return [4, validate('', { throwErrors: false })];
case 1:
_a.sent();
validated = state.getState(function (state) { return ({
errors: state.errors,
warnings: state.warnings
}); });
errors = validated.errors;
if (errors.length) {
state.setState(function (state) {
state.submitting = false;
});
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_FAILED, state);
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT_END, state);
if (shared_1.isFn(options.onValidateFailed)) {
options.onValidateFailed(validated);
}
throw errors;
}
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_SUCCESS, state);
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT, state);
values = state.getState(function (state) { return shared_1.clone(state.values); });
if (!shared_1.isFn(onSubmit)) return [3, 5];
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4, Promise.resolve(onSubmit(values))];
case 3:
payload = _a.sent();
return [3, 5];
case 4:
e_1 = _a.sent();
new Promise(function () {
throw e_1;
});
return [3, 5];
case 5:
state.setState(function (state) {
state.submitting = false;
});
heart.publish(types_1.LifeCycleTypes.ON_FORM_SUBMIT_END, state);
return [2, {
values: values,
validated: validated,
payload: payload
}];
}
});
}); };
return [2, env.submittingTask()];
});
});
}
function validate(path, opts) {
return __awaiter(this, void 0, void 0, function () {
var _a, throwErrors, payload, result, errors, warnings;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = (opts || {}).throwErrors, throwErrors = _a === void 0 ? true : _a;
if (!state.getState(function (state) { return state.validating; })) {
state.setSourceState(function (state) {
state.validating = true;
});
clearTimeout(env.validateTimer);
env.validateTimer = setTimeout(function () {
state.notify();
}, 60);
}
heart.publish(types_1.LifeCycleTypes.ON_FORM_VALIDATE_START, state);
return [4, validator.validate(path, opts)];
case 1:
payload = _b.sent();
clearTimeout(env.validateTimer);
state.setState(function (state) {
state.validating = false;
});
heart.publish(types_1.LifeCycleTypes.ON_FORM_VALIDATE_END, state);
result = {
errors: payload.errors.map(function (item) { return (__assign(__assign({}, item), { name: getFieldState(item.path).name })); }),
warnings: payload.warnings.map(function (item) { return (__assign(__assign({}, item), { name: getFieldState(item.path).name })); })
};
errors = result.errors, warnings = result.warnings;
if (warnings.length) {
console.warn(warnings);
}
if (errors.length > 0) {
if (throwErrors) {
throw result;
}
else {
return [2, result];
}
}
else {
return [2, result];
}
return [2];
}
});
});
}
function setFormState(callback, silent) {
env.leadingStage = true;
state.setState(callback, silent);
env.leadingStage = false;
}
function getFormState(callback) {
return state.getState(callback);
}
function batchRunTaskQueue(field, nodePath) {
for (var index = 0; index < env.taskQueue.length; index++) {
var _a = env.taskQueue[index], pattern = _a.pattern, callbacks = _a.callbacks;
var removed = false;
if (matchStrategy(pattern, nodePath)) {
callbacks.forEach(function (callback) {
field.setState(callback);
});
if (!pattern.isWildMatchPattern && !pattern.isMatchPattern) {
env.taskQueue.splice(index--, 1);
removed = true;
}
}
if (!removed) {
env.taskIndexes[pattern.toString()] = index;
}
else {
delete env.taskIndexes[pattern.toString()];
}
}
}
function setFieldState(path, callback, silent) {
if (!shared_1.isFn(callback))
return;
var matchCount = 0;
var pattern = shared_1.FormPath.getPath(path);
graph.select(pattern, function (field) {
field.setState(callback, silent);
matchCount++;
});
if (matchCount === 0 || pattern.isWildMatchPattern) {
var taskIndex = env.taskIndexes[pattern.toString()];
if (shared_1.isValid(taskIndex)) {
if (env.taskQueue[taskIndex] &&
!env.taskQueue[taskIndex].callbacks.some(function (fn) { return shared_1.isEqual(fn, callback); })) {
env.taskQueue[taskIndex].callbacks.push(callback);
}
}
else {
env.taskIndexes[pattern.toString()] = env.taskQueue.length;
env.taskQueue.push({
pattern: pattern,
callbacks: [callback]
});
}
}
}
function userUpdating(field, fn) {
if (!field)
return;
var nodePath = field.state.path;
if (nodePath)
env.userUpdateFields.push(nodePath);
if (shared_1.isFn(fn)) {
fn();
}
env.userUpdateFields.pop();
}
function setFieldValue(path, value, silent) {
setFieldState(path, function (state) {
state.value = value;
}, silent);
}
function getFieldValue(path) {
return getFieldState(path, function (state) {
return state.value;
});
}
function setFieldInitialValue(path, value, silent) {
setFieldState(path, function (state) {
state.initialValue = value;
}, silent);
}
function getFieldInitialValue(path) {
return getFieldState(path, function (state) {
return state.initialValue;
});
}
function getFieldState(path, callback) {
var field = graph.select(path);
return field && field.getState(callback);
}
function getFormGraph() {
return graph.map(function (node) {
return node.getState();
});
}
function setFormGraph(nodes) {
shared_1.each(nodes, function (node, key) {
var nodeState;
if (graph.exist(key)) {
nodeState = graph.get(key);
nodeState.setSourceState(function (state) {
Object.assign(state, node);
});
}
else {
if (node.displayName === 'VirtualFieldState') {
nodeState = registerVirtualField({
path: key
});
nodeState.setSourceState(function (state) {
Object.assign(state, node);
});
}
else if (node.displayName === 'FieldState') {
nodeState = registerField({
path: key
});
nodeState.setSourceState(function (state) {
Object.assign(state, node);
});
}
}
if (nodeState) {
nodeState.notify(state.getState());
}
});
}
function matchStrategy(pattern, nodePath) {
var matchPattern = shared_1.FormPath.parse(pattern);
var node = graph.get(nodePath);
if (!node)
return false;
return node.getSourceState(function (state) {
return matchPattern.matchAliasGroup(state.name, state.path);
});
}
function hasChanged(target, path) {
if (env.publishing[target ? target.path : ''] === false) {
throw new Error('The watch function must be used synchronously in the subscribe callback.');
}
if (types_1.isFormState(target)) {
return state.hasChanged(path);
}
else if (types_1.isFieldState(target) || types_1.isVirtualFieldState(target)) {
var node = graph.get(target.path);
return node && node.hasChanged(path);
}
else {
throw new Error('Illegal parameter,You must pass the correct state object(FormState/FieldState/VirtualFieldState).');
}
}
var state = new form_1.FormState(options);
var validator = new validator_1.FormValidator(__assign(__assign({}, options), { matchStrategy: matchStrategy }));
var graph = new graph_1.FormGraph({
matchStrategy: matchStrategy
});
var applyWithScheduler = shared_1.scheduler(options.validateConcurrentTimeMS);
var formApi = {
submit: submit,
reset: reset,
hasChanged: hasChanged,
clearErrors: clearErrors,
validate: validate,
setFormState: setFormState,
getFormState: getFormState,
setFieldState: setFieldState,
getFieldState: getFieldState,
registerField: registerField,
registerVirtualField: registerVirtualField,
createMutators: createMutators,
getFormGraph: getFormGraph,
setFormGraph: setFormGraph,
setFieldValue: setFieldValue,
unsafe_do_not_use_transform_data_path: transformDataPath,
getFieldValue: getFieldValue,
setFieldInitialValue: setFieldInitialValue,
getFieldInitialValue: getFieldInitialValue,
subscribe: function (callback) {
return heart.subscribe(callback);
},
unsubscribe: function (id) {
heart.unsubscribe(id);
},
notify: function (type, payload) {
heart.publish(type, payload);
}
};
var heart = new lifecycle_1.FormHeart(__assign(__assign({}, options), { context: formApi, beforeNotify: function (payload) {
env.publishing[payload.path || ''] = true;
}, afterNotify: function (payload) {
env.publishing[payload.path || ''] = false;
} }));
var env = {
validateTimer: null,
graphChangeTimer: null,
leadingStage: false,
publishing: {},
taskQueue: [],
userUpdateFields: [],
taskIndexes: {},
removeNodes: {},
hiddenPendingFields: {},
lastShownStates: {},
submittingTask: undefined
};
heart.publish(types_1.LifeCycleTypes.ON_FORM_WILL_INIT, state);
state.subscription = {
notify: onFormChange
};
graph.appendNode('', state);
state.setState(function (state) {
state.initialized = true;
});
graph.subscribe(onGraphChange);
return formApi;
}
exports.createForm = createForm;
exports.registerValidationFormats = validator_1.FormValidator.registerFormats;
exports.registerValidationRules = validator_1.FormValidator.registerRules;
exports.registerValidationMTEngine = validator_1.FormValidator.registerMTEngine;
exports.default = createForm;
module.exports = require('@formily/core');

8

package.json
{
"name": "@uform/core",
"version": "1.0.1",
"version": "1.0.2",
"license": "MIT",

@@ -29,5 +29,3 @@ "main": "lib",

"dependencies": {
"@uform/shared": "^1.0.1",
"@uform/validator": "^1.0.1",
"immer": "^3.2.0"
"@formily/core": "^1.0.0"
},

@@ -37,3 +35,3 @@ "publishConfig": {

},
"gitHead": "46762a5ba39888e079cf6382c26a66bcc3810d5d"
"gitHead": "2ab41cefdf4ff449bb597d5c540c1e053a5f6fb1"
}

@@ -1,1296 +0,1 @@

import {
isFn,
isEqual,
toArr,
isNum,
isArr,
clone,
isValid,
FormPath,
FormPathPattern,
each,
isObj,
scheduler
} from '@uform/shared'
import {
FormValidator,
setValidationLanguage,
setValidationLocale
} from '@uform/validator'
import { FormHeart } from './shared/lifecycle'
import { FormGraph } from './shared/graph'
import { FormState } from './state/form'
import { VirtualFieldState } from './state/virtual-field'
import { FieldState } from './state/field'
import {
IFormState,
IFieldState,
IVirtualFieldState,
IFormCreatorOptions,
IFieldStateProps,
IVirtualFieldStateProps,
IForm,
IFormSubmitResult,
IFormValidateResult,
IFormResetOptions,
IField,
IVirtualField,
isField,
FormHeartSubscriber,
LifeCycleTypes,
isVirtualField,
isFormState,
isFieldState,
isVirtualFieldState,
IFormExtendedValidateFieldOptions
} from './types'
export * from './shared/lifecycle'
export * from './types'
export function createForm<FieldProps, VirtualFieldProps>(
options: IFormCreatorOptions = {}
): IForm {
function onGraphChange({ type, payload }) {
heart.publish(LifeCycleTypes.ON_FORM_GRAPH_CHANGE, graph)
if (type === 'GRAPH_NODE_WILL_UNMOUNT') {
validator.unregister(payload.path.toString())
}
}
function syncFieldValues(state: IFieldState) {
const dataPath = FormPath.parse(state.name)
const parent = graph.getLatestParent(state.path)
const parentValue = getFormValuesIn(parent.path)
const value = getFormValuesIn(state.name)
/**
* https://github.com/alibaba/uform/issues/267 dynamic remove node
*/
let removed = false
if (isArr(parentValue) && !dataPath.existIn(parentValue, parent.path)) {
if (
!parent.path
.getNearestChildPathBy(state.path)
.existIn(parentValue, parent.path)
) {
graph.remove(state.path)
removed = true
}
} else {
each(env.removeNodes, (_, name) => {
if (dataPath.includes(name)) {
graph.remove(state.path)
delete env.removeNodes[name]
removed = true
}
})
}
if (removed) return
if (!isEqual(value, state.value)) {
state.value = value
}
}
function syncFieldIntialValues(state: IFieldState) {
const initialValue = getFormInitialValuesIn(state.name)
if (!isEqual(initialValue, state.initialValue)) {
state.initialValue = initialValue
if (!isValid(state.value)) {
state.value = initialValue
} else if (
/array/gi.test(state.dataType) &&
state.value &&
state.value.length === 0
) {
state.value = initialValue
}
}
}
function onFormChange(published: IFormState) {
heart.publish(LifeCycleTypes.ON_FORM_CHANGE, state)
const valuesChanged = state.isDirty('values')
const initialValuesChanged = state.isDirty('initialValues')
const unmountedChanged = state.isDirty('unmounted')
const mountedChanged = state.isDirty('mounted')
const initializedChanged = state.isDirty('initialized')
const editableChanged = state.isDirty('editable')
if (valuesChanged || initialValuesChanged) {
const updateFields = (field: IField | IVirtualField) => {
if (isField(field)) {
field.setState(state => {
if (state.visible || state.unmounted) {
if (valuesChanged) {
syncFieldValues(state)
}
if (initialValuesChanged) {
syncFieldIntialValues(state)
}
} else {
//缓存变化,等字段重新显示的时候再执行
if (valuesChanged) {
env.hiddenPendingFields[state.name] =
env.hiddenPendingFields[state.name] || {}
env.hiddenPendingFields[state.name].values = true
}
if (initialValuesChanged) {
env.hiddenPendingFields[state.name] =
env.hiddenPendingFields[state.name] || {}
env.hiddenPendingFields[state.name].initialValues = true
}
}
})
}
}
if (valuesChanged || initialValuesChanged) {
if (!env.leadingStage) {
const userUpdateFieldPath =
env.userUpdateFields[env.userUpdateFields.length - 1]
/*
* 考虑初始化的时候还没生成节点树
* 两种数据同步策略,
* 1. 精确更新的时候(mutators/setFieldState),只遍历父节点与子节点,同时父节点静默处理,子节点通知渲染
* 2. setFormState批量更新的时候,是会遍历所有节点,同时所有节点只要有变化就会被通知
*/
if (userUpdateFieldPath && graph.get(userUpdateFieldPath)) {
graph.eachParentAndChildren(userUpdateFieldPath, updateFields)
} else {
graph.eachChildren(updateFields)
}
} else {
graph.eachChildren(updateFields)
}
}
if (valuesChanged) {
if (isFn(options.onChange)) {
options.onChange(clone(published.values))
}
heart.publish(LifeCycleTypes.ON_FORM_VALUES_CHANGE, state)
}
if (initialValuesChanged) {
heart.publish(LifeCycleTypes.ON_FORM_INITIAL_VALUES_CHANGE, state)
}
}
if (editableChanged) {
graph.eachChildren((field: IField | IVirtualField) => {
if (isField(field)) {
field.setState(state => {
state.formEditable = published.editable
})
}
})
}
if (unmountedChanged && published.unmounted) {
heart.publish(LifeCycleTypes.ON_FORM_UNMOUNT, state)
}
if (mountedChanged && published.mounted) {
heart.publish(LifeCycleTypes.ON_FORM_MOUNT, state)
}
if (initializedChanged) {
heart.publish(LifeCycleTypes.ON_FORM_INIT, state)
}
}
function updateRecoverableShownState(
parentState:
| IVirtualFieldState<VirtualFieldProps>
| IFieldState<FieldProps>,
childState: IVirtualFieldState<VirtualFieldProps> | IFieldState<FieldProps>,
name: 'visible' | 'display'
) {
const lastShownState = env.lastShownStates[childState.path]
const lastStateValue = childState[name]
if (parentState[name] && lastShownState && lastShownState[name] === false) {
childState[name] = false
delete lastShownState[name]
if (
!lastShownState.hasOwnProperty('visible') &&
!lastShownState.hasOwnProperty('display')
) {
delete env.lastShownStates[childState.path]
}
} else {
childState[name] = parentState[name]
}
if (!parentState[name] && !lastStateValue) {
if (!lastShownState) {
env.lastShownStates[childState.path] = {}
}
env.lastShownStates[childState.path][name] = false
}
}
function onFieldChange({ field, path }) {
return (published: IFieldState<FieldProps>) => {
const valueChanged = field.isDirty('value')
const initialValueChanged = field.isDirty('initialValue')
const visibleChanged = field.isDirty('visible')
const displayChanged = field.isDirty('display')
const unmountedChanged = field.isDirty('unmounted')
const mountedChanged = field.isDirty('mounted')
const initializedChanged = field.isDirty('initialized')
const warningsChanged = field.isDirty('warnings')
const errorsChanged = field.isDirty('errors')
const userUpdateFieldPath =
env.userUpdateFields[env.userUpdateFields.length - 1]
const syncField = () => {
if (env.hiddenPendingFields[published.name]) {
field.setState((state: IFieldState) => {
if (env.hiddenPendingFields[state.name].values) {
syncFieldValues(state)
}
if (env.hiddenPendingFields[state.name].initialValues) {
syncFieldIntialValues(state)
}
delete env.hiddenPendingFields[state.name]
})
}
}
const notifyFormValuesChange = () => {
if (isFn(options.onChange)) {
options.onChange(state.getSourceState(state => clone(state.values)))
}
heart.publish(LifeCycleTypes.ON_FORM_VALUES_CHANGE, state)
}
if (initializedChanged) {
heart.publish(LifeCycleTypes.ON_FIELD_INIT, field)
const isEmptyValue = !isValid(published.value)
const isEmptyInitialValue = !isValid(published.initialValue)
if (isEmptyValue || isEmptyInitialValue) {
field.setSourceState((state: IFieldState<FieldProps>) => {
if (isEmptyValue) state.value = getFormValuesIn(state.name)
if (isEmptyInitialValue)
state.initialValue = getFormInitialValuesIn(state.name)
})
}
}
const wasHidden =
published.visible == false || published.unmounted === true
if (valueChanged) {
if (!wasHidden) {
userUpdating(field, () => {
setFormValuesIn(path, published.value)
})
}
heart.publish(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, field)
}
if (initialValueChanged) {
if (!wasHidden) {
setFormInitialValuesIn(path, published.initialValue)
}
heart.publish(LifeCycleTypes.ON_FIELD_INITIAL_VALUE_CHANGE, field)
}
if (displayChanged || visibleChanged) {
if (visibleChanged) {
userUpdating(field, () => {
if (!published.visible) {
deleteFormValuesIn(path, true)
//考虑到隐藏删值,不应该同步子树,但是需要触发表单变化事件
notifyFormValuesChange()
} else {
setFormValuesIn(path, published.value)
syncField()
}
})
}
graph.eachChildren(path, childState => {
childState.setState((state: IFieldState<FieldProps>) => {
if (visibleChanged) {
updateRecoverableShownState(published, state, 'visible')
}
if (displayChanged) {
updateRecoverableShownState(published, state, 'display')
}
}, true)
})
}
if (
unmountedChanged &&
(published.display !== false || published.visible === false)
) {
userUpdating(field, () => {
if (published.unmounted) {
deleteFormValuesIn(path, true)
//考虑到隐藏删值,不应该同步子树,但是需要触发表单变化事件
notifyFormValuesChange()
} else {
setFormValuesIn(path, published.value)
syncField()
}
})
heart.publish(LifeCycleTypes.ON_FIELD_UNMOUNT, field)
}
if (mountedChanged && published.mounted) {
heart.publish(LifeCycleTypes.ON_FIELD_MOUNT, field)
}
if (errorsChanged) {
syncFormMessages('errors', published)
}
if (warningsChanged) {
syncFormMessages('warnings', published)
}
heart.publish(LifeCycleTypes.ON_FIELD_CHANGE, field)
if (userUpdateFieldPath && !env.leadingStage) {
if (FormPath.parse(path).match(userUpdateFieldPath)) {
return
}
if (FormPath.parse(userUpdateFieldPath).includes(path)) {
return false
}
}
}
}
function onVirtualFieldChange({ field, path }) {
return (published: IVirtualFieldState<VirtualFieldProps>) => {
const visibleChanged = field.isDirty('visible')
const displayChanged = field.isDirty('display')
const mountedChanged = field.isDirty('mounted')
const initializedChanged = field.isDirty('initialized')
if (initializedChanged) {
heart.publish(LifeCycleTypes.ON_FIELD_INIT, field)
}
if (visibleChanged || displayChanged) {
graph.eachChildren(path, childState => {
childState.setState(
(state: IVirtualFieldState<VirtualFieldProps>) => {
if (visibleChanged) {
updateRecoverableShownState(published, state, 'visible')
}
if (displayChanged) {
updateRecoverableShownState(published, state, 'display')
}
},
true
)
})
}
if (mountedChanged && published.mounted) {
heart.publish(LifeCycleTypes.ON_FIELD_MOUNT, field)
}
heart.publish(LifeCycleTypes.ON_FIELD_CHANGE, field)
}
}
function registerVirtualField({
name,
path,
props,
display,
visible,
computeState,
useDirty
}: IVirtualFieldStateProps): IVirtualField {
let nodePath = FormPath.parse(path || name)
let dataPath = transformDataPath(nodePath)
let field: IVirtualField
const createField = (field?: IVirtualField) => {
const alreadyHaveField = !!field
field =
field ||
new VirtualFieldState({
nodePath,
dataPath,
computeState,
useDirty: isValid(useDirty) ? useDirty : options.useDirty
})
field.subscription = {
notify: onVirtualFieldChange({ field, path: nodePath })
}
heart.publish(LifeCycleTypes.ON_FIELD_WILL_INIT, field)
if (!alreadyHaveField) {
graph.appendNode(nodePath, field)
}
field.batch(() => {
field.setState((state: IVirtualFieldState<VirtualFieldProps>) => {
state.initialized = true
state.props = props
if (isValid(visible)) {
state.visible = visible
}
if (isValid(display)) {
state.display = display
}
})
batchRunTaskQueue(field, nodePath)
})
return field
}
if (graph.exist(nodePath)) {
field = graph.get(nodePath)
//field = createField(field) 如果重置会导致#565的问题,目前还没想清楚不重置会有啥问题
if (isField(field)) {
graph.replace(nodePath, field)
}
} else {
field = createField()
}
return field
}
function registerField({
path,
name,
value,
initialValue,
required,
rules,
editable,
visible,
display,
computeState,
dataType,
useDirty,
props
}: Exclude<IFieldStateProps, 'dataPath' | 'nodePath'>): IField {
let field: IField
let nodePath = FormPath.parse(path || name)
let dataPath = transformDataPath(nodePath)
const createField = (field?: IField) => {
const alreadyHaveField = !!field
field =
field ||
new FieldState({
nodePath,
dataPath,
computeState,
dataType,
useDirty: isValid(useDirty) ? useDirty : options.useDirty
})
field.subscription = {
notify: onFieldChange({ field, path: nodePath })
}
heart.publish(LifeCycleTypes.ON_FIELD_WILL_INIT, field)
if (!alreadyHaveField) {
graph.appendNode(nodePath, field)
}
field.batch(() => {
field.setState((state: IFieldState<FieldProps>) => {
const formValue = getFormValuesIn(dataPath)
const formInitialValue = getFormInitialValuesIn(dataPath)
if (isValid(value)) {
// value > formValue > initialValue
state.value = value
} else {
state.value = existFormValuesIn(dataPath) ? formValue : initialValue
}
// initialValue > formInitialValue
state.initialValue = isValid(initialValue)
? initialValue
: formInitialValue
if (isValid(visible)) {
state.visible = visible
}
if (isValid(display)) {
state.display = display
}
if (isValid(props)) {
state.props = props
}
if (isValid(required)) {
state.required = required
}
if (isValid(rules)) {
state.rules = rules
}
if (isValid(editable)) {
state.selfEditable = editable
}
if (isValid(options.editable)) {
state.formEditable = options.editable
}
state.initialized = true
})
batchRunTaskQueue(field, nodePath)
})
validator.register(nodePath, validate => {
const {
value,
rules,
editable,
visible,
unmounted,
display
} = field.getState()
// 不需要校验的情况有: 非编辑态(editable),已销毁(unmounted), 逻辑上不可见(visible)
if (
editable === false ||
visible === false ||
unmounted === true ||
display === false
)
return validate(value, [])
clearTimeout((field as any).validateTimer)
;(field as any).validateTimer = setTimeout(() => {
field.setState(state => {
state.validating = true
})
}, 60)
heart.publish(LifeCycleTypes.ON_FIELD_VALIDATE_START, field)
return validate(value, rules).then(({ errors, warnings }) => {
clearTimeout((field as any).validateTimer)
return new Promise(resolve => {
const syncState = () => {
field.setState((state: IFieldState<FieldProps>) => {
state.validating = false
state.ruleErrors = errors
state.ruleWarnings = warnings
})
heart.publish(LifeCycleTypes.ON_FIELD_VALIDATE_END, field)
resolve({ errors, warnings })
}
if (graph.size < 100) {
syncState()
} else {
applyWithScheduler(syncState)
}
})
})
})
return field
}
if (graph.exist(nodePath)) {
field = graph.get(nodePath)
//field = createField(field) 如果重置会导致#565的问题,目前还没想清楚不重置会有啥问题
if (isVirtualField(field)) {
graph.replace(nodePath, field)
}
} else {
field = createField()
}
return field
}
//实时同步Form Messages
function syncFormMessages(type: string, fieldState: IFieldState) {
const { name, path } = fieldState
const messages = fieldState[type]
state.setSourceState(state => {
let foundField = false
state[type] = state[type] || []
state[type] = state[type].reduce((buf: any, item: any) => {
if (item.path === path) {
foundField = true
return messages.length ? buf.concat({ path, messages }) : buf
} else {
return buf.concat(item)
}
}, [])
if (!foundField && messages.length) {
state[type].push({
name,
path,
messages
})
}
if (state.errors.length) {
state.invalid = true
state.valid = false
} else {
state.invalid = false
state.valid = true
}
})
}
function transformDataPath(path: FormPathPattern) {
const newPath = FormPath.getPath(path)
return newPath.reduce((path: FormPath, key: string, index: number) => {
if (index >= newPath.length - 1) return path.concat([key])
const realPath = newPath.slice(0, index + 1)
const dataPath = path.concat([key])
const selected = graph.get(realPath)
if (isVirtualField(selected)) {
return path
}
return dataPath
}, FormPath.getPath(''))
}
function setFormIn(
path: FormPathPattern,
key: string,
value: any,
silent?: boolean
) {
state.setState(state => {
FormPath.setIn(state[key], transformDataPath(path), value)
}, silent)
}
function deleteFormIn(path: FormPathPattern, key: string, silent?: boolean) {
state.setState(state => {
FormPath.deleteIn(state[key], transformDataPath(path))
}, silent)
}
function deleteFormValuesIn(path: FormPathPattern, silent?: boolean) {
deleteFormIn(path, 'values', silent)
}
function setFormValuesIn(
path: FormPathPattern,
value?: any,
silent?: boolean
) {
return setFormIn(path, 'values', value, silent)
}
function setFormInitialValuesIn(
path: FormPathPattern,
value?: any,
silent?: boolean
) {
return setFormIn(path, 'initialValues', value, silent)
}
function getFormIn(path: FormPathPattern, key?: string) {
return state.getState(state =>
FormPath.getIn(state[key], transformDataPath(path))
)
}
function getFormValuesIn(path: FormPathPattern) {
return getFormIn(path, 'values')
}
function existFormValuesIn(path: FormPathPattern) {
return state.getState(state =>
FormPath.existIn(state.values, transformDataPath(path))
)
}
function getFormInitialValuesIn(path: FormPathPattern) {
return getFormIn(path, 'initialValues')
}
function createMutators(field: IField) {
if (!isField(field)) {
throw new Error(
'The `createMutators` can only accept FieldState instance.'
)
}
function setValue(...values: any[]) {
field.setState((state: IFieldState<FieldProps>) => {
state.value = values[0]
state.values = values
})
heart.publish(LifeCycleTypes.ON_FIELD_INPUT_CHANGE, field)
heart.publish(LifeCycleTypes.ON_FORM_INPUT_CHANGE, state)
}
function removeValue(key: string | number) {
const nodePath = field.getSourceState(state => state.path)
if (isValid(key)) {
const childNodePath = FormPath.parse(nodePath).concat(key)
env.userUpdateFields.push(nodePath)
env.removeNodes[childNodePath.toString()] = true
deleteFormValuesIn(childNodePath)
field.notify(field.getState())
env.userUpdateFields.pop()
} else {
const parent = graph.selectParent(nodePath)
env.removeNodes[nodePath.toString()] = true
const parentNodePath =
parent && parent.getSourceState(state => state.path)
if (parentNodePath) {
env.userUpdateFields.push(parentNodePath)
} else {
env.userUpdateFields.push(nodePath)
}
deleteFormValuesIn(nodePath)
if (parent) {
parent.notify(parent.getState())
}
env.userUpdateFields.pop()
}
heart.publish(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, field)
heart.publish(LifeCycleTypes.ON_FIELD_INPUT_CHANGE, field)
heart.publish(LifeCycleTypes.ON_FORM_INPUT_CHANGE, state)
}
function getValue() {
return field.getSourceState(state => state.value)
}
return {
change(...values: any[]) {
setValue(...values)
return values[0]
},
focus() {
field.setState((state: IFieldState<FieldProps>) => {
state.active = true
})
},
blur() {
field.setState((state: IFieldState<FieldProps>) => {
state.active = false
state.visited = true
})
},
push(value?: any) {
const arr = toArr(getValue()).slice()
arr.push(value)
setValue(arr)
return arr
},
pop() {
const arr = toArr(getValue()).slice()
arr.pop()
setValue(arr)
return arr
},
insert(index: number, value: any) {
const arr = toArr(getValue()).slice()
arr.splice(index, 0, value)
setValue(arr)
return arr
},
remove(index?: number | string) {
let val = getValue()
if (isNum(index) && isArr(val)) {
val = [].concat(val)
val.splice(index, 1)
setValue(val)
} else {
removeValue(index)
}
},
exist(index?: number | string) {
const newPath = field.getSourceState(state =>
FormPath.parse(state.path)
)
let val = getValue()
return (isValid(index) ? newPath.concat(index) : newPath).existIn(
val,
newPath
)
},
unshift(value: any) {
const arr = toArr(getValue()).slice()
arr.unshift(value)
setValue(arr)
return arr
},
shift() {
const arr = toArr(getValue()).slice()
arr.shift()
setValue(arr)
return arr
},
move($from: number, $to: number) {
const arr = toArr(getValue()).slice()
const item = arr[$from]
arr.splice($from, 1)
arr.splice($to, 0, item)
setValue(arr)
return arr
},
moveUp(index: number) {
const arr = toArr(getValue()).slice()
const item = arr[index]
const len = arr.length
arr.splice(index, 1)
arr.splice(index - 1 < 0 ? len - 1 : index - 1, 0, item)
setValue(arr)
return arr
},
moveDown(index: number) {
const arr = toArr(getValue()).slice()
const item = arr[index]
const len = arr.length
arr.splice(index, 1)
arr.splice(index + 1 > len ? 0 : index + 1, 0, item)
setValue(arr)
return arr
},
validate(opts?: IFormExtendedValidateFieldOptions) {
return validate(
field.getSourceState(state => state.path),
opts
)
}
}
}
function clearErrors(pattern: FormPathPattern = '*') {
// 1. 指定路径或全部子路径清理
graph.eachChildren('', pattern, field => {
if (isField(field)) {
field.setState(state => {
state.ruleErrors = []
state.ruleWarnings = []
state.effectErrors = []
state.effectWarnings = []
})
}
})
}
async function reset({
selector = '*',
forceClear = false,
validate = true,
clearInitialValue = false
}: IFormResetOptions = {}): Promise<void | IFormValidateResult> {
graph.eachChildren('', selector, field => {
field.setState((state: IFieldState<FieldProps>) => {
state.modified = false
state.ruleErrors = []
state.ruleWarnings = []
state.effectErrors = []
state.effectWarnings = []
if (clearInitialValue) {
state.initialValue = undefined
}
// forceClear仅对设置initialValues的情况下有意义
if (forceClear || !isValid(state.initialValue)) {
if (isArr(state.value)) {
state.value = []
} else if (!isObj(state.value)) {
state.value = undefined
}
} else {
const value = clone(state.initialValue)
if (isArr(state.value)) {
if (isArr(value)) {
state.value = value
} else {
state.value = []
}
} else if (isObj(state.value)) {
if (isObj(value)) {
state.value = value
} else {
state.value = {}
}
} else {
state.value = value
}
}
})
})
if (isFn(options.onReset)) {
options.onReset()
}
heart.publish(LifeCycleTypes.ON_FORM_RESET, state)
let validateResult: void | IFormValidateResult
if (validate) {
validateResult = await formApi.validate(selector, { throwErrors: false })
}
return validateResult
}
async function submit(
onSubmit?: (values: IFormState['values']) => any | Promise<any>
): Promise<IFormSubmitResult> {
// 重复提交,返回前一次的promise
if (state.getState(state => state.submitting)) return env.submittingTask
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT_START, state)
onSubmit = onSubmit || options.onSubmit
state.setState(state => {
state.submitting = true
})
env.submittingTask = async () => {
// 增加onFormSubmitValidateStart来明确submit引起的校验开始了
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_START, state)
await validate('', { throwErrors: false })
const validated: IFormValidateResult = state.getState(state => ({
errors: state.errors,
warnings: state.warnings
}))
const { errors } = validated
// 校验失败
if (errors.length) {
// 由于校验失败导致submit退出
state.setState(state => {
state.submitting = false
})
// 增加onFormSubmitValidateFailed来明确结束submit的类型
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_FAILED, state)
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT_END, state)
if (isFn(options.onValidateFailed)) {
options.onValidateFailed(validated)
}
throw errors
}
// 增加onFormSubmitValidateSucces来明确submit引起的校验最终的结果
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT_VALIDATE_SUCCESS, state)
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT, state)
let payload,
values = state.getState(state => clone(state.values))
if (isFn(onSubmit)) {
try {
payload = await Promise.resolve(onSubmit(values))
} catch (e) {
new Promise(() => {
throw e
})
}
}
state.setState(state => {
state.submitting = false
})
heart.publish(LifeCycleTypes.ON_FORM_SUBMIT_END, state)
return {
values,
validated,
payload
}
}
return env.submittingTask()
}
async function validate(
path?: FormPathPattern,
opts?: IFormExtendedValidateFieldOptions
): Promise<IFormValidateResult> {
const { throwErrors = true } = opts || {}
if (!state.getState(state => state.validating)) {
state.setSourceState(state => {
state.validating = true
})
// 渲染优化
clearTimeout(env.validateTimer)
env.validateTimer = setTimeout(() => {
state.notify()
}, 60)
}
heart.publish(LifeCycleTypes.ON_FORM_VALIDATE_START, state)
const payload = await validator.validate(path, opts)
clearTimeout(env.validateTimer)
state.setState(state => {
state.validating = false
})
heart.publish(LifeCycleTypes.ON_FORM_VALIDATE_END, state)
// 增加name透出真实路径,和0.x保持一致
const result = {
errors: payload.errors.map(item => ({
...item,
name: getFieldState(item.path).name
})),
warnings: payload.warnings.map(item => ({
...item,
name: getFieldState(item.path).name
}))
}
const { errors, warnings } = result
// 打印warnings日志从submit挪到这里
if (warnings.length) {
console.warn(warnings)
}
if (errors.length > 0) {
if (throwErrors) {
throw result
} else {
return result
}
} else {
return result
}
}
function setFormState(
callback?: (state: IFormState) => any,
silent?: boolean
) {
env.leadingStage = true
state.setState(callback, silent)
env.leadingStage = false
}
function getFormState(callback?: (state: IFormState) => any) {
return state.getState(callback)
}
function batchRunTaskQueue(
field: IField | IVirtualField,
nodePath: FormPath
) {
for (let index = 0; index < env.taskQueue.length; index++) {
const { pattern, callbacks } = env.taskQueue[index]
let removed = false
if (matchStrategy(pattern, nodePath)) {
callbacks.forEach(callback => {
field.setState(callback)
})
if (!pattern.isWildMatchPattern && !pattern.isMatchPattern) {
env.taskQueue.splice(index--, 1)
removed = true
}
}
if (!removed) {
env.taskIndexes[pattern.toString()] = index
} else {
delete env.taskIndexes[pattern.toString()]
}
}
}
function setFieldState(
path: FormPathPattern,
callback?: (state: IFieldState<FieldProps>) => void,
silent?: boolean
) {
if (!isFn(callback)) return
let matchCount = 0
let pattern = FormPath.getPath(path)
graph.select(pattern, field => {
field.setState(callback, silent)
matchCount++
})
if (matchCount === 0 || pattern.isWildMatchPattern) {
let taskIndex = env.taskIndexes[pattern.toString()]
if (isValid(taskIndex)) {
if (
env.taskQueue[taskIndex] &&
!env.taskQueue[taskIndex].callbacks.some(fn => isEqual(fn, callback))
) {
env.taskQueue[taskIndex].callbacks.push(callback)
}
} else {
env.taskIndexes[pattern.toString()] = env.taskQueue.length
env.taskQueue.push({
pattern,
callbacks: [callback]
})
}
}
}
function userUpdating(field: IField | IVirtualField, fn?: () => void) {
if (!field) return
const nodePath = field.state.path
if (nodePath) env.userUpdateFields.push(nodePath)
if (isFn(fn)) {
fn()
}
env.userUpdateFields.pop()
}
function setFieldValue(path: FormPathPattern, value?: any, silent?: boolean) {
setFieldState(
path,
state => {
state.value = value
},
silent
)
}
function getFieldValue(path?: FormPathPattern) {
return getFieldState(path, state => {
return state.value
})
}
function setFieldInitialValue(
path?: FormPathPattern,
value?: any,
silent?: boolean
) {
setFieldState(
path,
state => {
state.initialValue = value
},
silent
)
}
function getFieldInitialValue(path?: FormPathPattern) {
return getFieldState(path, state => {
return state.initialValue
})
}
function getFieldState(
path: FormPathPattern,
callback?: (state: IFieldState<FieldProps>) => any
) {
const field = graph.select(path)
return field && field.getState(callback)
}
function getFormGraph() {
return graph.map(node => {
return node.getState()
})
}
function setFormGraph(nodes: {}) {
each(
nodes,
(
node: IFieldState<FieldProps> | IVirtualFieldState<VirtualFieldProps>,
key
) => {
let nodeState: any
if (graph.exist(key)) {
nodeState = graph.get(key)
nodeState.setSourceState(state => {
Object.assign(state, node)
})
} else {
if (node.displayName === 'VirtualFieldState') {
nodeState = registerVirtualField({
path: key
})
nodeState.setSourceState(state => {
Object.assign(state, node)
})
} else if (node.displayName === 'FieldState') {
nodeState = registerField({
path: key
})
nodeState.setSourceState(state => {
Object.assign(state, node)
})
}
}
if (nodeState) {
nodeState.notify(state.getState())
}
}
)
}
function matchStrategy(pattern: FormPathPattern, nodePath: FormPathPattern) {
const matchPattern = FormPath.parse(pattern)
const node = graph.get(nodePath)
if (!node) return false
return node.getSourceState(state =>
matchPattern.matchAliasGroup(state.name, state.path)
)
}
//在subscribe中必须同步使用,否则会监听不到变化
function hasChanged(target: any, path: FormPathPattern): boolean {
if (env.publishing[target ? target.path : ''] === false) {
throw new Error(
'The watch function must be used synchronously in the subscribe callback.'
)
}
if (isFormState(target)) {
return state.hasChanged(path)
} else if (isFieldState(target) || isVirtualFieldState(target)) {
const node = graph.get(target.path)
return node && node.hasChanged(path)
} else {
throw new Error(
'Illegal parameter,You must pass the correct state object(FormState/FieldState/VirtualFieldState).'
)
}
}
const state = new FormState(options)
const validator = new FormValidator({
...options,
matchStrategy
})
const graph = new FormGraph({
matchStrategy
})
const applyWithScheduler = scheduler(options.validateConcurrentTimeMS)
const formApi = {
submit,
reset,
hasChanged,
clearErrors,
validate,
setFormState,
getFormState,
setFieldState,
getFieldState,
registerField,
registerVirtualField,
createMutators,
getFormGraph,
setFormGraph,
setFieldValue,
unsafe_do_not_use_transform_data_path: transformDataPath, //eslint-disable-line
getFieldValue,
setFieldInitialValue,
getFieldInitialValue,
subscribe: (callback?: FormHeartSubscriber) => {
return heart.subscribe(callback)
},
unsubscribe: (id: number) => {
heart.unsubscribe(id)
},
notify: <T>(type: string, payload: T) => {
heart.publish(type, payload)
}
}
const heart = new FormHeart({
...options,
context: formApi,
beforeNotify: payload => {
env.publishing[payload.path || ''] = true
},
afterNotify: payload => {
env.publishing[payload.path || ''] = false
}
})
const env = {
validateTimer: null,
graphChangeTimer: null,
leadingStage: false,
publishing: {},
taskQueue: [],
userUpdateFields: [],
taskIndexes: {},
removeNodes: {},
hiddenPendingFields: {},
lastShownStates: {},
submittingTask: undefined
}
heart.publish(LifeCycleTypes.ON_FORM_WILL_INIT, state)
state.subscription = {
notify: onFormChange
}
graph.appendNode('', state)
state.setState((state: IFormState) => {
state.initialized = true
})
graph.subscribe(onGraphChange)
return formApi
}
export const registerValidationFormats = FormValidator.registerFormats
export const registerValidationRules = FormValidator.registerRules
export const registerValidationMTEngine = FormValidator.registerMTEngine
export {
setValidationLanguage,
setValidationLocale,
FormPath,
FormPathPattern,
FormGraph
}
export default createForm
module.exports = require('@formily/core')
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc