UNPKG

mobx-react-form

Version:
3,571 lines • 145 kB
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("_"), require("mobx"));
	else if(typeof define === 'function' && define.amd)
		define(["_", "mobx"], factory);
	else if(typeof exports === 'object')
		exports["MobxReactForm"] = factory(require("_"), require("mobx"));
	else
		root["MobxReactForm"] = factory(root["_"], root["mobx"]);
})(self, (__WEBPACK_EXTERNAL_MODULE_lodash__, __WEBPACK_EXTERNAL_MODULE_mobx__) => {
return /******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ "./src/Base.ts":
/*!*********************!*\
  !*** ./src/Base.ts ***!
  \*********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
const parser_1 = __webpack_require__(/*! ./parser */ "./src/parser.ts");
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
const OptionsModel_1 = __webpack_require__(/*! ./models/OptionsModel */ "./src/models/OptionsModel.ts");
const ValidatorInterface_1 = __webpack_require__(/*! ./models/ValidatorInterface */ "./src/models/ValidatorInterface.ts");
class Base {
    constructor() {
        Object.defineProperty(this, "noop", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: () => { }
        });
        Object.defineProperty(this, "state", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "fields", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: mobx_1.observable.map({})
        });
        Object.defineProperty(this, "path", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$submitted", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 0
        });
        Object.defineProperty(this, "$submitting", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$validated", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 0
        });
        Object.defineProperty(this, "$validating", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$clearing", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$resetting", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$touched", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$changed", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 0
        });
        Object.defineProperty(this, "$hooks", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {}
        });
        Object.defineProperty(this, "$handlers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {}
        });
        Object.defineProperty(this, "execHook", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (name, fallback = {}) => (0, utils_1.$try)(fallback[name], this.$hooks[name], this.noop).apply(this, [this])
        });
        Object.defineProperty(this, "execHandler", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (name, args, fallback = undefined, hook = null, execHook = true) => [
                (0, utils_1.$try)(this.$handlers[name] && this.$handlers[name].apply(this, [this]), fallback, this.noop).apply(this, [...args]),
                execHook && this.execHook(hook || name),
            ]
        });
        /**
          Interceptor
        */
        Object.defineProperty(this, "intercept", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (opt) => this.MOBXEvent((typeof opt === 'function')
                ? { type: "interceptor", call: opt }
                : Object.assign({ type: "interceptor" }, opt))
        });
        /**
          Observer
        */
        Object.defineProperty(this, "observe", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (opt) => this.MOBXEvent((typeof opt === 'function')
                ? { type: "observer", call: opt }
                : Object.assign({ type: "observer" }, opt))
        });
        /**
          Event Handler: On Clear
        */
        Object.defineProperty(this, "onClear", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onClear, args, (e) => {
                (0, utils_1.isEvent)(e) && e.preventDefault();
                this.clear(true, false);
            })
        });
        /**
          Event Handler: On Reset
        */
        Object.defineProperty(this, "onReset", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onReset, args, (e) => {
                (0, utils_1.isEvent)(e) && e.preventDefault();
                this.reset(true, false);
            })
        });
        /**
          Event Handler: On Submit
         */
        Object.defineProperty(this, "onSubmit", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onSubmit, args, (e, o = {}) => {
                (0, utils_1.isEvent)(e) && e.preventDefault();
                this.submit(o);
            }, null, false)
        });
        /**
          Event Handler: On Add
        */
        Object.defineProperty(this, "onAdd", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onAdd, args, (e, val) => {
                (0, utils_1.isEvent)(e) && e.preventDefault();
                this.add((0, utils_1.isEvent)(val) ? null : val, false);
            })
        });
        /**
          Event Handler: On Del
        */
        Object.defineProperty(this, "onDel", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onDel, args, (e, path) => {
                (0, utils_1.isEvent)(e) && e.preventDefault();
                this.del((0, utils_1.isEvent)(path) ? this.path : path, false);
            })
        });
        (0, mobx_1.makeObservable)(this, {
            $submitted: mobx_1.observable,
            $submitting: mobx_1.observable,
            $validated: mobx_1.observable,
            $validating: mobx_1.observable,
            $clearing: mobx_1.observable,
            $resetting: mobx_1.observable,
            $touched: mobx_1.observable,
            $changed: mobx_1.observable,
            $hooks: mobx_1.observable,
            $handlers: mobx_1.observable,
            changed: mobx_1.computed,
            submitted: mobx_1.computed,
            submitting: mobx_1.computed,
            validated: mobx_1.computed,
            validating: mobx_1.computed,
            clearing: mobx_1.computed,
            resetting: mobx_1.computed,
            hasIncrementalKeys: mobx_1.computed,
            hasNestedFields: mobx_1.computed,
            size: mobx_1.computed,
            // initialization
            initField: mobx_1.action,
            // actions
            submit: mobx_1.action,
            deepUpdate: mobx_1.action,
            set: mobx_1.action,
            add: mobx_1.action,
            del: mobx_1.action,
        });
    }
    get resetting() {
        return this.hasNestedFields ? this.check(FieldProps_1.FieldPropsEnum.resetting, true) : this.$resetting;
    }
    get clearing() {
        return this.hasNestedFields ? this.check(FieldProps_1.FieldPropsEnum.clearing, true) : this.$clearing;
    }
    get submitted() {
        return (0, mobx_1.toJS)(this.$submitted);
    }
    get submitting() {
        return (0, mobx_1.toJS)(this.$submitting);
    }
    get validated() {
        return (0, mobx_1.toJS)(this.$validated);
    }
    get validating() {
        return (0, mobx_1.toJS)(this.$validating);
    }
    get hasIncrementalKeys() {
        return !!this.fields.size && (0, utils_1.hasIntKeys)(this.fields);
    }
    get hasNestedFields() {
        return this.fields.size !== 0;
    }
    get size() {
        return this.fields.size;
    }
    get changed() {
        return !lodash_1.default.isNil(this.path) && this.hasNestedFields
            ? (this.reduce((acc, field) => (acc + field.changed), 0) + this.$changed)
            : this.$changed;
    }
    /******************************************************************
      Initializer
    */
    initFields(initial, update = false) {
        const fallback = this.state.options.get(OptionsModel_1.OptionsEnum.fallback);
        const $path = (key) => lodash_1.default.trimStart([this.path, key].join("."), ".");
        let fields;
        fields = (0, parser_1.prepareFieldsData)(initial, this.state.strict, fallback);
        fields = (0, parser_1.mergeSchemaDefaults)(fields, this.validator);
        // create fields
        lodash_1.default.forIn(fields, (field, key) => {
            const path = $path(key);
            const $f = this.select(path, null, false);
            if (lodash_1.default.isNil($f)) {
                if (fallback) {
                    this.initField(key, path, field, update);
                }
                else {
                    const structPath = (0, utils_1.pathToStruct)(path);
                    const struct = this.state.struct();
                    const found = struct
                        .filter((s) => s.startsWith(structPath))
                        .find((s) => s.charAt(structPath.length) === "." ||
                        s.substring(structPath.length, structPath.length + 2) === "[]" ||
                        s === structPath);
                    if (found)
                        this.initField(key, path, field, update);
                }
            }
        });
    }
    initField(key, path, data, update = false) {
        const initial = this.state.get("current", "props");
        const struct = (0, utils_1.pathToStruct)(path);
        // try to get props from separated objects
        const _try = (prop) => {
            const t = lodash_1.default.get(initial[prop], struct);
            if ([
                FieldProps_1.FieldPropsEnum.input,
                FieldProps_1.FieldPropsEnum.output,
                FieldProps_1.FieldPropsEnum.converter,
            ].includes(prop) && typeof t !== "function")
                return undefined;
            return t;
        };
        const props = {
            $value: lodash_1.default.get(initial[FieldProps_1.SeparatedPropsMode.values], path),
            $computed: _try(FieldProps_1.SeparatedPropsMode.computed),
            $label: _try(FieldProps_1.SeparatedPropsMode.labels),
            $placeholder: _try(FieldProps_1.SeparatedPropsMode.placeholders),
            $default: _try(FieldProps_1.SeparatedPropsMode.defaults),
            $initial: _try(FieldProps_1.SeparatedPropsMode.initials),
            $disabled: _try(FieldProps_1.SeparatedPropsMode.disabled),
            $deleted: _try(FieldProps_1.SeparatedPropsMode.deleted),
            $type: _try(FieldProps_1.SeparatedPropsMode.types),
            $related: _try(FieldProps_1.SeparatedPropsMode.related),
            $rules: _try(FieldProps_1.SeparatedPropsMode.rules),
            $options: _try(FieldProps_1.SeparatedPropsMode.options),
            $bindings: _try(FieldProps_1.SeparatedPropsMode.bindings),
            $extra: _try(FieldProps_1.SeparatedPropsMode.extra),
            $hooks: _try(FieldProps_1.SeparatedPropsMode.hooks),
            $handlers: _try(FieldProps_1.SeparatedPropsMode.handlers),
            $validatedWith: _try(FieldProps_1.SeparatedPropsMode.validatedWith),
            $validators: _try(FieldProps_1.SeparatedPropsMode.validators),
            $observers: _try(FieldProps_1.SeparatedPropsMode.observers),
            $interceptors: _try(FieldProps_1.SeparatedPropsMode.interceptors),
            $converters: _try(FieldProps_1.SeparatedPropsMode.converters),
            $input: _try(FieldProps_1.SeparatedPropsMode.input),
            $output: _try(FieldProps_1.SeparatedPropsMode.output),
            $autoFocus: _try(FieldProps_1.SeparatedPropsMode.autoFocus),
            $ref: _try(FieldProps_1.SeparatedPropsMode.refs),
            $nullable: _try(FieldProps_1.SeparatedPropsMode.nullable),
            $autoComplete: _try(FieldProps_1.SeparatedPropsMode.autoComplete),
        };
        const field = this.state.form.makeField({
            key,
            path,
            struct,
            data,
            props,
            update,
            state: this.state,
        }, data && data[FieldProps_1.FieldPropsEnum.class] || _try(FieldProps_1.SeparatedPropsMode.classes));
        this.fields.merge({ [key]: field });
        return field;
    }
    /******************************************************************
      Actions
    */
    validate(opt, obj) {
        const $opt = lodash_1.default.merge(opt, { path: this.path });
        return this.state.form.validator.validate($opt, obj);
    }
    /**
      Submit
    */
    submit(hooks = {}, { execOnSubmitHook = true, execValidationHooks = true, validate = true } = {}) {
        const execOnSubmit = () => this.execHook(FieldProps_1.FieldPropsEnum.onSubmit, hooks);
        const submit = execOnSubmitHook ? execOnSubmit() : undefined;
        this.$submitting = true;
        this.$submitted += 1;
        if (!validate || !this.state.options.get(OptionsModel_1.OptionsEnum.validateOnSubmit, this)) {
            return Promise
                .resolve(submit)
                .then((0, mobx_1.action)(() => (this.$submitting = false)))
                .catch((0, mobx_1.action)((err) => {
                this.$submitting = false;
                throw err;
            }))
                .then(() => this);
        }
        const exec = (isValid) => isValid
            ? this.execHook(ValidatorInterface_1.ValidationHooks.onSuccess, hooks)
            : this.execHook(ValidatorInterface_1.ValidationHooks.onError, hooks);
        return (this.validate({
            showErrors: this.state.options.get(OptionsModel_1.OptionsEnum.showErrorsOnSubmit, this),
        })
            .then(({ isValid }) => {
            const handler = execValidationHooks ? exec(isValid) : undefined;
            if (isValid)
                return Promise.all([submit, handler]);
            const $err = this.state.options.get(OptionsModel_1.OptionsEnum.defaultGenericError, this);
            const $throw = this.state.options.get(OptionsModel_1.OptionsEnum.submitThrowsError, this);
            if ($throw && $err)
                this.invalidate();
            return Promise.all([submit, handler]);
        })
            .then((0, mobx_1.action)(() => (this.$submitting = false)))
            .catch((0, mobx_1.action)((err) => {
            this.$submitting = false;
            throw err;
        }))
            .then(() => this));
    }
    /**
      Check Field Computed Values
     */
    check(prop, deep = false) {
        (0, utils_1.allowedProps)(FieldProps_1.AllowedFieldPropsTypes.computed, [prop]);
        return deep
            ? (0, utils_1.checkPropOccurrence)({
                type: utils_1.props.occurrences[prop],
                data: this.deepCheck(utils_1.props.occurrences[prop], prop, this.fields),
            })
            : this[prop];
    }
    deepCheck(type, prop, fields) {
        const $fields = (0, utils_1.getObservableMapValues)(fields);
        return lodash_1.default.transform($fields, (check, field) => {
            if (!field.fields.size || !Array.isArray(field.initial)) {
                check.push(field[prop]);
            }
            check.push((0, utils_1.checkPropOccurrence)({
                data: this.deepCheck(type, prop, field.fields),
                type,
            }));
            return check;
        }, []);
    }
    /**
      Update Field Values recurisvely
      OR Create Field if 'undefined'
     */
    update(fields) {
        if (!lodash_1.default.isPlainObject(fields)) {
            throw new Error("The update() method accepts only plain objects.");
        }
        this.deepUpdate((0, parser_1.prepareFieldsData)({ fields }, this.state.strict), undefined, undefined, fields);
    }
    deepUpdate(fields, path = "", recursion = true, raw) {
        lodash_1.default.each(fields, (field, key) => {
            var _a;
            const $key = lodash_1.default.has(field, FieldProps_1.FieldPropsEnum.name) ? field.name : key;
            const $path = lodash_1.default.trimStart(`${path}.${$key}`, ".");
            const strictUpdate = this.state.options.get(OptionsModel_1.OptionsEnum.strictUpdate, this);
            const $field = this.select($path, null, strictUpdate);
            const $container = this.select(path, null, false) || this.state.form.select(this.path, null, false);
            const applyInputConverterOnUpdate = this.state.options.get(OptionsModel_1.OptionsEnum.applyInputConverterOnUpdate, this);
            if (!lodash_1.default.isNil($field) && !lodash_1.default.isUndefined(field)) {
                if (Array.isArray($field.values())) {
                    const n = (_a = lodash_1.default.max(lodash_1.default.map(field.fields, (f, i) => Number(i)))) !== null && _a !== void 0 ? _a : -1;
                    (0, utils_1.getObservableMapValues)($field.fields).forEach(($f) => {
                        if (Number($f.name) > n) {
                            $field.$changed++;
                            $field.state.form.$changed++;
                            $field.fields.delete($f.name);
                        }
                    });
                }
                if (field === null || field === void 0 ? void 0 : field.fields) {
                    const fallback = this.state.options.get(OptionsModel_1.OptionsEnum.fallback);
                    const x = this.state.struct().findIndex(s => s.startsWith($field.path.replace(/\.\d+\./, '[].') + '[]'));
                    if (!fallback && $field.fields.size === 0 && x < 0) {
                        $field.value = (0, parser_1.parseInput)(applyInputConverterOnUpdate ? $field.$input : (val) => val, {
                            fallbackValueOption: this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this),
                            separated: lodash_1.default.get(raw, $path),
                        });
                        return;
                    }
                }
                if (lodash_1.default.isNull(field) || lodash_1.default.isNil(field.fields)) {
                    $field.value = (0, parser_1.parseInput)(applyInputConverterOnUpdate ? $field.$input : (val) => val, {
                        fallbackValueOption: this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this),
                        separated: field,
                    });
                    return;
                }
            }
            if (!lodash_1.default.isNil($container) && lodash_1.default.isNil($field)) {
                // get full path when using update() with select() - FIX: #179
                const $newFieldPath = lodash_1.default.trimStart([this.path, $path].join("."), ".");
                // init field into the container field
                $container.$changed++;
                $container.state.form.$changed++;
                $container.initField($key, $newFieldPath, field, true);
            }
            else if (recursion) {
                if (lodash_1.default.has(field, FieldProps_1.FieldPropsEnum.fields) && !lodash_1.default.isNil(field.fields)) {
                    // handle nested fields if defined
                    this.deepUpdate(field.fields, $path);
                }
                else {
                    // handle nested fields if undefined or null
                    const $fields = (0, parser_1.pathToFieldsTree)(this.state.struct(), $path);
                    this.deepUpdate($fields, $path, false);
                }
            }
        });
    }
    /**
      Get Fields Props
     */
    get(prop = null, strict = true) {
        if (lodash_1.default.isNil(prop)) {
            return this.deepGet([...utils_1.props.computed, ...utils_1.props.editable, ...utils_1.props.validation], this.fields, strict);
        }
        (0, utils_1.allowedProps)(FieldProps_1.AllowedFieldPropsTypes.all, Array.isArray(prop) ? prop : [prop]);
        if (lodash_1.default.isString(prop)) {
            if ([
                FieldProps_1.FieldPropsEnum.hooks,
                FieldProps_1.FieldPropsEnum.handlers
            ].includes(prop)) {
                return this[`$${prop}`];
            }
            if (strict && this.fields.size === 0) {
                const retrieveNullifiedEmptyStrings = this.state.options.get(OptionsModel_1.OptionsEnum.retrieveNullifiedEmptyStrings, this);
                return (0, parser_1.parseCheckOutput)(this, prop, strict ? retrieveNullifiedEmptyStrings : false);
            }
            const value = this.deepGet(prop, this.fields, strict);
            const removeNullishValuesInArrays = this.state.options.get(OptionsModel_1.OptionsEnum.removeNullishValuesInArrays, this);
            return (0, parser_1.parseCheckArray)(this, value, prop, strict ? removeNullishValuesInArrays : false);
        }
        return this.deepGet(prop, this.fields, strict);
    }
    /**
      Get Fields Props Recursively
     */
    deepGet(prop, fields, strict = true) {
        return lodash_1.default.transform((0, utils_1.getObservableMapValues)(fields), (obj, field) => {
            const $nested = ($fields) => $fields.size !== 0
                ? this.deepGet(prop, $fields, strict)
                : undefined;
            Object.assign(obj, {
                [field.key]: { fields: $nested(field.fields) },
            });
            if (lodash_1.default.isString(prop)) {
                const opt = this.state.options;
                const removeProp = ((opt.get(OptionsModel_1.OptionsEnum.retrieveOnlyDirtyFieldsValues, this) && prop === FieldProps_1.FieldPropsEnum.value && field.isPristine) ||
                    (opt.get(OptionsModel_1.OptionsEnum.retrieveOnlyEnabledFieldsValues, this) && prop === FieldProps_1.FieldPropsEnum.value && field.disabled) ||
                    (opt.get(OptionsModel_1.OptionsEnum.retrieveOnlyEnabledFieldsErrors, this) && prop === FieldProps_1.FieldPropsEnum.error && field.disabled && field.isValid && (!field.error || !field.hasError)) ||
                    (opt.get(OptionsModel_1.OptionsEnum.softDelete, this) && prop === FieldProps_1.FieldPropsEnum.value && field.deleted));
                if (field.fields.size === 0) {
                    delete obj[field.key];
                    if (removeProp)
                        return obj;
                    const retrieveNullifiedEmptyStrings = this.state.options.get(OptionsModel_1.OptionsEnum.retrieveNullifiedEmptyStrings, this);
                    return Object.assign(obj, {
                        [field.key]: (0, parser_1.parseCheckOutput)(field, prop, strict ? retrieveNullifiedEmptyStrings : false),
                    });
                }
                let value = this.deepGet(prop, field.fields, strict);
                if (prop === FieldProps_1.FieldPropsEnum.value)
                    value = field.$output(value);
                delete obj[field.key];
                if (removeProp)
                    return obj;
                const removeNullishValuesInArrays = this.state.options.get(OptionsModel_1.OptionsEnum.removeNullishValuesInArrays, this);
                return Object.assign(obj, {
                    [field.key]: (0, parser_1.parseCheckArray)(field, value, prop, strict ? removeNullishValuesInArrays : false),
                });
            }
            lodash_1.default.each(prop, ($prop) => Object.assign(obj[field.key], {
                [$prop]: field[$prop],
            }));
            return obj;
        }, {});
    }
    /**
      Set Fields Props
     */
    set(prop, data) {
        // UPDATE CUSTOM PROP
        if (lodash_1.default.isString(prop) && !lodash_1.default.isUndefined(data)) {
            (0, utils_1.allowedProps)(FieldProps_1.AllowedFieldPropsTypes.editable, [prop]);
            const isPlain = [
                FieldProps_1.FieldPropsEnum.hooks,
                FieldProps_1.FieldPropsEnum.handlers,
            ].includes(prop);
            const deep = (lodash_1.default.isObject(data) && prop === FieldProps_1.FieldPropsEnum.value) || (lodash_1.default.isPlainObject(data) && !isPlain);
            if (deep && this.hasNestedFields)
                return this.deepSet(prop, data, "", true);
            if (prop === FieldProps_1.FieldPropsEnum.value) {
                const applyInputConverterOnSet = this.state.options.get(OptionsModel_1.OptionsEnum.applyInputConverterOnSet, this);
                this.value = (0, parser_1.parseInput)(applyInputConverterOnSet ? this.$input : (val) => val, {
                    fallbackValueOption: this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this),
                    separated: data,
                });
            }
            else if (isPlain) {
                Object.assign(this[`$${prop}`], data);
            }
            else {
                lodash_1.default.set(this, `$${prop}`, data);
            }
            return;
        }
        // NO PROP NAME PROVIDED ("prop" is value)
        if (lodash_1.default.isNil(data)) {
            if (this.hasNestedFields)
                this.deepSet(FieldProps_1.FieldPropsEnum.value, prop, "", true);
            else
                this.set(FieldProps_1.FieldPropsEnum.value, prop);
        }
    }
    /**
      Set Fields Props Recursively
     */
    deepSet(prop, data, path = "", recursion = false) {
        const err = "You are updating a not existent field:";
        const isStrict = this.state.options.get(OptionsModel_1.OptionsEnum.strictSet, this);
        if (lodash_1.default.isNil(data)) {
            this.each((field) => field.$value = (0, parser_1.defaultValue)({
                fallbackValueOption: this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this),
                value: field.$value,
                nullable: field.$nullable,
                type: field.type,
            }));
            return;
        }
        lodash_1.default.each(data, ($val, $key) => {
            const $path = lodash_1.default.trimStart(`${path}.${$key}`, ".");
            // get the field by path joining keys recursively
            const field = this.select($path, null, isStrict);
            // if no field found when is strict update, throw error
            if (isStrict)
                (0, utils_1.throwError)($path, field, err);
            // update the field/fields if defined
            if (!lodash_1.default.isUndefined(field)) {
                // update field values or others props
                if (!lodash_1.default.isUndefined($val)) {
                    field.set(prop, $val, recursion);
                }
                // update values recursively only if field has nested
                if (field.fields.size && lodash_1.default.isObject($val)) {
                    this.deepSet(prop, $val, $path, recursion);
                }
            }
        });
    }
    /**
      Add Field
     */
    add(obj, execEvent = true) {
        if ((0, utils_1.isArrayOfObjects)(obj)) {
            lodash_1.default.each(obj, (values) => this.update({
                [(0, utils_1.maxKey)(this.fields)]: values,
            }));
            this.$changed++;
            this.state.form.$changed++;
            execEvent && this.execHook(FieldProps_1.FieldPropsEnum.onAdd);
            return this;
        }
        let key;
        if (lodash_1.default.has(obj, FieldProps_1.FieldPropsEnum.key))
            key = obj.key;
        if (lodash_1.default.has(obj, FieldProps_1.FieldPropsEnum.name))
            key = obj.name;
        if (!key)
            key = (0, utils_1.maxKey)(this.fields);
        const $path = ($key) => lodash_1.default.trimStart([this.path, $key].join("."), ".");
        const tree = (0, parser_1.pathToFieldsTree)(this.state.struct(), this.path, 0, true);
        const field = this.initField(key, $path(key), lodash_1.default.merge(tree[0], obj));
        const hasValues = lodash_1.default.has(obj, FieldProps_1.FieldPropsEnum.value) || lodash_1.default.has(obj, FieldProps_1.FieldPropsEnum.fields);
        if (!hasValues && !this.state.options.get(OptionsModel_1.OptionsEnum.preserveDeletedFieldsValues, this)) {
            const fallbackValueOption = this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this);
            field.$value = (0, parser_1.defaultValue)({ fallbackValueOption, value: field.$value, nullable: field.$nullable, type: field.type });
            field.each((field) => field.$value = (0, parser_1.defaultValue)({
                fallbackValueOption,
                value: field.$value,
                nullable: field.$nullable,
                type: field.type
            }));
        }
        this.$changed++;
        this.state.form.$changed++;
        execEvent && this.execHook(FieldProps_1.FieldPropsEnum.onAdd);
        return field;
    }
    /**
      Del Field
     */
    del($path = null, execEvent = true) {
        const isStrict = this.state.options.get(OptionsModel_1.OptionsEnum.strictDelete, this);
        const path = (0, parser_1.parsePath)($path !== null && $path !== void 0 ? $path : this.path);
        const fullpath = lodash_1.default.trim([this.path, path].join("."), ".");
        const container = this.container($path);
        const keys = lodash_1.default.split(path, ".");
        const last = lodash_1.default.last(keys);
        if (isStrict && !container.fields.has(last)) {
            const msg = `Key "${last}" not found when trying to delete field`;
            (0, utils_1.throwError)(fullpath, null, msg);
        }
        container.$changed++;
        container.state.form.$changed++;
        if (this.state.options.get(OptionsModel_1.OptionsEnum.softDelete, this)) {
            return this.select(fullpath).set(FieldProps_1.FieldPropsEnum.deleted, true);
        }
        container.each((field) => field.debouncedValidation.cancel());
        execEvent && this.execHook(FieldProps_1.FieldPropsEnum.onDel);
        return container.fields.delete(last);
    }
    /******************************************************************
      Events
    */
    /**
      MobX Event (observe/intercept)
     */
    MOBXEvent({ prop = FieldProps_1.FieldPropsEnum.value, key = null, path = null, call, type }) {
        let $prop = key || prop;
        (0, utils_1.allowedProps)(FieldProps_1.AllowedFieldPropsTypes.observable, [$prop]);
        const $instance = this.select(path || this.path, null, null) || this;
        const $call = (change) => call.apply(null, [
            {
                change,
                form: this.state.form,
                path: $instance.path || null,
                field: $instance.path ? $instance : null,
            },
        ]);
        let fn;
        let ffn;
        if (type === "observer") {
            fn = mobx_1.observe;
            ffn = (cb) => (0, mobx_1.observe)($instance.fields, cb); // fields
        }
        if (type === "interceptor") {
            $prop = `$${prop}`;
            fn = mobx_1.intercept;
            ffn = $instance.fields.intercept; // fields
        }
        const $dkey = $instance.path ? `${$prop}@${$instance.path}` : $prop;
        lodash_1.default.merge(this.state.disposers[type], {
            [$dkey]: $prop === FieldProps_1.FieldPropsEnum.fields
                ? ffn.apply((change) => $call(change))
                : fn($instance, $prop, (change) => $call(change)),
        });
    }
    /**
      Dispose MOBX Events
     */
    dispose(opt = null) {
        if (this.path && opt)
            return this.disposeSingle(opt);
        return this.disposeAll();
    }
    /**
      Dispose All Events (observe/intercept)
     */
    disposeAll() {
        const dispose = (disposer) => disposer.apply();
        lodash_1.default.each(this.state.disposers.interceptor, dispose);
        lodash_1.default.each(this.state.disposers.observer, dispose);
        this.state.disposers = { interceptor: {}, observer: {} };
        return null;
    }
    /**
      Dispose Single Event (observe/intercept)
     */
    disposeSingle({ type, key = FieldProps_1.FieldPropsEnum.value, path = null }) {
        const $path = (0, parser_1.parsePath)(path !== null && path !== void 0 ? path : this.path);
        // eslint-disable-next-line
        if (type === "interceptor")
            key = `$${key}`; // target observables
        this.state.disposers[type][`${key}@${$path}`].apply();
        delete this.state.disposers[type][`${key}@${$path}`];
    }
    /******************************************************************
      Utils
    */
    /**
      Fields Selector
    */
    select(path, fields = null, isStrict = true) {
        const $path = (0, parser_1.parsePath)(path);
        const keys = lodash_1.default.split($path, ".");
        const head = lodash_1.default.head(keys);
        keys.shift();
        let $fields = lodash_1.default.isNil(fields)
            ? this.fields.get(head)
            : fields.get(head);
        let stop = false;
        lodash_1.default.each(keys, ($key) => {
            if (stop)
                return;
            if (lodash_1.default.isNil($fields)) {
                $fields = undefined;
                stop = true;
            }
            else {
                $fields = $fields.fields.get($key);
            }
        });
        if (isStrict && this.state.options.get(OptionsModel_1.OptionsEnum.strictSelect, this)) {
            (0, utils_1.throwError)(path, $fields);
        }
        return $fields;
    }
    /**
      Get Container
     */
    container($path) {
        const path = (0, parser_1.parsePath)($path !== null && $path !== void 0 ? $path : this.path);
        const cpath = lodash_1.default.trim(path.replace(new RegExp("[^./]+$"), ""), ".");
        if (!!this.path && lodash_1.default.isNil($path)) {
            return cpath !== ""
                ? this.state.form.select(cpath, null, false)
                : this.state.form;
        }
        return cpath !== "" ? this.select(cpath, null, false) : this;
    }
    /**
      Has Field
     */
    has(path) {
        return this.fields.has(path);
    }
    /**
      Map Fields
    */
    map(cb) {
        return (0, utils_1.getObservableMapValues)(this.fields).map(cb);
    }
    /**
     * Iterates deeply over fields and invokes `iteratee` for each element.
     * The iteratee is invoked with three arguments: (value, index|key, depth).
     *
     * @param {Function} iteratee The function invoked per iteration.
     * @param {Array|Object} [fields=form.fields] fields to iterate over.
     * @param {number} [depth=1] The recursion depth for internal use.
     * @returns {Array} Returns [fields.values()] of input [fields] parameter.
     * @example
     *
     * JSON.stringify(form)
     * // => {
     *   "fields": {
     *     "state": {
     *       "fields": {
     *         "city": {
     *           "fields": { "places": {
     *                "fields": {},
     *                "key": "places", "path": "state.city.places", "$value": "NY Places"
     *              }
     *           },
     *           "key": "city", "path": "state.city", "$value": "New York"
     *         }
     *       },
     *       "key": "state", "path": "state", "$value": "USA"
     *     }
     *   }
     * }
     *
     * const data = {};
     * form.each(field => data[field.path] = field.value);
     * // => {
     *   "state": "USA",
     *   "state.city": "New York",
     *   "state.city.places": "NY Places"
     * }
     *
     */
    each(iteratee, fields = null, depth = 0) {
        const $fields = fields || this.fields;
        (0, utils_1.getObservableMapValues)($fields).forEach((field, index) => {
            iteratee(field, index, depth);
            if (field.fields.size !== 0) {
                this.each(iteratee, field.fields, depth + 1);
            }
        });
    }
    reduce(iteratee, acc) {
        return (0, utils_1.getObservableMapValues)(this.fields).reduce(iteratee, acc);
    }
    /******************************************************************
      Helpers
    */
    /**
      Fields Selector (alias of select)
     */
    $(key) {
        return this.select(key);
    }
    /**
      Fields Values (recursive with Nested Fields)
     */
    values() {
        return this.get(FieldProps_1.FieldPropsEnum.value);
    }
    /**
      Fields Errors (recursive with Nested Fields)
     */
    errors() {
        return this.get(FieldProps_1.FieldPropsEnum.error);
    }
    /**
      Fields Labels (recursive with Nested Fields)
     */
    labels() {
        return this.get(FieldProps_1.FieldPropsEnum.label);
    }
    /**
      Fields Placeholders (recursive with Nested Fields)
     */
    placeholders() {
        return this.get(FieldProps_1.FieldPropsEnum.placeholder);
    }
    /**
      Fields Default Values (recursive with Nested Fields)
     */
    defaults() {
        return this.get(FieldProps_1.FieldPropsEnum.default);
    }
    /**
      Fields Initial Values (recursive with Nested Fields)
     */
    initials() {
        return this.get(FieldProps_1.FieldPropsEnum.initial);
    }
    /**
      Fields Types (recursive with Nested Fields)
     */
    types() {
        return this.get(FieldProps_1.FieldPropsEnum.type);
    }
}
exports["default"] = Base;


/***/ }),

/***/ "./src/Bindings.ts":
/*!*************************!*\
  !*** ./src/Bindings.ts ***!
  \*************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
class Bindings {
    constructor() {
        Object.defineProperty(this, "templates", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
            // default: ({ field, form, props, keys, $try }) => ({
            //   [keys.id]: $try(props.id, field.id),
            // }),
            }
        });
        Object.defineProperty(this, "rewriters", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
                default: {
                    id: FieldProps_1.FieldPropsEnum.id,
                    name: FieldProps_1.FieldPropsEnum.name,
                    type: FieldProps_1.FieldPropsEnum.type,
                    value: FieldProps_1.FieldPropsEnum.value,
                    checked: FieldProps_1.FieldPropsEnum.checked,
                    label: FieldProps_1.FieldPropsEnum.label,
                    placeholder: FieldProps_1.FieldPropsEnum.placeholder,
                    disabled: FieldProps_1.FieldPropsEnum.disabled,
                    autoComplete: FieldProps_1.FieldPropsEnum.autoComplete,
                    onChange: FieldProps_1.FieldPropsEnum.onChange,
                    onBlur: FieldProps_1.FieldPropsEnum.onBlur,
                    onFocus: FieldProps_1.FieldPropsEnum.onFocus,
                    autoFocus: FieldProps_1.FieldPropsEnum.autoFocus,
                    inputMode: FieldProps_1.FieldPropsEnum.inputMode,
                    onKeyUp: FieldProps_1.FieldPropsEnum.onKeyUp,
                    onKeyDown: FieldProps_1.FieldPropsEnum.onKeyDown,
                },
            }
        });
    }
    register(bindings) {
        lodash_1.default.each(bindings, (val, key) => {
            if ((typeof val === 'function'))
                lodash_1.default.merge(this.templates, { [key]: val });
            if (lodash_1.default.isPlainObject(val))
                lodash_1.default.merge(this.rewriters, { [key]: val });
        });
        return this;
    }
    load(field, name = FieldProps_1.FieldPropsEnum.default, props) {
        const args = ({
            keys: lodash_1.default.get(this.rewriters, FieldProps_1.FieldPropsEnum.default),
            form: field.state.form,
            field,
            props,
            $try: utils_1.$try,
        });
        if (lodash_1.default.has(this.templates, FieldProps_1.FieldPropsEnum.default)) {
            return lodash_1.default.get(this.templates, name)(args);
        }
        if (lodash_1.default.has(this.rewriters, name)) {
            const $bindings = {};
            lodash_1.default.each(lodash_1.default.get(this.rewriters, name), ($v, $k) => lodash_1.default.merge($bindings, { [$v]: (0, utils_1.$try)(props[$k], field[$k]) }));
            return $bindings;
        }
        return lodash_1.default.get(this.templates, name)(args);
    }
}
exports["default"] = Bindings;


/***/ }),

/***/ "./src/Field.ts":
/*!**********************!*\
  !*** ./src/Field.ts ***!
  \**********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const Base_1 = __importDefault(__webpack_require__(/*! ./Base */ "./src/Base.ts"));
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
const parser_1 = __webpack_require__(/*! ./parser */ "./src/parser.ts");
const OptionsModel_1 = __webpack_require__(/*! ./models/OptionsModel */ "./src/models/OptionsModel.ts");
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
const applyFieldPropFunc = (instance, prop) => {
    if (typeof prop !== 'function')
        return prop;
    return prop.apply(instance, [{
            field: instance,
            form: instance.state.form
        }]);
};
const retrieveFieldPropFunc = (prop) => (typeof prop === 'function') ? prop : undefined;
const propGetter = (instance, prop) => (typeof instance[`_${prop}`] === 'function')
    ? instance[`_${prop}`].apply(instance, [{
            form: instance.state.form,
            field: instance,
        }]) : instance[`$${prop}`];
const setupFieldProps = (instance, props, data) => Object.assign(instance, {
    // retrieve functions
    _label: retrieveFieldPropFunc(props.$label || (data === null || data === void 0 ? void 0 : data.label)),
    _placeholder: retrieveFieldPropFunc(props.$placeholder || (data === null || data === void 0 ? void 0 : data.placeholder)),
    _disabled: retrieveFieldPropFunc(props.$disabled || (data === null || data === void 0 ? void 0 : data.disabled)),
    _rules: retrieveFieldPropFunc(props.$rules || (data === null || data === void 0 ? void 0 : data.rules)),
    _related: retrieveFieldPropFunc(props.$related || (data === null || data === void 0 ? void 0 : data.related)),
    _deleted: retrieveFieldPropFunc(props.$deleted || (data === null || data === void 0 ? void 0 : data.deleted)),
    _validators: retrieveFieldPropFunc(props.$validators || (data === null || data === void 0 ? void 0 : data.validators)),
    _validatedWith: retrieveFieldPropFunc(props.$validatedWith || (data === null || data === void 0 ? void 0 : data.validatedWith)),
    _bindings: retrieveFieldPropFunc(props.$bindings || (data === null || data === void 0 ? void 0 : data.bindings)),
    _extra: retrieveFieldPropFunc(props.$extra || (data === null || data === void 0 ? void 0 : data.extra)),
    _options: retrieveFieldPropFunc(props.$options || (data === null || data === void 0 ? void 0 : data.options)),
    _autoFocus: retrieveFieldPropFunc(props.$autoFocus || (data === null || data === void 0 ? void 0 : data.autoFocus)),
    _inputMode: retrieveFieldPropFunc(props.$inputMode || (data === null || data === void 0 ? void 0 : data.inputMode)),
    // apply functions or value
    $label: applyFieldPropFunc(instance, props.$label || (data === null || data === void 0 ? void 0 : data.label) || ""),
    $placeholder: applyFieldPropFunc(instance, props.$placeholder || (data === null || data === void 0 ? void 0 : data.placeholder) || ""),
    $disabled: applyFieldPropFunc(instance, props.$disabled || (data === null || data === void 0 ? void 0 : data.disabled) || false),
    $rules: applyFieldPropFunc(instance, props.$rules || (data === null || data === void 0 ? void 0 : data.rules) || null),
    $related: applyFieldPropFunc(instance, props.$related || (data === null || data === void 0 ? void 0 : data.related) || []),
    $deleted: applyFieldPropFunc(instance, props.$deleted || (data === null || data === void 0 ? void 0 : data.deleted) || false),
    $validatedWith: applyFieldPropFunc(instance, props.$validatedWith || (data === null || data === void 0 ? void 0 : data.validatedWith) || FieldProps_1.FieldPropsEnum.value),
    $bindings: applyFieldPropFunc(instance, props.$bindings || (data === null || data === void 0 ? void 0 : data.bindings) || FieldProps_1.FieldPropsEnum.default),
    $extra: applyFieldPropFunc(instance, props.$extra || (data === null || data === void 0 ? void 0 : data.extra) || null),
    $options: applyFieldPropFunc(instance, props.$options || (data === null || data === void 0 ? void 0 : data.options) || {}),
    $autoFocus: applyFieldPropFunc(instance, props.$autoFocus || (data === null || data === void 0 ? void 0 : data.autoFocus) || false),
    $inputMode: applyFieldPropFunc(instance, props.$inputMode || (data === null || data === void 0 ? void 0 : data.inputMode) || undefined),
    $validators: applyFieldPropFunc(instance, props.$validators || (data === null || data === void 0 ? void 0 : data.validators) || null),
    // other props
    $hooks: props.$hooks || (data === null || data === void 0 ? void 0 : data.hooks) || {},
    $handlers: props.$handlers || (data === null || data === void 0 ? void 0 : data.handlers) || {},
    $observers: props.$observers || (data === null || data === void 0 ? void 0 : data.observers) || null,
    $interceptors: props.$interceptors || (data === null || data === void 0 ? void 0 : data.interceptors) || null,
    $ref: props.$ref || (data === null || data === void 0 ? void 0 : data.ref) || undefined,
    $nullable: props.$nullable || (data === null || data === void 0 ? void 0 : data.nullable) || false,
    $autoComplete: props.$autoComplete || (data === null || data === void 0 ? void 0 : data.autoComplete) || undefined,
});
const setupDefaultProp = (instance, data, props, update, { isEmptyArray, fallbackValueOption }) => (0, parser_1.parseInput)((val) => val, {
    isEmptyArray,
    type: instance.type,
    unified: update
        ? (0, parser_1.defaultValue)({
            fallbackValueOption,
            type: instance.type,
            value: instance.value
        })
        : data === null || data === void 0 ? void 0 : data.default,
    separated: props.$default,
    fallback: instance.$initial,
});
class Field extends Base_1.default {
    constructor({ key, path, struct, data = {}, props = {}, update = false, state, }) {
        super();
        Object.defineProperty(this, "hasInitialNestedFields", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "incremental", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "id", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "key", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "name", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$observers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$interceptors", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$converter", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: ($) => $
        });
        Object.defineProperty(this, "$input", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: ($) => $
        });
        Object.defineProperty(this, "$output", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: ($) => $
        });
        Object.defineProperty(this, "_value", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_label", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_placeholder", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_disabled", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_rules", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_related", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_deleted", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_validatedWith", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_validators", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_bindings", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_extra", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_options", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_autoFocus", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "_inputMode", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$options", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$value", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$type", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$label", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$placeholder", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$default", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$initial", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$bindings", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$extra", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$related", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$validatedWith", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$validators", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$rules", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$disabled", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$focused", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$blurred", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$deleted", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$autoFocus", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$inputMode", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: undefined
        });
        Object.defineProperty(this, "$ref", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: undefined
        });
        Object.defineProperty(this, "$nullable", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "$autoComplete", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: undefined
        });
        Object.defineProperty(this, "showError", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "errorSync", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "errorAsync", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "validationErrorStack", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        Object.defineProperty(this, "validationFunctionsData", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        Object.defineProperty(this, "validationAsyncData", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "debouncedValidation", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "disposeValidationOnBlur", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "disposeValidationOnChange", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "files", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        /* ------------------------------------------------------------------ */
        /* EVENTS HANDLERS */
        Object.defineProperty(this, "sync", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (0, mobx_1.action)((e, v = null) => {
                const $get = ($) => (0, utils_1.isBool)($, this.value) ? $.target.checked : $.target.value;
                // assume "v" or "e" are the values
                if (lodash_1.default.isNil(e) || lodash_1.default.isNil(e.target)) {
                    if (!lodash_1.default.isNil(v) && !lodash_1.default.isNil(v.target)) {
                        v = $get(v); // eslint-disable-line
                    }
                    this.value = (0, utils_1.$try)(e, v);
                    return;
                }
                if (!lodash_1.default.isNil(e.target)) {
                    this.value = $get(e);
                    return;
                }
                this.value = e;
            })
        });
        Object.defineProperty(this, "onSync", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.type === "file"
                ? this.onDrop(...args)
                : this.execHandler(FieldProps_1.FieldPropsEnum.onChange, args, this.sync, FieldProps_1.FieldPropsEnum.onSync)
        });
        Object.defineProperty(this, "onChange", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: this.onSync
        });
        Object.defineProperty(this, "onToggle", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onToggle, args, this.sync)
        });
        Object.defineProperty(this, "onBlur", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onBlur, args, (0, mobx_1.action)(() => {
                this.$focused = false;
                this.$blurred = true;
            }))
        });
        Object.defineProperty(this, "onFocus", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onFocus, args, (0, mobx_1.action)(() => {
                this.$focused = true;
                this.$touched = true;
            }))
        });
        Object.defineProperty(this, "onDrop", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onDrop, args, (0, mobx_1.action)(() => {
                const e = args[0];
                let files = null;
                if ((0, utils_1.isEvent)(e) && (0, utils_1.hasFiles)(e)) {
                    files = lodash_1.default.map(e.target.files);
                }
                this.files = [
                    ...lodash_1.default.map(this.files),
                    ...(files || args)
                ];
            }))
        });
        Object.defineProperty(this, "onKeyDown", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onKeyDown, args)
        });
        Object.defineProperty(this, "onKeyUp", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: (...args) => this.execHandler(FieldProps_1.FieldPropsEnum.onKeyUp, args)
        });
        (0, mobx_1.makeObservable)(this, {
            $options: mobx_1.observable,
            $value: mobx_1.observable,
            $type: mobx_1.observable,
            $label: mobx_1.observable,
            $placeholder: mobx_1.observable,
            $default: mobx_1.observable,
            $initial: mobx_1.observable,
            $bindings: mobx_1.observable,
            $extra: mobx_1.observable,
            $related: mobx_1.observable,
            $validatedWith: mobx_1.observable,
            $validators: mobx_1.observable,
            $rules: mobx_1.observable,
            $disabled: mobx_1.observable,
            $focused: mobx_1.observable,
            $blurred: mobx_1.observable,
            $deleted: mobx_1.observable,
            showError: mobx_1.observable,
            errorSync: mobx_1.observable,
            errorAsync: mobx_1.observable,
            validationErrorStack: mobx_1.observable,
            validationFunctionsData: mobx_1.observable,
            validationAsyncData: mobx_1.observable,
            files: mobx_1.observable,
            autoFocus: mobx_1.computed,
            inputMode: mobx_1.computed,
            ref: mobx_1.computed,
            checkValidationErrors: mobx_1.computed,
            checked: mobx_1.computed,
            value: mobx_1.computed,
            initial: mobx_1.computed,
            default: mobx_1.computed,
            actionRunning: mobx_1.computed,
            type: mobx_1.computed,
            label: mobx_1.computed,
            placeholder: mobx_1.computed,
            extra: mobx_1.computed,
            options: mobx_1.computed,
            bindings: mobx_1.computed,
            related: mobx_1.computed,
            disabled: mobx_1.computed,
            rules: mobx_1.computed,
            validators: mobx_1.computed,
            validatedValue: mobx_1.computed,
            error: mobx_1.computed,
            hasError: mobx_1.computed,
            isValid: mobx_1.computed,
            isDefault: mobx_1.computed,
            isDirty: mobx_1.computed,
            isPristine: mobx_1.computed,
            isEmpty: mobx_1.computed,
            blurred: mobx_1.computed,
            touched: mobx_1.computed,
            deleted: mobx_1.computed,
            setupField: mobx_1.action,
            initNestedFields: mobx_1.action,
            invalidate: mobx_1.action,
            setValidationAsyncData: mobx_1.action,
            resetValidation: mobx_1.action,
            clear: mobx_1.action,
            reset: mobx_1.action,
            focus: mobx_1.action,
            blur: mobx_1.action,
            showErrors: mobx_1.action,
            update: mobx_1.action
        });
        this.state = state;
        this.setupField(key, path, struct, data, props, update);
        // this.checkValidationPlugins();
        this.initNestedFields(data, update);
        this.incremental = this.hasIncrementalKeys;
        this.debouncedValidation = lodash_1.default.debounce(this.validate, this.state.options.get(OptionsModel_1.OptionsEnum.validationDebounceWait, this), this.state.options.get(OptionsModel_1.OptionsEnum.validationDebounceOptions, this));
        this.observeValidationOnBlur();
        this.observeValidationOnChange();
        this.initMOBXEvent(FieldProps_1.FieldPropsEnum.observers);
        this.initMOBXEvent(FieldProps_1.FieldPropsEnum.interceptors);
        // setup hooks & handlers from initialization methods
        (0, mobx_1.runInAction)(() => { var _a; return Object.assign(this.$hooks, (_a = this.hooks) === null || _a === void 0 ? void 0 : _a.apply(this, [this])); });
        (0, mobx_1.runInAction)(() => { var _a; return Object.assign(this.$handlers, (_a = this.handlers) === null || _a === void 0 ? void 0 : _a.apply(this, [this])); });
        this.execHook(FieldProps_1.FieldPropsEnum.onInit);
        // handle Field onChange Hook
        (0, mobx_1.autorun)(() => this.changed && this.execHook(FieldProps_1.FieldPropsEnum.onChange));
    }
    /* ------------------------------------------------------------------ */
    /* COMPUTED */
    get checkValidationErrors() {
        var _a;
        return ((((_a = this.validationAsyncData) === null || _a === void 0 ? void 0 : _a.valid) === false &&
            !lodash_1.default.isEmpty(this.validationAsyncData)) ||
            !lodash_1.default.isEmpty(this.validationErrorStack) ||
            lodash_1.default.isString(this.errorAsync) ||
            lodash_1.default.isString(this.errorSync));
    }
    set value(newVal) {
        if (lodash_1.default.isString(newVal) && this.state.options.get(OptionsModel_1.OptionsEnum.autoTrimValue, this)) {
            newVal = newVal.trim();
        }
        if (this.$value === newVal)
            return;
        if (this.handleSetNumberValue(newVal))
            return;
        this.$value = this.$converter(newVal);
        this.$changed++;
        if (!this.actionRunning) {
            this.state.form.$changed++;
        }
        ;
    }
    handleSetNumberValue(newVal) {
        if (!this.state.options.get(OptionsModel_1.OptionsEnum.autoParseNumbers, this))
            return false;
        if (lodash_1.default.isNumber(this.$initial) || this.type == 'number') {
            if (new RegExp("^-?\\d+(,\\d+)*(\\.\\d+([eE]\\d+)?)?$", "g").exec(newVal)) {
                this.$value = this.$converter(lodash_1.default.toNumber(newVal));
                this.$changed++;
                if (!this.actionRunning) {
                    this.state.form.$changed++;
                }
                ;
                return true;
            }
        }
    }
    get actionRunning() {
        return this.submitting || this.clearing || this.resetting;
    }
    get checked() {
        return this.type === "checkbox" ? this.value : undefined;
    }
    get value() {
        return (typeof this._value === 'function' && !this.hasNestedFields)
            ? propGetter(this, FieldProps_1.FieldPropsEnum.value)
            : this.getComputedProp(FieldProps_1.FieldPropsEnum.value);
    }
    get initial() {
        return this.$initial
            ? (0, mobx_1.toJS)(this.$initial)
            : this.getComputedProp(FieldProps_1.FieldPropsEnum.initial);
    }
    get default() {
        return this.$default
            ? (0, mobx_1.toJS)(this.$default)
            : this.getComputedProp(FieldProps_1.FieldPropsEnum.default);
    }
    set initial(val) {
        this.$initial = val;
    }
    set default(val) {
        this.$default = val;
    }
    get nullable() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.nullable);
    }
    get autoComplete() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.autoComplete);
    }
    get ref() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.ref);
    }
    get extra() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.extra);
    }
    get autoFocus() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.autoFocus);
    }
    get inputMode() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.inputMode);
    }
    get type() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.type);
    }
    get label() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.label);
    }
    get placeholder() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.placeholder);
    }
    get options() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.options);
    }
    get bindings() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.bindings);
    }
    get related() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.related);
    }
    get disabled() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.disabled);
    }
    get rules() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.rules);
    }
    get validators() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.validators);
    }
    get validatedWith() {
        return propGetter(this, FieldProps_1.FieldPropsEnum.validatedWith);
    }
    get validatedValue() {
        return (0, parser_1.parseCheckOutput)(this, this.validatedWith);
    }
    get error() {
        if (this.showError === false)
            return null;
        return this.errorAsync || this.errorSync || null;
    }
    get hasError() {
        return this.checkValidationErrors || this.check(FieldProps_1.FieldPropsEnum.hasError, true);
    }
    get isValid() {
        return !this.checkValidationErrors && this.check(FieldProps_1.FieldPropsEnum.isValid, true);
    }
    get isDefault() {
        return !lodash_1.default.isNil(this.default) && lodash_1.default.isEqual(this.default, this.value);
    }
    get isDirty() {
        const value = this.changed ? this.value : this.initial;
        return !lodash_1.default.isEqual(this.initial, value);
    }
    get isPristine() {
        const value = this.changed ? this.value : this.initial;
        return lodash_1.default.isEqual(this.initial, value);
    }
    get isEmpty() {
        if (this.hasNestedFields)
            return this.check(FieldProps_1.FieldPropsEnum.isEmpty, true);
        if (lodash_1.default.isBoolean(this.value))
            return !!this.$value;
        if (lodash_1.default.isNumber(this.value))
            return false;
        if (lodash_1.default.isDate(this.value))
            return false;
        if (lodash_1.default.isNull(this.value))
            return false;
        return lodash_1.default.isEmpty(this.value);
    }
    get focused() {
        return this.hasNestedFields ? this.check(FieldProps_1.FieldPropsEnum.focused, true) : this.$focused;
    }
    get blurred() {
        return this.hasNestedFields ? this.check(FieldProps_1.FieldPropsEnum.blurred, true) : this.$blurred;
    }
    get touched() {
        return this.hasNestedFields ? this.check(FieldProps_1.FieldPropsEnum.touched, true) : this.$touched;
    }
    get deleted() {
        return this.hasNestedFields ? this.check(FieldProps_1.FieldPropsEnum.deleted, true) : this.$deleted;
    }
    setupField($key, $path, $struct, $data, $props, update) {
        var _a;
        this.key = $key;
        this.path = $path;
        this.id = (_a = this.state.options.get(OptionsModel_1.OptionsEnum.uniqueId)) === null || _a === void 0 ? void 0 : _a.apply(this, [this]);
        const fallbackValueOption = this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this);
        const applyInputConverterOnInit = this.state.options.get(OptionsModel_1.OptionsEnum.applyInputConverterOnInit, this);
        const struct = this.state.struct();
        const structPath = (0, utils_1.pathToStruct)(this.path);
        const isEmptyArray = (0, utils_1.isArrayFromStruct)(struct, structPath);
        const { $type, $input, $output, $converter, $converters, $computed } = $props;
        if (lodash_1.default.isPlainObject($data)) {
            const { type, input, output, converter, converters, computed } = $data;
            this.name = lodash_1.default.toString($data.name || $key);
            this.$type = $type || type || "text";
            this.$converter = (0, utils_1.$try)($converter, $converters, converter, converters, this.$converter);
            this.$input = (0, utils_1.$try)($input, input, this.$input);
            this.$output = (0, utils_1.$try)($output, output, this.$output);
            const value = (0, parser_1.parseInput)(applyInputConverterOnInit ? this.$input : (val) => val, {
                fallbackValueOption,
                isEmptyArray,
                type: this.type,
                unified: computed || $data.value,
                separated: $computed || $props.$value,
                fallback: $props.$initial,
            });
            this._value = retrieveFieldPropFunc(value);
            this.$value = (typeof this._value === 'function')
                ? applyFieldPropFunc(this, value)
                : value;
            this.$initial = (0, parser_1.parseInput)((val) => val, {
                fallbackValueOption,
                isEmptyArray,
                type: this.type,
                unified: $data.initial,
                separated: $props.$initial,
                fallback: this.$value,
            });
            this.$default = setupDefaultProp(this, $data, $props, update, {
                fallbackValueOption,
                isEmptyArray,
            });
            setupFieldProps(this, $props, $data);
            return;
        }
        /* The field IS the value here */
        this.name = lodash_1.default.toString($key);
        this.$type = $type || "text";
        this.$converter = (0, utils_1.$try)($converter, $converters, this.$converter);
        this.$input = (0, utils_1.$try)($input, this.$input);
        this.$output = (0, utils_1.$try)($output, this.$output);
        const value = (0, parser_1.parseInput)(applyInputConverterOnInit ? this.$input : (val) => val, {
            fallbackValueOption,
            isEmptyArray,
            type: this.type,
            unified: $computed || $data,
            separated: $computed || $props.$value,
        });
        this._value = retrieveFieldPropFunc(value);
        this.$value = (typeof this._value === 'function')
            ? applyFieldPropFunc(this, value)
            : value;
        this.$initial = (0, parser_1.parseInput)((val) => val, {
            fallbackValueOption,
            isEmptyArray,
            type: this.type,
            unified: $data,
            separated: $props.$initial,
            fallback: this.$value,
        });
        this.$default = setupDefaultProp(this, $data, $props, update, {
            fallbackValueOption,
            isEmptyArray,
        });
        setupFieldProps(this, $props, $data);
    }
    getComputedProp(key) {
        if (this.incremental || this.hasNestedFields) {
            return (key === FieldProps_1.FieldPropsEnum.value)
                ? this.get(key, false)
                : (0, mobx_1.untracked)(() => this.get(key, false));
        }
        // @ts-ignore
        const val = this[`$${key}`];
        if (Array.isArray(val) || (0, mobx_1.isObservableArray)(val)) {
            return [].slice.call(val);
        }
        return (0, mobx_1.toJS)(val);
    }
    // checkValidationPlugins(): void {
    //   const { drivers } = this.state.form.validator;
    //   const form = this.state.form.name ? `${this.state.form.name}/` : "";
    //   if (_.isNil(drivers.dvr) && !_.isNil(this.rules)) {
    //     throw new Error(
    //       `The DVR validation rules are defined but no DVR plugin provided. Field: "${
    //         form + this.path
    //       }".`
    //     );
    //   }
    //   if (_.isNil(drivers.vjf) && !_.isNil(this.validators)) {
    //     throw new Error(
    //       `The VJF validators functions are defined but no VJF plugin provided. Field: "${
    //         form + this.path
    //       }".`
    //     );
    //   }
    // }
    initNestedFields(field, update) {
        const fields = lodash_1.default.isNil(field) ? null : field.fields;
        if (Array.isArray(fields) && !lodash_1.default.isEmpty(fields)) {
            this.hasInitialNestedFields = true;
        }
        this.initFields({ fields }, update);
        if (!update && Array.isArray(fields) && lodash_1.default.isEmpty(fields)) {
            if (Array.isArray(this.value) && !lodash_1.default.isEmpty(this.value)) {
                this.hasInitialNestedFields = true;
                this.initFields({ fields, values: this.value }, update);
            }
        }
    }
    invalidate(message, deep = true, async = false) {
        if (async === true) {
            this.errorAsync = message;
            this.showErrors(true, deep);
            return;
        }
        if (Array.isArray(message)) {
            this.validationErrorStack = message;
            this.showErrors(true, deep);
            return;
        }
        this.validationErrorStack.unshift(message);
        this.showErrors(true, deep);
    }
    setValidationAsyncData(valid = false, message = "") {
        this.validationAsyncData = { valid, message };
    }
    resetValidation(deep = false) {
        this.showError = false;
        this.errorSync = null;
        this.errorAsync = null;
        this.validationAsyncData = undefined;
        this.validationFunctionsData = [];
        this.validationErrorStack = [];
        Promise.resolve().then((0, mobx_1.action)(() => {
            this.$resetting = false;
            this.$clearing = false;
        }));
        deep && this.each((field) => field.resetValidation(deep));
    }
    clear(deep = true, execHook = true) {
        execHook && this.execHook(FieldProps_1.FieldPropsEnum.onClear);
        this.$clearing = true;
        this.$touched = false;
        this.$blurred = false;
        this.$changed = 0;
        this.files = undefined;
        this.$value = (0, parser_1.defaultValue)({
            fallbackValueOption: this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue),
            value: this.$value,
            nullable: this.$nullable,
            type: this.type,
        });
        deep && this.each((field) => field.clear(deep));
        this.state.options.get(OptionsModel_1.OptionsEnum.validateOnClear, this)
            ? this.validate({
                showErrors: this.state.options.get(OptionsModel_1.OptionsEnum.showErrorsOnClear, this),
            }) : this.resetValidation(deep);
    }
    reset(deep = true, execHook = true) {
        execHook && this.execHook(FieldProps_1.FieldPropsEnum.onReset);
        this.$resetting = true;
        this.$touched = false;
        this.$blurred = false;
        this.$changed = 0;
        this.files = undefined;
        const useDefaultValue = this.$default !== this.$initial;
        if (useDefaultValue)
            this.value = this.$default;
        if (!useDefaultValue)
            this.value = this.$initial;
        deep && this.each((field) => field.reset(deep));
        this.state.options.get(OptionsModel_1.OptionsEnum.validateOnReset, this)
            ? this.validate({
                showErrors: this.state.options.get(OptionsModel_1.OptionsEnum.showErrorsOnReset, this),
            }) : this.resetValidation(deep);
    }
    focus() {
        if (this.ref && !this.focused)
            this.ref.focus();
        this.$focused = true;
        this.$touched = true;
    }
    blur() {
        if (this.ref && this.focused)
            this.ref.blur();
        this.$focused = false;
        this.$blurred = true;
    }
    trim() {
        if (!lodash_1.default.isString(this.value))
            return;
        this.$value = this.value.trim();
    }
    showErrors(show = true, deep = true) {
        var _a, _b;
        this.showError = show;
        this.errorSync = lodash_1.default.head(this.validationErrorStack) || null;
        this.errorAsync = (((_a = this.validationAsyncData) === null || _a === void 0 ? void 0 : _a.valid) === false) ? (_b = this.validationAsyncData) === null || _b === void 0 ? void 0 : _b.message : null;
        deep && this.each((field) => field.showErrors(show, deep));
    }
    observeValidationOnBlur() {
        const opt = this.state.options;
        if (opt.get(OptionsModel_1.OptionsEnum.validateOnBlur, this)) {
            this.disposeValidationOnBlur = (0, mobx_1.observe)(this, "$focused", (change) => change.newValue === false &&
                this.debouncedValidation({
                    showErrors: opt.get(OptionsModel_1.OptionsEnum.showErrorsOnBlur, this),
                }));
        }
    }
    observeValidationOnChange() {
        const opt = this.state.options;
        if (opt.get(OptionsModel_1.OptionsEnum.validateOnChange, this)) {
            this.disposeValidationOnChange = (0, mobx_1.observe)(this, "$value", () => !this.actionRunning && this.debouncedValidation({
                showErrors: opt.get(OptionsModel_1.OptionsEnum.showErrorsOnChange, this),
            }));
        }
        else if (opt.get(OptionsModel_1.OptionsEnum.validateOnChangeAfterInitialBlur, this) ||
            opt.get(OptionsModel_1.OptionsEnum.validateOnChangeAfterSubmit, this)) {
            this.disposeValidationOnChange = (0, mobx_1.observe)(this, "$value", () => !this.actionRunning && ((opt.get(OptionsModel_1.OptionsEnum.validateOnChangeAfterInitialBlur, this) && this.blurred)
                || (opt.get(OptionsModel_1.OptionsEnum.validateOnChangeAfterSubmit, this) && this.state.form.submitted))
                && this.debouncedValidation({
                    showErrors: opt.get(OptionsModel_1.OptionsEnum.showErrorsOnChange, this),
                }));
        }
    }
    initMOBXEvent(type) {
        if (!Array.isArray(this[`$${type}`]))
            return;
        let fn;
        if (type === FieldProps_1.FieldPropsEnum.observers)
            fn = this.observe;
        if (type === FieldProps_1.FieldPropsEnum.interceptors)
            fn = this.intercept;
        this[`$${type}`].map((obj) => fn(lodash_1.default.omit(obj, FieldProps_1.FieldPropsEnum.path)));
    }
    bind(props = {}) {
        return Object.assign(Object.assign({}, this.state.bindings.load(this, this.bindings, props)), { ref: ($ref) => (this.$ref = $ref) });
    }
    update(fields) {
        if (!lodash_1.default.isPlainObject(fields)) {
            throw new Error("The update() method accepts only plain objects.");
        }
        const fallback = this.state.options.get(OptionsModel_1.OptionsEnum.fallback, this);
        const applyInputConverterOnUpdate = this.state.options.get(OptionsModel_1.OptionsEnum.applyInputConverterOnUpdate, this);
        const x = this.state.struct().findIndex(s => s.startsWith(this.path.replace(/\.\d+\./, '[].') + '[]'));
        if (!fallback && this.fields.size === 0 && x < 0) {
            this.value = (0, parser_1.parseInput)(applyInputConverterOnUpdate ? this.$input : (val) => val, {
                fallbackValueOption: this.state.options.get(OptionsModel_1.OptionsEnum.fallbackValue, this),
                separated: fields,
            });
            return;
        }
        super.update(fields);
    }
}
exports["default"] = Field;


/***/ }),

/***/ "./src/Form.ts":
/*!*********************!*\
  !*** ./src/Form.ts ***!
  \*********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const Base_1 = __importDefault(__webpack_require__(/*! ./Base */ "./src/Base.ts"));
const Validator_1 = __importDefault(__webpack_require__(/*! ./Validator */ "./src/Validator.ts"));
const State_1 = __importDefault(__webpack_require__(/*! ./State */ "./src/State.ts"));
const Field_1 = __importDefault(__webpack_require__(/*! ./Field */ "./src/Field.ts"));
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
const OptionsModel_1 = __webpack_require__(/*! ./models/OptionsModel */ "./src/models/OptionsModel.ts");
class Form extends Base_1.default {
    constructor(setup = {}, { name = "", options = {}, plugins = {}, bindings = {}, hooks = {}, handlers = {}, } = {}) {
        super();
        Object.defineProperty(this, "name", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "path", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "validator", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "debouncedValidation", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        (0, mobx_1.makeObservable)(this, {
            fields: mobx_1.observable,
            validatedValues: mobx_1.computed,
            error: mobx_1.computed,
            hasError: mobx_1.computed,
            isValid: mobx_1.computed,
            isPristine: mobx_1.computed,
            isDirty: mobx_1.computed,
            isDefault: mobx_1.computed,
            isEmpty: mobx_1.computed,
            focused: mobx_1.computed,
            touched: mobx_1.computed,
            disabled: mobx_1.computed,
            // init: action,
            invalidate: mobx_1.action,
            clear: mobx_1.action,
            reset: mobx_1.action,
            resetValidation: mobx_1.action,
        });
        this.name = name;
        (0, mobx_1.runInAction)(() => (this.$hooks = hooks));
        (0, mobx_1.runInAction)(() => (this.$handlers = handlers));
        // load data from initializers methods
        const initial = lodash_1.default.each({
            setup,
            options,
            plugins,
            bindings,
        }, (val, key) => (typeof this[key] === 'function')
            ? lodash_1.default.merge(val, this[key].apply(this, [this]))
            : val);
        // setup hooks & handlers from initialization methods
        (0, mobx_1.runInAction)(() => { var _a; return Object.assign(this.$hooks, (_a = this.hooks) === null || _a === void 0 ? void 0 : _a.apply(this, [this])); });
        (0, mobx_1.runInAction)(() => { var _a; return Object.assign(this.$handlers, (_a = this.handlers) === null || _a === void 0 ? void 0 : _a.apply(this, [this])); });
        this.state = new State_1.default({
            form: this,
            initial: initial.setup,
            options: initial.options,
            bindings: initial.bindings,
        });
        this.validator = new Validator_1.default({
            form: this,
            plugins: initial.plugins,
        });
        this.initFields(initial.setup);
        this.debouncedValidation = lodash_1.default.debounce(this.validate, this.state.options.get(OptionsModel_1.OptionsEnum.validationDebounceWait), this.state.options.get(OptionsModel_1.OptionsEnum.validationDebounceOptions));
        // execute validation on form initialization
        this.state.options.get(OptionsModel_1.OptionsEnum.validateOnInit)
            && this.validator.validate({
                showErrors: this.state.options.get(OptionsModel_1.OptionsEnum.showErrorsOnInit),
            });
        this.execHook(FieldProps_1.FieldPropsEnum.onInit);
        // handle Form onChange Hook
        (0, mobx_1.autorun)(() => this.$changed && this.execHook(FieldProps_1.FieldPropsEnum.onChange));
    }
    /* ------------------------------------------------------------------ */
    /* COMPUTED */
    get validatedValues() {
        const data = {};
        this.each(($field) => (data[$field.path] = $field.validatedValue));
        return data;
    }
    get error() {
        return this.validator.error;
    }
    get hasError() {
        return !!this.validator.error || this.check(FieldProps_1.FieldPropsEnum.hasError, true);
    }
    get isValid() {
        return !this.validator.error && this.check(FieldProps_1.FieldPropsEnum.isValid, true);
    }
    get isPristine() {
        return this.check(FieldProps_1.FieldPropsEnum.isPristine, true);
    }
    get isDirty() {
        return this.check(FieldProps_1.FieldPropsEnum.isDirty, true);
    }
    get isDefault() {
        return this.check(FieldProps_1.FieldPropsEnum.isDefault, true);
    }
    get isEmpty() {
        return this.check(FieldProps_1.FieldPropsEnum.isEmpty, true);
    }
    get focused() {
        return this.check(FieldProps_1.FieldPropsEnum.focused, true);
    }
    get touched() {
        return this.check(FieldProps_1.FieldPropsEnum.touched, true);
    }
    get disabled() {
        return this.check(FieldProps_1.FieldPropsEnum.disabled, true);
    }
    makeField(data, FieldClass = Field_1.default) {
        return new FieldClass(data);
    }
    /** DEPRECATED
      Init Form Fields and Nested Fields
  
    init($fields: any = null): void {
      _.set(this, "fields", observable.map({}));
  
      this.state.initial.props.values = $fields; // eslint-disable-line
      this.state.current.props.values = $fields; // eslint-disable-line
  
      this.initFields({
        fields: $fields || this.state.struct(),
      });
    }
    */
    invalidate(message = null, deep = true) {
        this.debouncedValidation.cancel();
        this.validator.error = message || this.state.options.get(OptionsModel_1.OptionsEnum.defaultGenericError) || true;
        deep && this.each((field) => field.debouncedValidation.cancel());
    }
    showErrors(show = true) {
        this.each((field) => field.showErrors(show));
    }
    resetValidation(deep = true) {
        this.validator.error = null;
        deep && this.each((field) => field.resetValidation(deep));
    }
    /**
      Clear Form Fields
    */
    clear(deep = true, execHook = true) {
        execHook && this.execHook(FieldProps_1.FieldPropsEnum.onClear);
        this.$touched = false;
        this.$changed = 0;
        deep && this.each((field) => field.clear(deep));
    }
    /**
      Reset Form Fields
    */
    reset(deep = true, execHook = true) {
        execHook && this.execHook(FieldProps_1.FieldPropsEnum.onReset);
        this.$touched = false;
        this.$changed = 0;
        deep && this.each((field) => field.reset(deep));
    }
}
exports["default"] = Form;


/***/ }),

/***/ "./src/Options.ts":
/*!************************!*\
  !*** ./src/Options.ts ***!
  \************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
class Options {
    constructor() {
        Object.defineProperty(this, "options", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
                uniqueId: utils_1.uniqueId,
                fallback: true,
                fallbackValue: "",
                defaultGenericError: null,
                submitThrowsError: true,
                showErrorsOnInit: false,
                showErrorsOnSubmit: true,
                showErrorsOnBlur: true,
                showErrorsOnChange: true,
                showErrorsOnClear: false,
                showErrorsOnReset: true,
                validateOnInit: true,
                validateOnSubmit: true,
                validateOnBlur: true,
                validateOnChange: false,
                validateOnChangeAfterInitialBlur: false,
                validateOnChangeAfterSubmit: false,
                validateOnClear: false,
                validateOnReset: false,
                validateDisabledFields: false,
                validateDeletedFields: false,
                validatePristineFields: true,
                strictSet: false,
                strictUpdate: false,
                strictDelete: true,
                strictSelect: true,
                softDelete: false,
                retrieveOnlyDirtyFieldsValues: false,
                retrieveOnlyEnabledFieldsValues: false,
                retrieveOnlyEnabledFieldsErrors: false,
                retrieveNullifiedEmptyStrings: false,
                autoTrimValue: false,
                autoParseNumbers: false,
                removeNullishValuesInArrays: false,
                preserveDeletedFieldsValues: false,
                validationDebounceWait: 250,
                validationDebounceOptions: {
                    leading: false,
                    trailing: true,
                },
                stopValidationOnError: false,
                validationPluginsOrder: undefined,
                resetValidationBeforeValidate: true,
                validateTrimmedValue: false,
                applyInputConverterOnInit: true,
                applyInputConverterOnSet: true,
                applyInputConverterOnUpdate: true,
            }
        });
        (0, mobx_1.makeObservable)(this, {
            options: mobx_1.observable,
            set: mobx_1.action,
        });
    }
    get(key, field = null) {
        // handle field option
        if (lodash_1.default.has(field, "path")) {
            if (lodash_1.default.has(field.$options, key)) {
                return field.$options[key];
            }
        }
        // fallback on global form options
        if (key)
            return lodash_1.default.get(this.options, key);
        return (0, mobx_1.toJS)(this.options);
    }
    set(options) {
        if (mobx_1.set) {
            (0, mobx_1.set)(this.options, options);
        }
        else {
            (0, mobx_1.extendObservable)(this.options, options);
        }
    }
}
exports["default"] = Options;


/***/ }),

/***/ "./src/State.ts":
/*!**********************!*\
  !*** ./src/State.ts ***!
  \**********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const Options_1 = __importDefault(__webpack_require__(/*! ./Options */ "./src/Options.ts"));
const Bindings_1 = __importDefault(__webpack_require__(/*! ./Bindings */ "./src/Bindings.ts"));
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
const StateInterface_1 = __webpack_require__(/*! ./models/StateInterface */ "./src/models/StateInterface.ts");
const OptionsModel_1 = __webpack_require__(/*! ./models/OptionsModel */ "./src/models/OptionsModel.ts");
class State {
    constructor({ form, initial, options, bindings }) {
        Object.defineProperty(this, "mode", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: StateInterface_1.RuntimeMode.mixed
        });
        Object.defineProperty(this, "strict", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "form", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "options", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "bindings", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$extra", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "$struct", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        Object.defineProperty(this, "disposers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
                interceptor: {},
                observer: {},
            }
        });
        Object.defineProperty(this, "initial", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
                props: {},
                fields: {},
            }
        });
        Object.defineProperty(this, "current", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
                props: {},
                fields: {},
            }
        });
        this.set("form", form);
        this.initProps(initial);
        this.options = new Options_1.default();
        this.options.set(options);
        this.bindings = new Bindings_1.default();
        this.bindings.register(bindings);
        this.observeOptions();
    }
    initProps(initial = {}) {
        const initialProps = lodash_1.default.pick(initial, [
            ...utils_1.props.editable,
            ...utils_1.props.separated,
            ...utils_1.props.validation,
            ...utils_1.props.functions,
            ...utils_1.props.handlers,
        ]);
        this.set("initial", "props", initialProps);
        const $unified = (0, utils_1.hasUnifiedProps)(initial);
        const $separated = (0, utils_1.hasSeparatedProps)(initial);
        if (($separated || (0, utils_1.isArrayOfStrings)(initial.fields)) && !$unified) {
            const struct = (0, utils_1.$try)(initial.struct, initial.fields);
            this.struct(struct);
            this.strict = true;
            this.mode = StateInterface_1.RuntimeMode.separated;
            return;
        }
        this.struct(initial.struct);
        this.mode = StateInterface_1.RuntimeMode.unified;
    }
    /**
      Get/Set Fields Structure
    */
    struct(data = null) {
        if (data)
            this.$struct = data;
        return this.$struct;
    }
    /**
      Get Props/Fields
    */
    get(type, subtype) {
        return this[type][subtype];
    }
    /**
      Set Props/Fields
    */
    set(type, subtype, state = null) {
        if (type === "form") {
            // subtype is the form here
            this.form = subtype;
        }
        if (type === "initial") {
            Object.assign(this.initial[subtype], state);
            Object.assign(this.current[subtype], state);
        }
        if (type === "current") {
            Object.assign(this.current[subtype], state);
        }
    }
    extra(data = null) {
        if (lodash_1.default.isString(data))
            return lodash_1.default.get(this.$extra, data);
        if (data === null)
            return this.$extra;
        this.$extra = data;
        return null;
    }
    observeOptions() {
        // Fix Issue #201
        (0, mobx_1.observe)(this.options.options, (0, utils_1.checkObserve)([
            {
                // start observing fields validateOnChange
                type: "update",
                key: OptionsModel_1.OptionsEnum.validateOnChange,
                to: true,
                exec: () => this.form.each((field) => field.observeValidationOnChange()),
            },
            {
                // stop observing fields validateOnChange
                type: "update",
                key: OptionsModel_1.OptionsEnum.validateOnChange,
                to: false,
                exec: () => this.form.each((field) => field.disposeValidationOnChange()),
            },
            {
                // start observing fields validateOnBlur
                type: "update",
                key: OptionsModel_1.OptionsEnum.validateOnBlur,
                to: true,
                exec: () => this.form.each((field) => field.observeValidationOnBlur()),
            },
            {
                // stop observing fields validateOnBlur
                type: "update",
                key: OptionsModel_1.OptionsEnum.validateOnBlur,
                to: false,
                exec: () => this.form.each((field) => field.disposeValidationOnBlur()),
            },
        ]));
    }
}
exports["default"] = State;


/***/ }),

/***/ "./src/Validator.ts":
/*!**************************!*\
  !*** ./src/Validator.ts ***!
  \**************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
const OptionsModel_1 = __webpack_require__(/*! ./models/OptionsModel */ "./src/models/OptionsModel.ts");
class Validator {
    constructor(obj) {
        Object.defineProperty(this, "promises", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: []
        });
        Object.defineProperty(this, "form", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "drivers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {}
        });
        Object.defineProperty(this, "plugins", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: {
                vjf: undefined,
                dvr: undefined,
                svk: undefined,
                yup: undefined,
                zod: undefined,
                joi: undefined,
            }
        });
        Object.defineProperty(this, "error", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        (0, mobx_1.makeObservable)(this, {
            error: mobx_1.observable,
            validate: mobx_1.action,
            validateField: mobx_1.action,
        });
        this.form = obj.form;
        Object.assign(this.plugins, obj.plugins);
        this.initDrivers();
    }
    initDrivers() {
        lodash_1.default.map(this.plugins, (plugin, key) => (this.drivers[key] = (plugin && plugin.class) &&
            new plugin.class({
                config: plugin.config,
                state: this.form.state,
                promises: this.promises,
            })));
    }
    validate(opt, obj) {
        const path = (0, utils_1.$try)(opt === null || opt === void 0 ? void 0 : opt.path, opt);
        const instance = (0, utils_1.$try)(opt === null || opt === void 0 ? void 0 : opt.field, this.form.select(path, null, false), this.form);
        const related = (0, utils_1.$try)(opt === null || opt === void 0 ? void 0 : opt.related, obj === null || obj === void 0 ? void 0 : obj.related, true);
        const showErrors = (0, utils_1.$try)(opt === null || opt === void 0 ? void 0 : opt.showErrors, obj === null || obj === void 0 ? void 0 : obj.showErrors, false);
        instance.$validating = true;
        instance.$validated += 1;
        this.error = null;
        return new Promise((resolve) => {
            // validate instance (form or filed)
            if (instance.path || lodash_1.default.isString(path)) {
                this.validateField({
                    field: instance,
                    showErrors,
                    related,
                    path,
                });
            }
            // validate nested fields
            instance.each((field) => this.validateField({
                path: field.path,
                field: field,
                showErrors,
                related,
            }));
            // wait all promises
            resolve(Promise.all(this.promises));
        })
            .then((0, mobx_1.action)(() => {
            instance.$validating = false;
            instance.$clearing = false;
            instance.$resetting = false;
        }))
            .catch((0, mobx_1.action)((err) => {
            instance.$validating = false;
            instance.$clearing = false;
            instance.$resetting = false;
            throw err;
        }))
            .then(() => instance);
    }
    validateField({ showErrors = false, related = false, field = null, path, }) {
        const instance = field || this.form.select(path);
        const { options } = this.form.state;
        // check if the field is a valid instance
        if (!instance.path)
            throw new Error("Validation Error: Invalid Field Instance");
        // do not validate soft deleted fields
        if (instance.deleted && !options.get(OptionsModel_1.OptionsEnum.validateDeletedFields, instance))
            return;
        // do not validate disabled fields
        if (instance.disabled && !options.get(OptionsModel_1.OptionsEnum.validateDisabledFields, instance))
            return;
        // do not validate pristine fields
        if (instance.isPristine && !options.get(OptionsModel_1.OptionsEnum.validatePristineFields, instance))
            return;
        // reset validation before validate
        if (options.get(OptionsModel_1.OptionsEnum.resetValidationBeforeValidate, instance))
            instance.resetValidation();
        // trim string value before validation
        if (options.get(OptionsModel_1.OptionsEnum.validateTrimmedValue, instance))
            instance.trim();
        // get stop on error
        const stopOnError = options.get(OptionsModel_1.OptionsEnum.stopValidationOnError, instance);
        // get validation plugin order
        const validationPluginOrder = options.get(OptionsModel_1.OptionsEnum.validationPluginsOrder, instance);
        const drivers = validationPluginOrder
            ? validationPluginOrder.map((n) => this.drivers[n])
            : this.drivers;
        // validate with all enabled drivers
        lodash_1.default.each(drivers, (driver) => {
            driver && driver.validate(instance);
            if (stopOnError && instance.hasError)
                return;
        });
        // send error to the view
        instance.showErrors(showErrors, false);
        // related validation
        if (related)
            this.validateRelatedFields(instance, showErrors);
    }
    /**
      Validate 'related' fields if specified
      and related validation allowed (recursive)
    */
    validateRelatedFields(field, showErrors) {
        if (!field.related || !field.related.length)
            return;
        field.related.map((path) => this.validateField({
            related: false,
            showErrors,
            path,
        }));
    }
}
exports["default"] = Validator;


/***/ }),

/***/ "./src/index.ts":
/*!**********************!*\
  !*** ./src/index.ts ***!
  \**********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Field = exports.Form = void 0;
const Form_1 = __importDefault(__webpack_require__(/*! ./Form */ "./src/Form.ts"));
exports.Form = Form_1.default;
const Field_1 = __importDefault(__webpack_require__(/*! ./Field */ "./src/Field.ts"));
exports.Field = Field_1.default;
exports["default"] = Form_1.default;


/***/ }),

/***/ "./src/models/FieldProps.ts":
/*!**********************************!*\
  !*** ./src/models/FieldProps.ts ***!
  \**********************************/
/***/ ((__unused_webpack_module, exports) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SeparatedPropsMode = exports.FieldPropsOccurrence = exports.AllowedFieldPropsTypes = exports.FieldPropsEnum = void 0;
var FieldPropsEnum;
(function (FieldPropsEnum) {
    FieldPropsEnum["key"] = "key";
    FieldPropsEnum["id"] = "id";
    FieldPropsEnum["path"] = "path";
    FieldPropsEnum["name"] = "name";
    FieldPropsEnum["fields"] = "fields";
    FieldPropsEnum["ref"] = "ref";
    FieldPropsEnum["type"] = "type";
    FieldPropsEnum["computed"] = "computed";
    FieldPropsEnum["value"] = "value";
    FieldPropsEnum["initial"] = "initial";
    FieldPropsEnum["default"] = "default";
    FieldPropsEnum["checked"] = "checked";
    FieldPropsEnum["label"] = "label";
    FieldPropsEnum["placeholder"] = "placeholder";
    FieldPropsEnum["error"] = "error";
    FieldPropsEnum["validatedWith"] = "validatedWith";
    FieldPropsEnum["validators"] = "validators";
    FieldPropsEnum["rules"] = "rules";
    FieldPropsEnum["related"] = "related";
    FieldPropsEnum["options"] = "options";
    FieldPropsEnum["extra"] = "extra";
    FieldPropsEnum["bindings"] = "bindings";
    FieldPropsEnum["hooks"] = "hooks";
    FieldPropsEnum["handlers"] = "handlers";
    FieldPropsEnum["converter"] = "converter";
    FieldPropsEnum["input"] = "input";
    FieldPropsEnum["output"] = "output";
    FieldPropsEnum["interceptors"] = "interceptors";
    FieldPropsEnum["observers"] = "observers";
    // computed
    FieldPropsEnum["disabled"] = "disabled";
    FieldPropsEnum["deleted"] = "deleted";
    FieldPropsEnum["blurred"] = "blurred";
    FieldPropsEnum["validating"] = "validating";
    FieldPropsEnum["submitting"] = "submitting";
    FieldPropsEnum["clearing"] = "clearing";
    FieldPropsEnum["resetting"] = "resetting";
    FieldPropsEnum["changed"] = "changed";
    FieldPropsEnum["touched"] = "touched";
    FieldPropsEnum["focused"] = "focused";
    FieldPropsEnum["isEmpty"] = "isEmpty";
    FieldPropsEnum["isDefault"] = "isDefault";
    FieldPropsEnum["isPristine"] = "isPristine";
    FieldPropsEnum["isDirty"] = "isDirty";
    FieldPropsEnum["isValid"] = "isValid";
    FieldPropsEnum["hasError"] = "hasError";
    // handlers
    FieldPropsEnum["onInit"] = "onInit";
    FieldPropsEnum["onSync"] = "onSync";
    FieldPropsEnum["onChange"] = "onChange";
    FieldPropsEnum["onBlur"] = "onBlur";
    FieldPropsEnum["onFocus"] = "onFocus";
    FieldPropsEnum["onToggle"] = "onToggle";
    FieldPropsEnum["onDrop"] = "onDrop";
    FieldPropsEnum["onSubmit"] = "onSubmit";
    FieldPropsEnum["onReset"] = "onReset";
    FieldPropsEnum["onClear"] = "onClear";
    FieldPropsEnum["onAdd"] = "onAdd";
    FieldPropsEnum["onDel"] = "onDel";
    FieldPropsEnum["autoFocus"] = "autoFocus";
    FieldPropsEnum["inputMode"] = "inputMode";
    FieldPropsEnum["onKeyDown"] = "onKeyDown";
    FieldPropsEnum["onKeyUp"] = "onKeyUp";
    FieldPropsEnum["class"] = "class";
    FieldPropsEnum["nullable"] = "nullable";
    FieldPropsEnum["autoComplete"] = "autoComplete";
})(FieldPropsEnum = exports.FieldPropsEnum || (exports.FieldPropsEnum = {}));
var AllowedFieldPropsTypes;
(function (AllowedFieldPropsTypes) {
    AllowedFieldPropsTypes["computed"] = "computed";
    AllowedFieldPropsTypes["observable"] = "observable";
    AllowedFieldPropsTypes["editable"] = "editable";
    AllowedFieldPropsTypes["all"] = "all";
})(AllowedFieldPropsTypes = exports.AllowedFieldPropsTypes || (exports.AllowedFieldPropsTypes = {}));
var FieldPropsOccurrence;
(function (FieldPropsOccurrence) {
    FieldPropsOccurrence["some"] = "some";
    FieldPropsOccurrence["every"] = "every";
})(FieldPropsOccurrence = exports.FieldPropsOccurrence || (exports.FieldPropsOccurrence = {}));
var SeparatedPropsMode;
(function (SeparatedPropsMode) {
    SeparatedPropsMode["computed"] = "computed";
    SeparatedPropsMode["values"] = "values";
    SeparatedPropsMode["labels"] = "labels";
    SeparatedPropsMode["placeholders"] = "placeholders";
    SeparatedPropsMode["defaults"] = "defaults";
    SeparatedPropsMode["initials"] = "initials";
    SeparatedPropsMode["disabled"] = "disabled";
    SeparatedPropsMode["deleted"] = "deleted";
    SeparatedPropsMode["types"] = "types";
    SeparatedPropsMode["related"] = "related";
    SeparatedPropsMode["rules"] = "rules";
    SeparatedPropsMode["options"] = "options";
    SeparatedPropsMode["bindings"] = "bindings";
    SeparatedPropsMode["extra"] = "extra";
    SeparatedPropsMode["hooks"] = "hooks";
    SeparatedPropsMode["handlers"] = "handlers";
    SeparatedPropsMode["validatedWith"] = "validatedWith";
    SeparatedPropsMode["validators"] = "validators";
    SeparatedPropsMode["observers"] = "observers";
    SeparatedPropsMode["interceptors"] = "interceptors";
    SeparatedPropsMode["converters"] = "converters";
    SeparatedPropsMode["input"] = "input";
    SeparatedPropsMode["output"] = "output";
    SeparatedPropsMode["autoFocus"] = "autoFocus";
    SeparatedPropsMode["inputMode"] = "inputMode";
    SeparatedPropsMode["refs"] = "refs";
    SeparatedPropsMode["classes"] = "classes";
    SeparatedPropsMode["nullable"] = "nullable";
    SeparatedPropsMode["autoComplete"] = "autoComplete";
})(SeparatedPropsMode = exports.SeparatedPropsMode || (exports.SeparatedPropsMode = {}));


/***/ }),

/***/ "./src/models/OptionsModel.ts":
/*!************************************!*\
  !*** ./src/models/OptionsModel.ts ***!
  \************************************/
/***/ ((__unused_webpack_module, exports) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.OptionsEnum = void 0;
var OptionsEnum;
(function (OptionsEnum) {
    OptionsEnum["uniqueId"] = "uniqueId";
    OptionsEnum["fallback"] = "fallback";
    OptionsEnum["fallbackValue"] = "fallbackValue";
    OptionsEnum["defaultGenericError"] = "defaultGenericError";
    OptionsEnum["submitThrowsError"] = "submitThrowsError";
    OptionsEnum["showErrorsOnInit"] = "showErrorsOnInit";
    OptionsEnum["showErrorsOnSubmit"] = "showErrorsOnSubmit";
    OptionsEnum["showErrorsOnBlur"] = "showErrorsOnBlur";
    OptionsEnum["showErrorsOnChange"] = "showErrorsOnChange";
    OptionsEnum["showErrorsOnClear"] = "showErrorsOnClear";
    OptionsEnum["showErrorsOnReset"] = "showErrorsOnReset";
    OptionsEnum["validateOnInit"] = "validateOnInit";
    OptionsEnum["validateOnSubmit"] = "validateOnSubmit";
    OptionsEnum["validateOnBlur"] = "validateOnBlur";
    OptionsEnum["validateOnChange"] = "validateOnChange";
    OptionsEnum["validateOnChangeAfterInitialBlur"] = "validateOnChangeAfterInitialBlur";
    OptionsEnum["validateOnChangeAfterSubmit"] = "validateOnChangeAfterSubmit";
    OptionsEnum["validateDisabledFields"] = "validateDisabledFields";
    OptionsEnum["validateDeletedFields"] = "validateDeletedFields";
    OptionsEnum["validatePristineFields"] = "validatePristineFields";
    OptionsEnum["validateTrimmedValue"] = "validateTrimmedValue";
    OptionsEnum["validateOnClear"] = "validateOnClear";
    OptionsEnum["validateOnReset"] = "validateOnReset";
    OptionsEnum["strictSet"] = "strictSet";
    OptionsEnum["strictUpdate"] = "strictUpdate";
    OptionsEnum["strictDelete"] = "strictDelete";
    OptionsEnum["strictSelect"] = "strictSelect";
    OptionsEnum["softDelete"] = "softDelete";
    OptionsEnum["retrieveOnlyDirtyFieldsValues"] = "retrieveOnlyDirtyFieldsValues";
    OptionsEnum["retrieveOnlyEnabledFieldsValues"] = "retrieveOnlyEnabledFieldsValues";
    OptionsEnum["retrieveOnlyEnabledFieldsErrors"] = "retrieveOnlyEnabledFieldsErrors";
    OptionsEnum["retrieveNullifiedEmptyStrings"] = "retrieveNullifiedEmptyStrings";
    OptionsEnum["removeNullishValuesInArrays"] = "removeNullishValuesInArrays";
    OptionsEnum["preserveDeletedFieldsValues"] = "preserveDeletedFieldsValues";
    OptionsEnum["autoTrimValue"] = "autoTrimValue";
    OptionsEnum["autoParseNumbers"] = "autoParseNumbers";
    OptionsEnum["validationDebounceWait"] = "validationDebounceWait";
    OptionsEnum["validationDebounceOptions"] = "validationDebounceOptions";
    OptionsEnum["stopValidationOnError"] = "stopValidationOnError";
    OptionsEnum["validationPluginsOrder"] = "validationPluginsOrder";
    OptionsEnum["resetValidationBeforeValidate"] = "resetValidationBeforeValidate";
    OptionsEnum["applyInputConverterOnInit"] = "applyInputConverterOnInit";
    OptionsEnum["applyInputConverterOnSet"] = "applyInputConverterOnSet";
    OptionsEnum["applyInputConverterOnUpdate"] = "applyInputConverterOnUpdate";
})(OptionsEnum = exports.OptionsEnum || (exports.OptionsEnum = {}));


/***/ }),

/***/ "./src/models/StateInterface.ts":
/*!**************************************!*\
  !*** ./src/models/StateInterface.ts ***!
  \**************************************/
/***/ ((__unused_webpack_module, exports) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.RuntimeMode = void 0;
var RuntimeMode;
(function (RuntimeMode) {
    RuntimeMode["mixed"] = "mixed";
    RuntimeMode["unified"] = "unified";
    RuntimeMode["separated"] = "separated";
})(RuntimeMode = exports.RuntimeMode || (exports.RuntimeMode = {}));


/***/ }),

/***/ "./src/models/ValidatorInterface.ts":
/*!******************************************!*\
  !*** ./src/models/ValidatorInterface.ts ***!
  \******************************************/
/***/ ((__unused_webpack_module, exports) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ValidationHooks = void 0;
var ValidationHooks;
(function (ValidationHooks) {
    ValidationHooks["onSuccess"] = "onSuccess";
    ValidationHooks["onError"] = "onError";
})(ValidationHooks = exports.ValidationHooks || (exports.ValidationHooks = {}));


/***/ }),

/***/ "./src/parser.ts":
/*!***********************!*\
  !*** ./src/parser.ts ***!
  \***********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.pathToFieldsTree = exports.prepareFieldsData = exports.handleFieldsArrayOfStrings = exports.handleFieldsNested = exports.mergeSchemaDefaults = exports.parseCheckOutput = exports.parseCheckArray = exports.parseArrayProp = exports.parsePath = exports.parseInput = exports.defaultValue = void 0;
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
const utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
const defaultValue = ({ type = undefined, value = undefined, nullable = undefined, isEmptyArray = false, fallbackValueOption = "", }) => {
    if (Array.isArray(value) || isEmptyArray)
        return [];
    if (nullable || lodash_1.default.isDate(value) || type === "date" || type === "datetime-local")
        return null;
    if (lodash_1.default.isNumber(value) || type === "number")
        return 0;
    if (lodash_1.default.isBoolean(value) || type === "checkbox")
        return false;
    if (lodash_1.default.isString(value) || type === "file")
        return "";
    return fallbackValueOption;
};
exports.defaultValue = defaultValue;
const parsePath = (path) => {
    let $path = path;
    $path = lodash_1.default.replace($path, new RegExp("\\[", "g"), ".");
    $path = lodash_1.default.replace($path, new RegExp("\\]", "g"), "");
    return $path;
};
exports.parsePath = parsePath;
const parseInput = (input, { fallbackValueOption = "", type, isEmptyArray, separated, unified, fallback }) => input((0, utils_1.$try)(separated, unified, fallback, defaultValue({
    fallbackValueOption,
    type,
    isEmptyArray,
})));
exports.parseInput = parseInput;
const parseArrayProp = (val, prop, removeNullishValuesInArrays) => {
    const values = lodash_1.default.values(val);
    const isValProp = [
        FieldProps_1.FieldPropsEnum.value,
        FieldProps_1.FieldPropsEnum.initial,
        FieldProps_1.FieldPropsEnum.default,
    ].includes(prop);
    if (removeNullishValuesInArrays && isValProp) {
        return lodash_1.default.without(values, ...[null, undefined, ""]);
    }
    return values;
};
exports.parseArrayProp = parseArrayProp;
const parseCheckArray = (field, value, prop, removeNullishValuesInArrays) => {
    if (field.incremental && lodash_1.default.isObject(value) && lodash_1.default.isEmpty(value))
        return [];
    return field.hasIncrementalKeys ? parseArrayProp(value, prop, removeNullishValuesInArrays) : value;
};
exports.parseCheckArray = parseCheckArray;
const parseCheckOutput = (field, prop, retrieveNullifiedEmptyStrings = false) => {
    if (prop === FieldProps_1.FieldPropsEnum.value || prop.startsWith("value.")) {
        const base = field.$output ? field.$output(field[FieldProps_1.FieldPropsEnum.value]) : field[FieldProps_1.FieldPropsEnum.value];
        const value = prop.startsWith("value.") ? lodash_1.default.get(base, prop.substring(6)) : base;
        if (lodash_1.default.isString(value) && lodash_1.default.isEmpty(value) && retrieveNullifiedEmptyStrings)
            return null;
        return value;
    }
    return field[prop];
};
exports.parseCheckOutput = parseCheckOutput;
const defineFieldsFromStruct = (struct, add = false) => lodash_1.default.reduceRight(struct, ($, name) => {
    const obj = {};
    if (lodash_1.default.endsWith(name, "[]")) {
        const val = add ? [$] : [];
        obj[lodash_1.default.trimEnd(name, "[]")] = val;
        return obj;
    }
    // no brakets
    const prev = struct[struct.indexOf(name) - 1];
    const stop = lodash_1.default.endsWith(prev, "[]") && lodash_1.default.last(struct) === name;
    if (!add && stop)
        return obj;
    obj[name] = $;
    return obj;
}, {});
const handleFieldsArrayOfStrings = ($fields, add = false) => {
    let fields = $fields;
    // handle array with field struct (strings)
    if ((0, utils_1.isArrayOfStrings)(fields)) {
        fields = lodash_1.default.transform(fields, ($obj, $) => {
            const pathStruct = lodash_1.default.split($, ".");
            // as array of strings (with empty values)
            if (!pathStruct.length)
                return Object.assign($obj, { [$]: "" });
            // define flat or nested fields from pathStruct
            return lodash_1.default.merge($obj, defineFieldsFromStruct(pathStruct, add));
        }, {});
    }
    return fields;
};
exports.handleFieldsArrayOfStrings = handleFieldsArrayOfStrings;
const handleFieldsArrayOfObjects = ($fields) => {
    let fields = $fields;
    // handle array of objects (with unified props)
    if ((0, utils_1.isArrayOfObjects)(fields)) {
        fields = lodash_1.default.transform(fields, ($obj, field) => {
            if ((0, utils_1.hasUnifiedProps)({ fields: { field } }) && !lodash_1.default.has(field, FieldProps_1.FieldPropsEnum.name))
                return undefined;
            return Object.assign($obj, { [field.name]: field });
        }, {});
    }
    return fields;
};
const handleFieldsNested = (fields, strictProps = true) => lodash_1.default.transform(fields, (obj, field, key) => {
    if ((0, utils_1.allowNested)(field, strictProps)) {
        // define nested field
        return Object.assign(obj, {
            [key]: {
                fields: (0, utils_1.isEmptyArray)(field) ? [] : handleFieldsNested(field),
            },
        });
    }
    return Object.assign(obj, { [key]: field });
}, {});
exports.handleFieldsNested = handleFieldsNested;
/* mapNestedValuesToUnifiedValues

FROM:

{
  street: '123 Fake St.',
  zip: '12345',
}

TO:

[{
  name: 'street'
  value: '123 Fake St.',
}, {
  name: 'zip'
  value: '12345',
}]

*/
const mapNestedValuesToUnifiedValues = (data) => lodash_1.default.isPlainObject(data)
    ? lodash_1.default.map(data, (value, name) => ({ value, name }))
    : undefined;
/* reduceValuesToUnifiedFields

FROM:

{
  name: 'fatty',
  address: {
    street: '123 Fake St.',
    zip: '12345',
  },
};

TO:

{
  name: {
    value: 'fatty',
    fields: undefined
  },
  address: {
    value: {
      street: '123 Fake St.',
      zip: '12345'
    },
    fields: [ ... ]
  },
};

*/
const reduceValuesToUnifiedFields = (values) => lodash_1.default.transform(values, (obj, value, key) => Object.assign(obj, {
    [key]: {
        value,
        fields: mapNestedValuesToUnifiedValues(value),
    },
}), {});
/*
  Fallback Unified Props to Separated Mode
*/
const handleFieldsPropsFallback = (fields, initial, fallback) => {
    if (!lodash_1.default.has(initial, FieldProps_1.SeparatedPropsMode.values))
        return fields;
    // if the 'values' object is passed in constructor
    // then update the fields definitions
    let { values } = initial;
    if ((0, utils_1.hasUnifiedProps)({ fields: initial.fields })) {
        values = reduceValuesToUnifiedFields(values);
    }
    return lodash_1.default.merge(fields, lodash_1.default.transform(values, (result, v, k) => {
        if (Array.isArray(fields[k]))
            result[k] = v;
        if (!(k in fields) && (!isNaN(Number(k)) || fallback))
            result[k] = v;
    }, {}));
};
const mergeSchemaDefaults = (fields, validator) => {
    if (validator) {
        const schema = lodash_1.default.get(validator.plugins, "svk.config.schema");
        if (lodash_1.default.isEmpty(fields) && schema && !!schema.properties) {
            lodash_1.default.each(schema.properties, (prop, key) => {
                lodash_1.default.set(fields, key, {
                    value: prop.default,
                    label: prop.title,
                });
            });
        }
    }
    return fields;
};
exports.mergeSchemaDefaults = mergeSchemaDefaults;
const prepareFieldsData = (initial, strictProps = true, fallback = true) => {
    let fields = lodash_1.default.merge(handleFieldsArrayOfStrings(initial.fields, false), handleFieldsArrayOfStrings(initial.struct, false));
    fields = handleFieldsArrayOfObjects(fields);
    fields = handleFieldsPropsFallback(fields, initial, fallback);
    fields = handleFieldsNested(fields, strictProps);
    return fields;
};
exports.prepareFieldsData = prepareFieldsData;
const pathToFieldsTree = (struct, path, n = 0, add = false) => {
    const structPath = (0, utils_1.pathToStruct)(path);
    const structArray = lodash_1.default.filter(struct, (item) => lodash_1.default.startsWith(item, structPath));
    const $tree = handleFieldsArrayOfStrings(structArray, add);
    const $struct = lodash_1.default.replace(structPath, new RegExp("\\[]", "g"), `[${n}]`);
    const fields = handleFieldsNested(lodash_1.default.get($tree, $struct));
    // fix issues #614 & #615
    struct.length && struct
        .filter(s => s.startsWith(path + '[]'))
        .map(s => s.substring((path + '[].').length))
        .filter(s => s.endsWith('[]'))
        .map(s => s.substring(0, s.length - 2))
        .forEach(s => {
        var _a, _b;
        const ss = s.split('.');
        let t = (_a = fields[0]) === null || _a === void 0 ? void 0 : _a.fields;
        for (let i = 0; i < ss.length; i++) {
            t = (_b = t === null || t === void 0 ? void 0 : t[ss[i]]) === null || _b === void 0 ? void 0 : _b[FieldProps_1.FieldPropsEnum.fields];
            if (!t)
                break;
        }
        if (t)
            delete t[0];
    });
    return fields;
};
exports.pathToFieldsTree = pathToFieldsTree;


/***/ }),

/***/ "./src/props.ts":
/*!**********************!*\
  !*** ./src/props.ts ***!
  \**********************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.props = void 0;
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
exports.props = {
    editable: [
        FieldProps_1.FieldPropsEnum.type,
        FieldProps_1.FieldPropsEnum.value,
        FieldProps_1.FieldPropsEnum.initial,
        FieldProps_1.FieldPropsEnum.default,
        FieldProps_1.FieldPropsEnum.label,
        FieldProps_1.FieldPropsEnum.placeholder,
        FieldProps_1.FieldPropsEnum.related,
        FieldProps_1.FieldPropsEnum.options,
        FieldProps_1.FieldPropsEnum.extra,
        FieldProps_1.FieldPropsEnum.bindings,
        FieldProps_1.FieldPropsEnum.hooks,
        FieldProps_1.FieldPropsEnum.handlers,
        FieldProps_1.FieldPropsEnum.deleted,
        FieldProps_1.FieldPropsEnum.disabled,
        FieldProps_1.FieldPropsEnum.autoFocus,
        FieldProps_1.FieldPropsEnum.inputMode,
        FieldProps_1.FieldPropsEnum.ref,
        FieldProps_1.FieldPropsEnum.nullable,
        FieldProps_1.FieldPropsEnum.autoComplete,
    ],
    handlers: [
        FieldProps_1.FieldPropsEnum.onChange,
        FieldProps_1.FieldPropsEnum.onToggle,
        FieldProps_1.FieldPropsEnum.onFocus,
        FieldProps_1.FieldPropsEnum.onBlur,
        FieldProps_1.FieldPropsEnum.onDrop,
        FieldProps_1.FieldPropsEnum.onSubmit,
        FieldProps_1.FieldPropsEnum.onReset,
        FieldProps_1.FieldPropsEnum.onClear,
        FieldProps_1.FieldPropsEnum.onAdd,
        FieldProps_1.FieldPropsEnum.onDel,
    ],
    computed: [
        FieldProps_1.FieldPropsEnum.error,
        FieldProps_1.FieldPropsEnum.hasError,
        FieldProps_1.FieldPropsEnum.isValid,
        FieldProps_1.FieldPropsEnum.isDirty,
        FieldProps_1.FieldPropsEnum.isPristine,
        FieldProps_1.FieldPropsEnum.isDefault,
        FieldProps_1.FieldPropsEnum.isEmpty,
        FieldProps_1.FieldPropsEnum.focused,
        FieldProps_1.FieldPropsEnum.touched,
        FieldProps_1.FieldPropsEnum.changed,
        FieldProps_1.FieldPropsEnum.validating,
        FieldProps_1.FieldPropsEnum.submitting,
        FieldProps_1.FieldPropsEnum.resetting,
        FieldProps_1.FieldPropsEnum.clearing,
        FieldProps_1.FieldPropsEnum.blurred,
        FieldProps_1.FieldPropsEnum.deleted,
        FieldProps_1.FieldPropsEnum.disabled,
    ],
    separated: [
        FieldProps_1.SeparatedPropsMode.computed,
        FieldProps_1.SeparatedPropsMode.values,
        FieldProps_1.SeparatedPropsMode.labels,
        FieldProps_1.SeparatedPropsMode.placeholders,
        FieldProps_1.SeparatedPropsMode.defaults,
        FieldProps_1.SeparatedPropsMode.initials,
        FieldProps_1.SeparatedPropsMode.disabled,
        FieldProps_1.SeparatedPropsMode.deleted,
        FieldProps_1.SeparatedPropsMode.types,
        FieldProps_1.SeparatedPropsMode.related,
        FieldProps_1.SeparatedPropsMode.rules,
        FieldProps_1.SeparatedPropsMode.options,
        FieldProps_1.SeparatedPropsMode.bindings,
        FieldProps_1.SeparatedPropsMode.extra,
        FieldProps_1.SeparatedPropsMode.hooks,
        FieldProps_1.SeparatedPropsMode.handlers,
        FieldProps_1.SeparatedPropsMode.validatedWith,
        FieldProps_1.SeparatedPropsMode.validators,
        FieldProps_1.SeparatedPropsMode.observers,
        FieldProps_1.SeparatedPropsMode.interceptors,
        FieldProps_1.SeparatedPropsMode.converters,
        FieldProps_1.SeparatedPropsMode.input,
        FieldProps_1.SeparatedPropsMode.output,
        FieldProps_1.SeparatedPropsMode.autoFocus,
        FieldProps_1.SeparatedPropsMode.inputMode,
        FieldProps_1.SeparatedPropsMode.refs,
        FieldProps_1.SeparatedPropsMode.classes,
        FieldProps_1.SeparatedPropsMode.nullable,
        FieldProps_1.SeparatedPropsMode.autoComplete,
    ],
    functions: [
        FieldProps_1.FieldPropsEnum.computed,
        FieldProps_1.FieldPropsEnum.observers,
        FieldProps_1.FieldPropsEnum.interceptors,
        FieldProps_1.FieldPropsEnum.converter,
        FieldProps_1.FieldPropsEnum.input,
        FieldProps_1.FieldPropsEnum.output,
    ],
    validation: [
        FieldProps_1.FieldPropsEnum.rules,
        FieldProps_1.FieldPropsEnum.validators,
        FieldProps_1.FieldPropsEnum.validatedWith,
    ],
    occurrences: {
        isDirty: FieldProps_1.FieldPropsOccurrence.some,
        isPristine: FieldProps_1.FieldPropsOccurrence.every,
        isDefault: FieldProps_1.FieldPropsOccurrence.every,
        isValid: FieldProps_1.FieldPropsOccurrence.every,
        isEmpty: FieldProps_1.FieldPropsOccurrence.every,
        hasError: FieldProps_1.FieldPropsOccurrence.some,
        focused: FieldProps_1.FieldPropsOccurrence.some,
        blurred: FieldProps_1.FieldPropsOccurrence.some,
        touched: FieldProps_1.FieldPropsOccurrence.some,
        deleted: FieldProps_1.FieldPropsOccurrence.every,
        disabled: FieldProps_1.FieldPropsOccurrence.every,
        clearing: FieldProps_1.FieldPropsOccurrence.every,
        resetting: FieldProps_1.FieldPropsOccurrence.every,
    },
};


/***/ }),

/***/ "./src/utils.ts":
/*!**********************!*\
  !*** ./src/utils.ts ***!
  \**********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getObservableMapValues = exports.getObservableMapKeys = exports.$try = exports.isBool = exports.hasFiles = exports.isEvent = exports.uniqueId = exports.maxKey = exports.hasIntKeys = exports.parseIntKeys = exports.allowNested = exports.hasSeparatedProps = exports.hasUnifiedProps = exports.isArrayFromStruct = exports.pathToStruct = exports.isArrayOfObjects = exports.isEmptyArray = exports.isArrayOfStrings = exports.throwError = exports.allowedProps = exports.hasProps = exports.checkPropOccurrence = exports.checkObserve = exports.props = void 0;
const lodash_1 = __importDefault(__webpack_require__(/*! lodash */ "lodash"));
const mobx_1 = __webpack_require__(/*! mobx */ "mobx");
const FieldProps_1 = __webpack_require__(/*! ./models/FieldProps */ "./src/models/FieldProps.ts");
const props_1 = __webpack_require__(/*! ./props */ "./src/props.ts");
Object.defineProperty(exports, "props", ({ enumerable: true, get: function () { return props_1.props; } }));
const getObservableMapValues = (observableMap) => (0, mobx_1.values)(observableMap);
exports.getObservableMapValues = getObservableMapValues;
const getObservableMapKeys = (observableMap) => (0, mobx_1.keys)(observableMap);
exports.getObservableMapKeys = getObservableMapKeys;
const checkObserveItem = (change) => ({ key, to, type, exec }) => change.type === type &&
    change.name === key &&
    change.newValue === to &&
    exec.apply(change, [change]);
const checkObserve = (collection) => (change) => collection.map(checkObserveItem(change));
exports.checkObserve = checkObserve;
const checkPropOccurrence = ({ type, data }) => {
    let $check;
    switch (type) {
        case FieldProps_1.FieldPropsOccurrence.some:
            $check = ($data) => lodash_1.default.some($data, Boolean);
            break;
        case FieldProps_1.FieldPropsOccurrence.every:
            $check = ($data) => lodash_1.default.every($data, Boolean);
            break;
        default: throw new Error('Occurrence not found for specified prop');
    }
    return $check(data);
};
exports.checkPropOccurrence = checkPropOccurrence;
const hasProps = ($type, $data) => {
    let $props;
    switch ($type) {
        case FieldProps_1.AllowedFieldPropsTypes.computed:
            $props = props_1.props.computed;
            break;
        case FieldProps_1.AllowedFieldPropsTypes.observable:
            $props = [
                FieldProps_1.FieldPropsEnum.fields,
                ...props_1.props.computed,
                ...props_1.props.editable,
            ];
            break;
        case FieldProps_1.AllowedFieldPropsTypes.editable:
            $props = [
                ...props_1.props.editable,
                ...props_1.props.validation,
                ...props_1.props.functions,
                ...props_1.props.handlers,
            ];
            break;
        case FieldProps_1.AllowedFieldPropsTypes.all:
            $props = [
                FieldProps_1.FieldPropsEnum.id,
                FieldProps_1.FieldPropsEnum.key,
                FieldProps_1.FieldPropsEnum.name,
                FieldProps_1.FieldPropsEnum.path,
                ...props_1.props.computed,
                ...props_1.props.editable,
                ...props_1.props.validation,
                ...props_1.props.functions,
                ...props_1.props.handlers,
            ];
            break;
        default:
            $props = null;
    }
    return lodash_1.default.intersection($data, $props).length > 0;
};
exports.hasProps = hasProps;
/**
  Check Allowed Properties
*/
const allowedProps = (type, data) => {
    if (hasProps(type, data))
        return;
    const $msg = "The selected property is not allowed";
    throw new Error(`${$msg} (${JSON.stringify(data)})`);
};
exports.allowedProps = allowedProps;
/**
  Throw Error if undefined Fields
*/
const throwError = (path, fields, msg = null) => {
    if (!lodash_1.default.isNil(fields))
        return;
    const $msg = lodash_1.default.isNil(msg) ? "The selected field is not defined" : msg;
    throw new Error(`${$msg} (${path})`);
};
exports.throwError = throwError;
const pathToStruct = (path) => {
    let struct;
    struct = lodash_1.default.replace(path, new RegExp("[.]\\d+($|.)", "g"), "[].");
    struct = lodash_1.default.replace(struct, "..", ".");
    struct = lodash_1.default.trim(struct, ".");
    return struct;
};
exports.pathToStruct = pathToStruct;
const isArrayFromStruct = (struct, structPath) => {
    if (isArrayOfStrings(struct))
        return !!struct
            .filter((s) => s.startsWith(structPath))
            .find((s) => s.substring(structPath.length) === "[]")
            || lodash_1.default.endsWith(struct === null || struct === void 0 ? void 0 : struct.find((e) => e === structPath), '[]');
    else
        return false;
};
exports.isArrayFromStruct = isArrayFromStruct;
const hasSome = (obj, keys) => lodash_1.default.some(keys, lodash_1.default.partial(lodash_1.default.has, obj));
const isEmptyArray = (field) => lodash_1.default.isEmpty(field) && Array.isArray(field);
exports.isEmptyArray = isEmptyArray;
const isArrayOfStrings = (struct) => Array.isArray(struct) && lodash_1.default.every(struct, lodash_1.default.isString);
exports.isArrayOfStrings = isArrayOfStrings;
const isArrayOfObjects = (fields) => Array.isArray(fields) && lodash_1.default.every(fields, lodash_1.default.isPlainObject);
exports.isArrayOfObjects = isArrayOfObjects;
const getKeys = (fields) => lodash_1.default.union(...lodash_1.default.map(lodash_1.default.values(fields), (values) => lodash_1.default.keys(values)));
const hasUnifiedProps = ({ fields }) => !isArrayOfStrings({ fields }) && hasProps(FieldProps_1.AllowedFieldPropsTypes.editable, getKeys(fields));
exports.hasUnifiedProps = hasUnifiedProps;
const hasSeparatedProps = (initial) => hasSome(initial, props_1.props.separated) || hasSome(initial, props_1.props.validation);
exports.hasSeparatedProps = hasSeparatedProps;
const allowNested = (field, strictProps) => lodash_1.default.isObject(field) &&
    !lodash_1.default.isDate(field) &&
    !lodash_1.default.has(field, FieldProps_1.FieldPropsEnum.fields) &&
    !lodash_1.default.has(field, FieldProps_1.FieldPropsEnum.class) &&
    (!hasSome(field, [
        ...props_1.props.editable,
        ...props_1.props.handlers,
        ...props_1.props.validation,
        ...props_1.props.functions,
    ]) || strictProps);
exports.allowNested = allowNested;
const parseIntKeys = (fields) => lodash_1.default.map(getObservableMapKeys(fields), lodash_1.default.ary(lodash_1.default.toNumber, 1));
exports.parseIntKeys = parseIntKeys;
const hasIntKeys = (fields) => lodash_1.default.every(parseIntKeys(fields), lodash_1.default.isInteger);
exports.hasIntKeys = hasIntKeys;
const maxKey = (fields) => {
    const max = lodash_1.default.max(parseIntKeys(fields));
    return lodash_1.default.isUndefined(max) ? 0 : max + 1;
};
exports.maxKey = maxKey;
const uniqueId = (field) => lodash_1.default.uniqueId([lodash_1.default.replace(field.path, new RegExp("\\.", "g"), "-"), "--"].join(""));
exports.uniqueId = uniqueId;
const isEvent = (obj) => {
    if (lodash_1.default.isNil(obj) || typeof Event === "undefined")
        return false;
    return obj instanceof Event || !lodash_1.default.isNil(obj.target);
};
exports.isEvent = isEvent;
const hasFiles = ($) => $.target.files && $.target.files.length !== 0;
exports.hasFiles = hasFiles;
const isBool = ($, val) => lodash_1.default.isBoolean(val) && lodash_1.default.isBoolean($.target.checked);
exports.isBool = isBool;
const $try = (...args) => {
    let found = undefined;
    args.map((val) => found === undefined && !lodash_1.default.isUndefined(val) && (found = val));
    return found;
};
exports.$try = $try;


/***/ }),

/***/ "lodash":
/*!********************!*\
  !*** external "_" ***!
  \********************/
/***/ ((module) => {

module.exports = __WEBPACK_EXTERNAL_MODULE_lodash__;

/***/ }),

/***/ "mobx":
/*!***********************!*\
  !*** external "mobx" ***!
  \***********************/
/***/ ((module) => {

module.exports = __WEBPACK_EXTERNAL_MODULE_mobx__;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module is referenced by other modules so it can't be inlined
/******/ 	var __webpack_exports__ = __webpack_require__("./src/index.ts");
/******/ 	
/******/ 	return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=MobxReactForm.umd.js.map