zent
Version:
一套前端设计语言和基于React的实现
239 lines (238 loc) • 11 kB
JavaScript
import { __assign, __awaiter, __extends, __generator, __rest } from "tslib";
import { jsx as _jsx } from "react/jsx-runtime";
import cx from 'classnames';
import { Component, createRef } from 'react';
import { FormProvider, useField, useFieldArray, useFieldSet, field, set, array, form, FieldValue, FieldSetValue, useFieldArrayChildModels, ValidateOption, createAsyncValidator, isAsyncValidator, useFieldValue, FieldValid, useFieldValid, useModelValid, useModelValue, useNamedChildModel, } from './formulr';
import memorize from '../utils/memorize-one';
import { FormChildrenContext, } from './context';
import { useForm, useFormValue, useFormValid } from './ZentForm';
import { smoothScroll } from '../utils/scroll';
import { CombineErrors } from './CombineErrors';
import { ValidateOccasion, TouchWhen } from './shared';
import { Disabled } from '../disabled';
import getScrollPosition from '../utils/dom/getScollPosition';
import isPromise from '../utils/isPromise';
export { isViewDrivenProps, ValidateOccasion, } from './shared';
function makeChildrenContext(children) {
return {
children: children,
};
}
var Form = (function (_super) {
__extends(Form, _super);
function Form() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.formRef = createRef();
_this.children = [];
_this.getChildrenContext = memorize(makeChildrenContext);
_this.submitSubscription = null;
_this.resetSubscription = null;
_this.onSubmit = function (e) {
e.preventDefault();
e.stopPropagation();
_this.props.form.submit(e);
};
_this.onReset = function (e) {
e.preventDefault();
e.stopPropagation();
_this.props.form.reset(e);
};
_this.onKeyDown = function (e) {
var _a = _this.props, onKeyDown = _a.onKeyDown, _b = _a.disableEnterSubmit, disableEnterSubmit = _b === void 0 ? true : _b;
if (disableEnterSubmit &&
e.key === 'Enter' &&
e.target.tagName === 'INPUT') {
e.preventDefault();
e.stopPropagation();
}
onKeyDown && onKeyDown(e);
};
_this.submitListener = function (e) {
_this.submit(e);
};
_this.resetListener = function (e) {
_this.reset(e);
};
return _this;
}
Form.prototype.reset = function (e) {
var _a = this.props, form = _a.form, onReset = _a.onReset;
form.resetValue();
onReset === null || onReset === void 0 ? void 0 : onReset(e);
};
Form.prototype.submit = function (e) {
return __awaiter(this, void 0, void 0, function () {
var _a, onSubmit, form, onSubmitFail, onSubmitSuccess, scrollToError, success, fail, error_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this.props, onSubmit = _a.onSubmit, form = _a.form, onSubmitFail = _a.onSubmitFail, onSubmitSuccess = _a.onSubmitSuccess, scrollToError = _a.scrollToError;
if (!onSubmit) {
return [2];
}
success = function () {
onSubmitSuccess && onSubmitSuccess();
form.submitSuccess();
};
fail = function (error) {
onSubmitFail && onSubmitFail(error);
form.submitError();
};
_b.label = 1;
case 1:
_b.trys.push([1, 4, , 5]);
form.submitStart();
return [4, form.validate(ValidateOption.IncludeAsync |
ValidateOption.IncludeChildrenRecursively |
ValidateOption.IncludeUntouched)];
case 2:
_b.sent();
if (!form.isValid()) {
scrollToError && this.scrollToFirstError();
fail(new FormValidationError('Form validation failed'));
return [2];
}
return [4, onSubmit(form, e)];
case 3:
_b.sent();
success();
return [3, 5];
case 4:
error_1 = _b.sent();
fail(error_1);
return [3, 5];
case 5: return [2];
}
});
});
};
Form.prototype.scrollToFirstError = function () {
var _this = this;
var _a = this.props, willScrollToError = _a.willScrollToError, form = _a.form;
if (typeof willScrollToError !== 'function') {
this._scrollToFirstError();
}
else {
var p = willScrollToError(form);
if (!isPromise(p)) {
this._scrollToFirstError(p);
}
else {
p.then(function (opt) {
_this._scrollToFirstError(opt);
}).catch(function () { });
}
}
};
Form.prototype._scrollToFirstError = function (options) {
var scrollX = Infinity;
var scrollY = Infinity;
for (var i = 0; i < this.children.length; i += 1) {
var child = this.children[i];
var el = child.getDOMNode();
if (!el || child.valid()) {
continue;
}
var elementBound = el.getBoundingClientRect();
var y = elementBound.top;
var x = elementBound.left;
if (y < scrollY || (y === scrollY && x < scrollX)) {
scrollX = x;
scrollY = y;
}
}
if (scrollX === Infinity || scrollY === Infinity) {
return;
}
var scrollOptions = (options !== null && options !== void 0 ? options : {});
var _a = scrollOptions.offsetX, offsetX = _a === void 0 ? 0 : _a, _b = scrollOptions.offsetY, offsetY = _b === void 0 ? 0 : _b, scrollContainer = scrollOptions.scrollContainer;
if (scrollContainer) {
var containerBox = scrollContainer.getBoundingClientRect();
var deltaX = scrollX - containerBox.left;
var deltaY = scrollY - containerBox.top;
var x = scrollContainer.scrollLeft + deltaX + offsetX;
var y = scrollContainer.scrollTop + deltaY + offsetY;
smoothScroll(scrollContainer, x, y);
}
else {
var _c = getScrollPosition(), x = _c.x, y = _c.y;
smoothScroll(document.body, scrollX + x + offsetX, scrollY + y + offsetY);
}
};
Form.prototype.subscribe = function () {
var form = this.props.form;
this.submitSubscription = form.submit$.subscribe(this.submitListener);
this.resetSubscription = form.reset$.subscribe(this.resetListener);
};
Form.prototype.unsubscribe = function () {
if (this.submitSubscription) {
this.submitSubscription.unsubscribe();
this.submitSubscription = null;
}
if (this.resetSubscription) {
this.resetSubscription.unsubscribe();
this.resetSubscription = null;
}
};
Form.prototype.componentDidMount = function () {
this.subscribe();
};
Form.prototype.componentDidUpdate = function (prevProps) {
if (prevProps.form !== this.props.form) {
this.unsubscribe();
this.subscribe();
}
};
Form.prototype.componentWillUnmount = function () {
this.unsubscribe();
};
Form.prototype.render = function () {
var _a = this.props, children = _a.children, _b = _a.layout, layout = _b === void 0 ? 'vertical' : _b, _c = _a.direction, direction = _c === void 0 ? 'column' : _c, className = _a.className, form = _a.form, onSubmit = _a.onSubmit, onSubmitFail = _a.onSubmitFail, onSubmitSuccess = _a.onSubmitSuccess, disableEnterSubmit = _a.disableEnterSubmit, _d = _a.disabled, disabled = _d === void 0 ? false : _d, scrollToError = _a.scrollToError, willScrollToError = _a.willScrollToError, props = __rest(_a, ["children", "layout", "direction", "className", "form", "onSubmit", "onSubmitFail", "onSubmitSuccess", "disableEnterSubmit", "disabled", "scrollToError", "willScrollToError"]);
var childrenCtx = this.getChildrenContext(this.children);
return (_jsx(Disabled, __assign({ value: disabled }, { children: _jsx(FormChildrenContext.Provider, __assign({ value: childrenCtx }, { children: _jsx(FormProvider, __assign({ value: form.ctx }, { children: _jsx("form", __assign({ ref: this.formRef }, props, { className: cx('zent-form-reactive', {
'zent-form-vertical': layout === 'vertical',
'zent-form-horizontal': layout === 'horizontal',
'zent-form-direction-row': direction === 'row',
'zent-form-direction-column': direction === 'column',
}, className), onSubmit: this.onSubmit, onReset: this.onReset, onKeyDown: this.onKeyDown, "data-zv": '10.0.17' }, { children: children }), void 0) }), void 0) }), void 0) }), void 0));
};
Form.displayName = 'ZentForm';
Form.CombineErrors = CombineErrors;
Form.useForm = useForm;
Form.useField = useField;
Form.useFieldArray = useFieldArray;
Form.useFieldSet = useFieldSet;
Form.useNamedChildModel = useNamedChildModel;
Form.useFieldArrayChildModels = useFieldArrayChildModels;
Form.useFieldArrayValue = useFieldArrayChildModels;
Form.field = field;
Form.set = set;
Form.array = array;
Form.form = form;
Form.FieldValue = FieldValue;
Form.FieldSetValue = FieldSetValue;
Form.useFormValue = useFormValue;
Form.useFieldValue = useFieldValue;
Form.FieldValid = FieldValid;
Form.useFormValid = useFormValid;
Form.useFieldValid = useFieldValid;
Form.useModelValue = useModelValue;
Form.useModelValid = useModelValid;
Form.ValidateOption = ValidateOption;
Form.createAsyncValidator = createAsyncValidator;
Form.isAsyncValidator = isAsyncValidator;
Form.ValidateOccasion = ValidateOccasion;
Form.TouchWhen = TouchWhen;
return Form;
}(Component));
export { Form };
var FormValidationError = (function (_super) {
__extends(FormValidationError, _super);
function FormValidationError(message) {
var _this = _super.call(this, message) || this;
_this.name = 'FormValidationError';
return _this;
}
return FormValidationError;
}(Error));
export { FormValidationError };