"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 classnames_1 = tslib_1.__importDefault(require("classnames"));
var mobx_1 = require("mobx");
var factory_1 = require("../../factory");
var helper_1 = require("../../utils/helper");
;
;
;
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 = this.props, inputClassName = _a.inputClassName, model = _a.formItem, ns = _a.classPrefix, children = _a.children, type = _a.type, renderControl = _a.renderControl, formItemConfig = _a.formItemConfig, sizeMutable = _a.sizeMutable, size = _a.size, defaultSize = _a.defaultSize, rest = tslib_1.__rest(_a, ["inputClassName", "formItem", "classPrefix", "children", "type", "renderControl", "formItemConfig", "sizeMutable", "size", "defaultSize"]);
        if (renderControl) {
            var controlSize = size || defaultSize;
            return renderControl(tslib_1.__assign({}, rest, { type: type, classPrefix: ns, formItem: model, className: classnames_1.default(ns + "Form-control", (_b = {
                        'is-inline': !!rest.inline,
                        'is-error': model && !model.valid
                    },
                    _b[ns + "Form-control--size" + helper_1.ucFirst(controlSize)] = sizeMutable !== false
                        && typeof controlSize === 'string'
                        && !!controlSize
                        && controlSize !== 'full',
                    _b), inputClassName) }));
        }
        return null;
        var _b;
    };
    FormItemWrap.prototype.renderHorizontal = function () {
        var _a = this.props, className = _a.className, ns = _a.classPrefix, description = _a.description, descriptionClassName = _a.descriptionClassName, captionClassName = _a.captionClassName, desc = _a.desc, label = _a.label, labelClassName = _a.labelClassName, render = _a.render, required = _a.required, caption = _a.caption, type = _a.type, remark = _a.remark, labelRemark = _a.labelRemark, env = _a.env, model = _a.formItem, renderLabel = _a.renderLabel, hint = _a.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: classnames_1.default(ns + "Form-item " + ns + "Form-item--horizontal", className, (_b = {},
                _b["is-error"] = model && !model.valid,
                _b["is-required"] = required,
                _b)) },
            label !== false ? (react_1.default.createElement("label", { className: classnames_1.default(ns + "Form-label", (_c = {},
                    _c[ns + "Form-itemColumn--" + (typeof horizontal.leftFixed === 'string' ? horizontal.leftFixed : 'normal')] = horizontal.leftFixed,
                    _c[ns + "Form-itemColumn--" + left] = !horizontal.leftFixed,
                    _c), labelClassName) },
                react_1.default.createElement("span", null,
                    label,
                    required ? (react_1.default.createElement("span", { className: ns + "Form-star" }, "*")) : null,
                    labelRemark ? render('label-remark', {
                        type: 'remark',
                        tooltip: labelRemark,
                        className: classnames_1.default(ns + "Form-labelRemark"),
                        container: env && env.getModalContainer ? env.getModalContainer() : undefined
                    }) : null))) : null,
            react_1.default.createElement("div", { className: classnames_1.default(ns + "Form-value", (_d = {},
                    // [`${ns}Form-itemColumn--offset${getWidthRate(horizontal.offset)}`]: !label && label !== false,
                    _d[ns + "Form-itemColumn--" + right] = !!right && right !== (12 - left),
                    _d)) },
                this.renderControl(),
                caption ? render('caption', caption, {
                    className: classnames_1.default(ns + "Form-caption", captionClassName)
                }) : null,
                remark ? render('remark', {
                    type: 'remark',
                    tooltip: remark,
                    className: classnames_1.default(ns + "Form-remark"),
                    container: env && env.getModalContainer ? env.getModalContainer() : undefined
                }) : null,
                hint && this.state.isFocused ? (render('hint', hint, {
                    className: classnames_1.default(ns + "Form-hint")
                })) : null,
                model && !model.valid ? (react_1.default.createElement("ul", { className: ns + "Form-feedback" }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
                description ? render('description', description, {
                    className: classnames_1.default(ns + "Form-description", descriptionClassName)
                }) : null)));
        var _b, _c, _d;
    };
    FormItemWrap.prototype.renderNormal = function () {
        var _a = this.props, className = _a.className, ns = _a.classPrefix, desc = _a.desc, description = _a.description, label = _a.label, labelClassName = _a.labelClassName, render = _a.render, required = _a.required, type = _a.type, caption = _a.caption, remark = _a.remark, labelRemark = _a.labelRemark, env = _a.env, descriptionClassName = _a.descriptionClassName, captionClassName = _a.captionClassName, model = _a.formItem, renderLabel = _a.renderLabel, hint = _a.hint, formMode = _a.formMode;
        description = description || desc;
        return (react_1.default.createElement("div", { className: classnames_1.default(ns + "Form-item " + ns + "Form-item--" + formMode, className, (_b = {
                    'is-error': model && !model.valid
                },
                _b["is-required"] = required,
                _b)) },
            label && renderLabel !== false ? (react_1.default.createElement("label", { className: classnames_1.default(ns + "Form-label", labelClassName) },
                react_1.default.createElement("span", null,
                    label,
                    required ? (react_1.default.createElement("span", { className: ns + "Form-star" }, "*")) : null,
                    labelRemark ? render('label-remark', {
                        type: 'remark',
                        tooltip: labelRemark,
                        className: classnames_1.default(ns + "Form-lableRemark"),
                        container: env && env.getModalContainer ? env.getModalContainer() : undefined
                    }) : null))) : null,
            this.renderControl(),
            caption ? render('caption', caption, {
                className: classnames_1.default(ns + "Form-caption", captionClassName)
            }) : null,
            remark ? render('remark', {
                type: 'remark',
                className: classnames_1.default(ns + "Form-remark"),
                tooltip: remark,
                container: env && env.getModalContainer ? env.getModalContainer() : undefined
            }) : null,
            hint && this.state.isFocused ? (render('hint', hint, {
                className: classnames_1.default(ns + "Form-hint")
            })) : null,
            model && !model.valid ? (react_1.default.createElement("ul", { className: ns + "Form-feedback" }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
            description ? render('description', description, {
                className: classnames_1.default(ns + "Form-description", descriptionClassName)
            }) : null));
        var _b;
    };
    FormItemWrap.prototype.renderInline = function () {
        var _a = this.props, className = _a.className, ns = _a.classPrefix, desc = _a.desc, description = _a.description, label = _a.label, labelClassName = _a.labelClassName, render = _a.render, required = _a.required, caption = _a.caption, descriptionClassName = _a.descriptionClassName, captionClassName = _a.captionClassName, model = _a.formItem, remark = _a.remark, labelRemark = _a.labelRemark, env = _a.env, hint = _a.hint, renderLabel = _a.renderLabel;
        description = description || desc;
        return (react_1.default.createElement("div", { className: classnames_1.default(ns + "Form-item " + ns + "Form-item--inline", className, (_b = {
                    'is-error': model && !model.valid
                },
                _b["is-required"] = required,
                _b)) },
            label && renderLabel !== false ? (react_1.default.createElement("label", { className: classnames_1.default(ns + "Form-label", labelClassName) },
                react_1.default.createElement("span", null,
                    label,
                    required ? (react_1.default.createElement("span", { className: ns + "Form-star" }, "*")) : null,
                    labelRemark ? render('label-remark', {
                        type: 'remark',
                        tooltip: labelRemark,
                        className: classnames_1.default(ns + "Form-lableRemark"),
                        container: env && env.getModalContainer ? env.getModalContainer() : undefined
                    }) : null))) : null,
            react_1.default.createElement("div", { className: ns + "Form-value" },
                this.renderControl(),
                caption ? render('caption', caption, {
                    className: classnames_1.default(ns + "Form-caption", captionClassName)
                }) : null,
                remark ? render('remark', {
                    type: 'remark',
                    className: classnames_1.default(ns + "Form-remark"),
                    tooltip: remark,
                    container: env && env.getModalContainer ? env.getModalContainer() : undefined
                }) : null,
                hint && this.state.isFocused ? (render('hint', hint, {
                    className: classnames_1.default(ns + "Form-hint")
                })) : null,
                model && !model.valid ? (react_1.default.createElement("ul", { className: ns + "Form-feedback" }, model.errors.map(function (msg, key) { return (react_1.default.createElement("li", { key: key }, msg)); }))) : null,
                description ? render('description', description, {
                    className: classnames_1.default(ns + "Form-description", descriptionClassName)
                }) : null)));
        var _b;
    };
    FormItemWrap.prototype.renderRow = function () {
        var _a = this.props, className = _a.className, cx = _a.classnames, ns = _a.classPrefix, desc = _a.desc, description = _a.description, label = _a.label, labelClassName = _a.labelClassName, render = _a.render, required = _a.required, type = _a.type, caption = _a.caption, remark = _a.remark, labelRemark = _a.labelRemark, env = _a.env, descriptionClassName = _a.descriptionClassName, captionClassName = _a.captionClassName, model = _a.formItem, renderLabel = _a.renderLabel, hint = _a.hint, formMode = _a.formMode;
        description = description || desc;
        return (react_1.default.createElement("div", { className: cx("Form-item Form-item--" + formMode, className, (_b = {
                    'is-error': model && !model.valid
                },
                _b["is-required"] = required,
                _b)) },
            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 ? render('description', description, {
                className: cx("Form-description", descriptionClassName)
            }) : null));
        var _b;
    };
    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
        })(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 = this.props, inputClassName = _a.inputClassName, model = _a.formItem, ns = _a.classPrefix, children = _a.children, type = _a.type, size = _a.size, defaultSize = _a.defaultSize, rest = tslib_1.__rest(_a, ["inputClassName", "formItem", "classPrefix", "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, classPrefix: ns, ref: this.refFn, formItem: model, className: classnames_1.default(ns + "Form-control", (_b = {
                        'is-inline': !!rest.inline,
                        'is-error': model && !model.valid
                    },
                    _b[ns + "Form-control--size" + helper_1.ucFirst(controlSize)] = config.sizeMutable !== false
                        && typeof controlSize === 'string'
                        && !!controlSize
                        && controlSize !== 'full',
                    _b), inputClassName) })));
            var _b;
        };
        FormItemRenderer.defaultProps = tslib_1.__assign({ className: '', renderLabel: config.renderLabel, sizeMutable: config.sizeMutable, wrap: config.wrap, strictMode: config.strictMode }, Control.defaultProps);
        FormItemRenderer.propsList = [
            'value',
            'defaultValue',
            'onChange',
            'setPrinstineValue',
            'readOnly'
        ].concat(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({}, 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({}, config, { component: component }));
        return renderer.component;
    };
}
exports.FormItem = FormItem;
exports.default = FormItem;
//# sourceMappingURL=./renderers/Form/Item.js.map
