"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importDefault(require("react"));
var hoistNonReactStatic = require("hoist-non-react-statics");
var mobx_1 = require("mobx");
var factory_1 = require("../../factory");
var helper_1 = require("../../utils/helper");
var mobx_react_1 = require("mobx-react");
var FormItemWrap = /** @class */ (function (_super) {
    tslib_1.__extends(FormItemWrap, _super);
    function FormItemWrap(props) {
        var _this = _super.call(this, props) || this;
        _this.state = {
            isFocused: false
        };
        _this.handleFocus = _this.handleFocus.bind(_this);
        _this.handleBlur = _this.handleBlur.bind(_this);
        return _this;
    }
    FormItemWrap.prototype.componentWillMount = function () {
        var _this = this;
        var model = this.props.formItem;
        if (model) {
            this.reaction = mobx_1.reaction(function () { return model.errors.join(''); }, function () { return _this.forceUpdate(); });
        }
    };
    FormItemWrap.prototype.componentWillUnmount = function () {
        this.reaction && this.reaction();
    };
    FormItemWrap.prototype.handleFocus = function (e) {
        this.setState({
            isFocused: true
        });
        this.props.onFocus && this.props.onFocus(e);
    };
    FormItemWrap.prototype.handleBlur = function (e) {
        this.setState({
            isFocused: false
        });
        this.props.onBlur && this.props.onBlur(e);
    };
    FormItemWrap.prototype.renderControl = function () {
        var _a;
        var _b = this.props, inputClassName = _b.inputClassName, model = _b.formItem, cx = _b.classnames, children = _b.children, type = _b.type, renderControl = _b.renderControl, formItemConfig = _b.formItemConfig, sizeMutable = _b.sizeMutable, size = _b.size, defaultSize = _b.defaultSize, rest = tslib_1.__rest(_b, ["inputClassName", "formItem", "classnames", "children", "type", "renderControl", "formItemConfig", "sizeMutable", "size", "defaultSize"]);
        if (renderControl) {
            var controlSize = size || defaultSize;
            return renderControl(tslib_1.__assign(tslib_1.__assign({}, rest), { type: type, classnames: cx, formItem: model, className: cx("Form-control", (_a = {
                        'is-inline': !!rest.inline,
                        'is-error': model && !model.valid
                    },
                    _a["Form-control--size" + helper_1.ucFirst(controlSize)] = sizeMutable !== false &&
                        typeof controlSize === 'string' &&
                        !!controlSize &&
                        controlSize !== 'full',
                    _a), inputClassName) }));
        }
        return null;
    };
    FormItemWrap.prototype.renderHorizontal = function () {
        var _a, _b, _c;
        var _d = this.props, className = _d.className, cx = _d.classnames, description = _d.description, descriptionClassName = _d.descriptionClassName, captionClassName = _d.captionClassName, desc = _d.desc, label = _d.label, labelClassName = _d.labelClassName, render = _d.render, required = _d.required, caption = _d.caption, remark = _d.remark, labelRemark = _d.labelRemark, env = _d.env, model = _d.formItem, renderLabel = _d.renderLabel, renderDescription = _d.renderDescription, hint = _d.hint;
        // 强制不渲染 label 的话
        if (renderLabel === false) {
            label = label === false ? false : '';
        }
        description = description || desc;
        var horizontal = this.props.horizontal || this.props.formHorizontal;
        var left = helper_1.getWidthRate(horizontal.left);
        var right = helper_1.getWidthRate(horizontal.right);
        return (react_1.default.createElement("div", { className: cx("Form-item Form-item--horizontal", className, (_a = {},
                _a["is-error"] = model && !model.valid,
                _a["is-required"] = required,
                _a)) },
            label !== false ? (react_1.default.createElement("label", { className: cx("Form-label", (_b = {},
                    _b["Form-itemColumn--" + (typeof horizontal.leftFixed === 'string' ? horizontal.leftFixed : 'normal')] = horizontal.leftFixed,
                    _b["Form-itemColumn--" + left] = !horizontal.leftFixed,
                    _b), labelClassName) },
                react_1.default.createElement("span", null,
                    label,
                    required ? react_1.default.createElement("span", { className: cx("Form-star") }, "*") : null,
                    labelRemark
                        ? render('label-remark', {
                            type: 'remark',
                            tooltip: labelRemark,
                            className: cx("Form-labelRemark"),
                            container: env && env.getModalContainer ? env.getModalContainer() : undefined
                        })
                        : null))) : null,
            react_1.default.createElement("div", { className: cx("Form-value", (_c = {},
                    // [`Form-itemColumn--offset${getWidthRate(horizontal.offset)}`]: !label && label !== false,
                    _c["Form-itemColumn--" + right] = !!right && right !== 12 - left,
                    _c)) },
                this.renderControl(),
                caption
                    ? render('caption', caption, {
                        className: cx("Form-caption", captionClassName)
                    })
                    : null,
                remark
                    ? render('remark', {
                        type: 'remark',
                        tooltip: remark,
                        className: cx("Form-remark"),
                        container: env && env.getModalContainer ? env.getModalContainer() : undefined
                    })
                    : null,
                hint && this.state.isFocused
                    ? render('hint', hint, {
                        className: cx("Form-hint")
                    })
                    : null,
                model && !model.valid ? (react_1.default.createElement("ul", { className: cx("Form-feedback") }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
                renderDescription !== false && description
                    ? render('description', description, {
                        className: cx("Form-description", descriptionClassName)
                    })
                    : null)));
    };
    FormItemWrap.prototype.renderNormal = function () {
        var _a;
        var _b = this.props, className = _b.className, cx = _b.classnames, desc = _b.desc, description = _b.description, label = _b.label, labelClassName = _b.labelClassName, render = _b.render, required = _b.required, caption = _b.caption, remark = _b.remark, labelRemark = _b.labelRemark, env = _b.env, descriptionClassName = _b.descriptionClassName, captionClassName = _b.captionClassName, model = _b.formItem, renderLabel = _b.renderLabel, renderDescription = _b.renderDescription, hint = _b.hint, formMode = _b.formMode;
        description = description || desc;
        return (react_1.default.createElement("div", { className: cx("Form-item Form-item--" + formMode, className, (_a = {
                    'is-error': model && !model.valid
                },
                _a["is-required"] = required,
                _a)) },
            label && renderLabel !== false ? (react_1.default.createElement("label", { className: cx("Form-label", labelClassName) },
                react_1.default.createElement("span", null,
                    label,
                    required ? react_1.default.createElement("span", { className: cx("Form-star") }, "*") : null,
                    labelRemark
                        ? render('label-remark', {
                            type: 'remark',
                            tooltip: labelRemark,
                            className: cx("Form-lableRemark"),
                            container: env && env.getModalContainer ? env.getModalContainer() : undefined
                        })
                        : null))) : null,
            this.renderControl(),
            caption
                ? render('caption', caption, {
                    className: cx("Form-caption", captionClassName)
                })
                : null,
            remark
                ? render('remark', {
                    type: 'remark',
                    className: cx("Form-remark"),
                    tooltip: remark,
                    container: env && env.getModalContainer ? env.getModalContainer() : undefined
                })
                : null,
            hint && this.state.isFocused
                ? render('hint', hint, {
                    className: cx("Form-hint")
                })
                : null,
            model && !model.valid ? (react_1.default.createElement("ul", { className: cx("Form-feedback") }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
            renderDescription !== false && description
                ? render('description', description, {
                    className: cx("Form-description", descriptionClassName)
                })
                : null));
    };
    FormItemWrap.prototype.renderInline = function () {
        var _a;
        var _b = this.props, className = _b.className, cx = _b.classnames, desc = _b.desc, description = _b.description, label = _b.label, labelClassName = _b.labelClassName, render = _b.render, required = _b.required, caption = _b.caption, descriptionClassName = _b.descriptionClassName, captionClassName = _b.captionClassName, model = _b.formItem, remark = _b.remark, labelRemark = _b.labelRemark, env = _b.env, hint = _b.hint, renderLabel = _b.renderLabel, renderDescription = _b.renderDescription;
        description = description || desc;
        return (react_1.default.createElement("div", { className: cx("Form-item Form-item--inline", className, (_a = {
                    'is-error': model && !model.valid
                },
                _a["is-required"] = required,
                _a)) },
            label && renderLabel !== false ? (react_1.default.createElement("label", { className: cx("Form-label", labelClassName) },
                react_1.default.createElement("span", null,
                    label,
                    required ? react_1.default.createElement("span", { className: cx("Form-star") }, "*") : null,
                    labelRemark
                        ? render('label-remark', {
                            type: 'remark',
                            tooltip: labelRemark,
                            className: cx("Form-lableRemark"),
                            container: env && env.getModalContainer ? env.getModalContainer() : undefined
                        })
                        : null))) : null,
            react_1.default.createElement("div", { className: cx("Form-value") },
                this.renderControl(),
                caption
                    ? render('caption', caption, {
                        className: cx("Form-caption", captionClassName)
                    })
                    : null,
                remark
                    ? render('remark', {
                        type: 'remark',
                        className: cx("Form-remark"),
                        tooltip: remark,
                        container: env && env.getModalContainer ? env.getModalContainer() : undefined
                    })
                    : null,
                hint && this.state.isFocused
                    ? render('hint', hint, {
                        className: cx("Form-hint")
                    })
                    : null,
                model && !model.valid ? (react_1.default.createElement("ul", { className: cx("Form-feedback") }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
                renderDescription !== false && description
                    ? render('description', description, {
                        className: cx("Form-description", descriptionClassName)
                    })
                    : null)));
    };
    FormItemWrap.prototype.renderRow = function () {
        var _a;
        var _b = this.props, className = _b.className, cx = _b.classnames, desc = _b.desc, description = _b.description, label = _b.label, labelClassName = _b.labelClassName, render = _b.render, required = _b.required, caption = _b.caption, remark = _b.remark, labelRemark = _b.labelRemark, env = _b.env, descriptionClassName = _b.descriptionClassName, captionClassName = _b.captionClassName, model = _b.formItem, renderLabel = _b.renderLabel, renderDescription = _b.renderDescription, hint = _b.hint, formMode = _b.formMode;
        description = description || desc;
        return (react_1.default.createElement("div", { className: cx("Form-item Form-item--" + formMode, className, (_a = {
                    'is-error': model && !model.valid
                },
                _a["is-required"] = required,
                _a)) },
            react_1.default.createElement("div", { className: cx('Form-rowInner') },
                label && renderLabel !== false ? (react_1.default.createElement("label", { className: cx("Form-label", labelClassName) },
                    react_1.default.createElement("span", null,
                        label,
                        required ? react_1.default.createElement("span", { className: cx("Form-star") }, "*") : null,
                        labelRemark
                            ? render('label-remark', {
                                type: 'remark',
                                tooltip: labelRemark,
                                className: cx("Form-lableRemark"),
                                container: env && env.getModalContainer ? env.getModalContainer() : undefined
                            })
                            : null))) : null,
                this.renderControl(),
                caption
                    ? render('caption', caption, {
                        className: cx("Form-caption", captionClassName)
                    })
                    : null,
                remark
                    ? render('remark', {
                        type: 'remark',
                        className: cx("Form-remark"),
                        tooltip: remark,
                        container: env && env.getModalContainer ? env.getModalContainer() : undefined
                    })
                    : null),
            hint && this.state.isFocused
                ? render('hint', hint, {
                    className: cx("Form-hint")
                })
                : null,
            model && !model.valid ? (react_1.default.createElement("ul", { className: cx('Form-feedback') }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
            description && renderDescription !== false
                ? render('description', description, {
                    className: cx("Form-description", descriptionClassName)
                })
                : null));
    };
    FormItemWrap.prototype.render = function () {
        var _a = this.props, formMode = _a.formMode, inputOnly = _a.inputOnly, wrap = _a.wrap;
        if (wrap === false || inputOnly) {
            return this.renderControl();
        }
        return formMode === 'inline'
            ? this.renderInline()
            : formMode === 'horizontal'
                ? this.renderHorizontal()
                : formMode === 'row'
                    ? this.renderRow()
                    : this.renderNormal();
    };
    return FormItemWrap;
}(react_1.default.Component));
exports.FormItemWrap = FormItemWrap;
function registerFormItem(config) {
    var Control = config.component;
    // 兼容老的 FormItem 用法。
    if (config.validate && !Control.prototype.validate) {
        var fn_1 = config.validate;
        Control.prototype.validate = function () {
            // console.warn('推荐直接在类中定义，而不是 FormItem HOC 的参数中传入。');
            var host = {
                input: this
            };
            return fn_1.apply(host, arguments);
        };
    }
    else if (config.validate) {
        console.error('FormItem配置中的 validate 将不起作用，因为类的成员函数中已经定义了 validate 方法，将优先使用类里面的实现。');
    }
    if (config.storeType) {
        Control = factory_1.HocStoreFactory({
            storeType: config.storeType,
            extendsData: config.extendsData
        })(mobx_react_1.observer(Control));
        delete config.storeType;
    }
    // @observer
    var FormItemRenderer = /** @class */ (function (_super) {
        tslib_1.__extends(FormItemRenderer, _super);
        function FormItemRenderer(props) {
            var _this = _super.call(this, props) || this;
            _this.refFn = _this.refFn.bind(_this);
            return _this;
        }
        FormItemRenderer.prototype.componentWillMount = function () {
            var _a = this.props, validations = _a.validations, model = _a.formItem;
            // 组件注册的时候可能默认指定验证器类型
            if (model && !validations && config.validations) {
                model.config({
                    rules: config.validations
                });
            }
            _super.prototype.componentWillMount.call(this);
        };
        FormItemRenderer.prototype.shouldComponentUpdate = function (nextProps) {
            if (nextProps.strictMode === false) {
                return true;
            }
            // 把可能会影响视图的白名单弄出来，减少重新渲染次数。
            if (helper_1.anyChanged([
                'formPristine',
                'addable',
                'addButtonClassName',
                'addButtonText',
                'addOn',
                'btnClassName',
                'btnLabel',
                'btnDisabled',
                'className',
                'clearable',
                'columns',
                'columnsCount',
                'controls',
                'desc',
                'description',
                'disabled',
                'draggable',
                'editable',
                'editButtonClassName',
                'formHorizontal',
                'formMode',
                'hideRoot',
                'horizontal',
                'icon',
                'inline',
                'inputClassName',
                'label',
                'labelClassName',
                'labelField',
                'language',
                'level',
                'max',
                'maxRows',
                'min',
                'minRows',
                'multiLine',
                'multiple',
                'option',
                'placeholder',
                'removable',
                'required',
                'remark',
                'hint',
                'rows',
                'searchable',
                'showCompressOptions',
                'size',
                'step',
                'showInput',
                'unit',
                'value',
                'diffValue'
            ], this.props, nextProps)) {
                return true;
            }
            return false;
        };
        FormItemRenderer.prototype.getWrappedInstance = function () {
            return this.ref;
        };
        FormItemRenderer.prototype.refFn = function (ref) {
            this.ref = ref;
        };
        FormItemRenderer.prototype.renderControl = function () {
            var _a;
            var _b = this.props, inputClassName = _b.inputClassName, model = _b.formItem, cx = _b.classnames, children = _b.children, type = _b.type, size = _b.size, defaultSize = _b.defaultSize, rest = tslib_1.__rest(_b, ["inputClassName", "formItem", "classnames", "children", "type", "size", "defaultSize"]);
            var controlSize = size || defaultSize;
            return (react_1.default.createElement(Control, tslib_1.__assign({}, rest, { size: config.sizeMutable !== false ? undefined : size, onFocus: this.handleFocus, onBlur: this.handleBlur, type: type, classnames: cx, ref: this.refFn, formItem: model, className: cx("Form-control", (_a = {
                        'is-inline': !!rest.inline,
                        'is-error': model && !model.valid
                    },
                    _a["Form-control--size" + helper_1.ucFirst(controlSize)] = config.sizeMutable !== false &&
                        typeof controlSize === 'string' &&
                        !!controlSize &&
                        controlSize !== 'full',
                    _a), inputClassName) })));
        };
        FormItemRenderer.defaultProps = tslib_1.__assign({ className: '', renderLabel: config.renderLabel, renderDescription: config.renderDescription, sizeMutable: config.sizeMutable, wrap: config.wrap, strictMode: config.strictMode }, Control.defaultProps);
        FormItemRenderer.propsList = tslib_1.__spreadArrays([
            'value',
            'defaultValue',
            'onChange',
            'setPrinstineValue',
            'readOnly'
        ], (Control.propsList || []));
        FormItemRenderer.displayName = "FormItem" + (config.type ? "(" + config.type + ")" : '');
        FormItemRenderer.ComposedComponent = Control;
        return FormItemRenderer;
    }(FormItemWrap));
    hoistNonReactStatic(FormItemRenderer, Control);
    return factory_1.registerRenderer(tslib_1.__assign(tslib_1.__assign({}, config), { name: config.name || config.type + "-control", weight: typeof config.weight !== 'undefined' ? config.weight : -100, test: config.test || new RegExp("(^|/)form(?:/.+)?/control/(?:d+/)?" + config.type + "$", 'i'), component: FormItemRenderer, isFormItem: true }));
}
exports.registerFormItem = registerFormItem;
function FormItem(config) {
    return function (component) {
        var renderer = registerFormItem(tslib_1.__assign(tslib_1.__assign({}, config), { component: component }));
        return renderer.component;
    };
}
exports.FormItem = FormItem;
exports.default = FormItem;
//# sourceMappingURL=./renderers/Form/Item.js.map
