mobx-formkit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/AGENTS.md +761 -0
  2. package/LICENSE +21 -0
  3. package/README.md +214 -0
  4. package/lib/ArrayMap.d.ts +50 -0
  5. package/lib/ArrayMap.d.ts.map +1 -0
  6. package/lib/ArrayMap.js +151 -0
  7. package/lib/ArrayMap.js.map +1 -0
  8. package/lib/Base.d.ts +237 -0
  9. package/lib/Base.d.ts.map +1 -0
  10. package/lib/Base.js +872 -0
  11. package/lib/Base.js.map +1 -0
  12. package/lib/Bindings.d.ts +28 -0
  13. package/lib/Bindings.d.ts.map +1 -0
  14. package/lib/Bindings.js +73 -0
  15. package/lib/Bindings.js.map +1 -0
  16. package/lib/Field.d.ts +195 -0
  17. package/lib/Field.d.ts.map +1 -0
  18. package/lib/Field.js +734 -0
  19. package/lib/Field.js.map +1 -0
  20. package/lib/Form.d.ts +75 -0
  21. package/lib/Form.d.ts.map +1 -0
  22. package/lib/Form.js +199 -0
  23. package/lib/Form.js.map +1 -0
  24. package/lib/Options.d.ts +9 -0
  25. package/lib/Options.d.ts.map +1 -0
  26. package/lib/Options.js +85 -0
  27. package/lib/Options.js.map +1 -0
  28. package/lib/State.d.ts +43 -0
  29. package/lib/State.d.ts.map +1 -0
  30. package/lib/State.js +147 -0
  31. package/lib/State.js.map +1 -0
  32. package/lib/Validator.d.ts +25 -0
  33. package/lib/Validator.d.ts.map +1 -0
  34. package/lib/Validator.js +143 -0
  35. package/lib/Validator.js.map +1 -0
  36. package/lib/compat.d.ts +29 -0
  37. package/lib/compat.d.ts.map +1 -0
  38. package/lib/compat.js +117 -0
  39. package/lib/compat.js.map +1 -0
  40. package/lib/composer.d.ts +26 -0
  41. package/lib/composer.d.ts.map +1 -0
  42. package/lib/composer.js +65 -0
  43. package/lib/composer.js.map +1 -0
  44. package/lib/esm/ArrayMap.js +146 -0
  45. package/lib/esm/ArrayMap.js.map +1 -0
  46. package/lib/esm/Base.js +868 -0
  47. package/lib/esm/Base.js.map +1 -0
  48. package/lib/esm/Bindings.js +69 -0
  49. package/lib/esm/Bindings.js.map +1 -0
  50. package/lib/esm/Field.js +730 -0
  51. package/lib/esm/Field.js.map +1 -0
  52. package/lib/esm/Form.js +195 -0
  53. package/lib/esm/Form.js.map +1 -0
  54. package/lib/esm/Options.js +81 -0
  55. package/lib/esm/Options.js.map +1 -0
  56. package/lib/esm/State.js +143 -0
  57. package/lib/esm/State.js.map +1 -0
  58. package/lib/esm/Validator.js +139 -0
  59. package/lib/esm/Validator.js.map +1 -0
  60. package/lib/esm/compat.js +96 -0
  61. package/lib/esm/compat.js.map +1 -0
  62. package/lib/esm/composer.js +63 -0
  63. package/lib/esm/composer.js.map +1 -0
  64. package/lib/esm/index.js +8 -0
  65. package/lib/esm/index.js.map +1 -0
  66. package/lib/esm/models/FieldProps.js +116 -0
  67. package/lib/esm/models/FieldProps.js.map +1 -0
  68. package/lib/esm/models/OptionsModel.js +51 -0
  69. package/lib/esm/models/OptionsModel.js.map +1 -0
  70. package/lib/esm/models/StateInterface.js +9 -0
  71. package/lib/esm/models/StateInterface.js.map +1 -0
  72. package/lib/esm/models/ValidatorInterface.js +8 -0
  73. package/lib/esm/models/ValidatorInterface.js.map +1 -0
  74. package/lib/esm/parser.js +235 -0
  75. package/lib/esm/parser.js.map +1 -0
  76. package/lib/esm/props.js +118 -0
  77. package/lib/esm/props.js.map +1 -0
  78. package/lib/esm/utils.js +156 -0
  79. package/lib/esm/utils.js.map +1 -0
  80. package/lib/esm/validators/AJV.js +105 -0
  81. package/lib/esm/validators/AJV.js.map +1 -0
  82. package/lib/esm/validators/DVR.js +104 -0
  83. package/lib/esm/validators/DVR.js.map +1 -0
  84. package/lib/esm/validators/JOI.js +54 -0
  85. package/lib/esm/validators/JOI.js.map +1 -0
  86. package/lib/esm/validators/VALIBOT.js +50 -0
  87. package/lib/esm/validators/VALIBOT.js.map +1 -0
  88. package/lib/esm/validators/VINEJS.js +60 -0
  89. package/lib/esm/validators/VINEJS.js.map +1 -0
  90. package/lib/esm/validators/VJF.js +88 -0
  91. package/lib/esm/validators/VJF.js.map +1 -0
  92. package/lib/esm/validators/YUP.js +69 -0
  93. package/lib/esm/validators/YUP.js.map +1 -0
  94. package/lib/esm/validators/ZOD.js +43 -0
  95. package/lib/esm/validators/ZOD.js.map +1 -0
  96. package/lib/index.d.ts +7 -0
  97. package/lib/index.d.ts.map +1 -0
  98. package/lib/index.js +15 -0
  99. package/lib/index.js.map +1 -0
  100. package/lib/models/BaseInterface.d.ts +40 -0
  101. package/lib/models/BaseInterface.d.ts.map +1 -0
  102. package/lib/models/BindingsInterface.d.ts +18 -0
  103. package/lib/models/BindingsInterface.d.ts.map +1 -0
  104. package/lib/models/FieldInterface.d.ts +88 -0
  105. package/lib/models/FieldInterface.d.ts.map +1 -0
  106. package/lib/models/FieldProps.d.ts +111 -0
  107. package/lib/models/FieldProps.d.ts.map +1 -0
  108. package/lib/models/FieldProps.js +116 -0
  109. package/lib/models/FieldProps.js.map +1 -0
  110. package/lib/models/FormInterface.d.ts +184 -0
  111. package/lib/models/FormInterface.d.ts.map +1 -0
  112. package/lib/models/OptionsInterface.d.ts +8 -0
  113. package/lib/models/OptionsInterface.d.ts.map +1 -0
  114. package/lib/models/OptionsModel.d.ts +99 -0
  115. package/lib/models/OptionsModel.d.ts.map +1 -0
  116. package/lib/models/OptionsModel.js +51 -0
  117. package/lib/models/OptionsModel.js.map +1 -0
  118. package/lib/models/SharedActionsInterface.d.ts +27 -0
  119. package/lib/models/SharedActionsInterface.d.ts.map +1 -0
  120. package/lib/models/SharedEventsInterface.d.ts +8 -0
  121. package/lib/models/SharedEventsInterface.d.ts.map +1 -0
  122. package/lib/models/SharedHelpersInterface.d.ts +26 -0
  123. package/lib/models/SharedHelpersInterface.d.ts.map +1 -0
  124. package/lib/models/SharedInitializerInterface.d.ts +6 -0
  125. package/lib/models/SharedInitializerInterface.d.ts.map +1 -0
  126. package/lib/models/SharedUtilsInterface.d.ts +10 -0
  127. package/lib/models/SharedUtilsInterface.d.ts.map +1 -0
  128. package/lib/models/StateInterface.d.ts +37 -0
  129. package/lib/models/StateInterface.d.ts.map +1 -0
  130. package/lib/models/StateInterface.js +9 -0
  131. package/lib/models/StateInterface.js.map +1 -0
  132. package/lib/models/ValidatorInterface.d.ts +74 -0
  133. package/lib/models/ValidatorInterface.d.ts.map +1 -0
  134. package/lib/models/ValidatorInterface.js +8 -0
  135. package/lib/models/ValidatorInterface.js.map +1 -0
  136. package/lib/parser.d.ts +13 -0
  137. package/lib/parser.d.ts.map +1 -0
  138. package/lib/parser.js +247 -0
  139. package/lib/parser.js.map +1 -0
  140. package/lib/props.d.ts +14 -0
  141. package/lib/props.d.ts.map +1 -0
  142. package/lib/props.js +120 -0
  143. package/lib/props.js.map +1 -0
  144. package/lib/utils.d.ts +34 -0
  145. package/lib/utils.d.ts.map +1 -0
  146. package/lib/utils.js +182 -0
  147. package/lib/utils.js.map +1 -0
  148. package/lib/validators/AJV.d.ts +4 -0
  149. package/lib/validators/AJV.d.ts.map +1 -0
  150. package/lib/validators/AJV.js +109 -0
  151. package/lib/validators/AJV.js.map +1 -0
  152. package/lib/validators/DVR.d.ts +4 -0
  153. package/lib/validators/DVR.d.ts.map +1 -0
  154. package/lib/validators/DVR.js +108 -0
  155. package/lib/validators/DVR.js.map +1 -0
  156. package/lib/validators/JOI.d.ts +4 -0
  157. package/lib/validators/JOI.d.ts.map +1 -0
  158. package/lib/validators/JOI.js +58 -0
  159. package/lib/validators/JOI.js.map +1 -0
  160. package/lib/validators/VALIBOT.d.ts +4 -0
  161. package/lib/validators/VALIBOT.d.ts.map +1 -0
  162. package/lib/validators/VALIBOT.js +73 -0
  163. package/lib/validators/VALIBOT.js.map +1 -0
  164. package/lib/validators/VINEJS.d.ts +4 -0
  165. package/lib/validators/VINEJS.d.ts.map +1 -0
  166. package/lib/validators/VINEJS.js +64 -0
  167. package/lib/validators/VINEJS.js.map +1 -0
  168. package/lib/validators/VJF.d.ts +4 -0
  169. package/lib/validators/VJF.d.ts.map +1 -0
  170. package/lib/validators/VJF.js +92 -0
  171. package/lib/validators/VJF.js.map +1 -0
  172. package/lib/validators/YUP.d.ts +4 -0
  173. package/lib/validators/YUP.d.ts.map +1 -0
  174. package/lib/validators/YUP.js +73 -0
  175. package/lib/validators/YUP.js.map +1 -0
  176. package/lib/validators/ZOD.d.ts +4 -0
  177. package/lib/validators/ZOD.d.ts.map +1 -0
  178. package/lib/validators/ZOD.js +47 -0
  179. package/lib/validators/ZOD.js.map +1 -0
  180. package/package.json +183 -0
  181. package/src/ArrayMap.ts +165 -0
  182. package/src/Base.ts +1229 -0
  183. package/src/Bindings.ts +85 -0
  184. package/src/Field.ts +1034 -0
  185. package/src/Form.ts +264 -0
  186. package/src/Options.ts +91 -0
  187. package/src/State.ts +183 -0
  188. package/src/Validator.ts +177 -0
  189. package/src/compat.ts +104 -0
  190. package/src/composer.ts +82 -0
  191. package/src/index.ts +7 -0
  192. package/src/models/BaseInterface.ts +45 -0
  193. package/src/models/BindingsInterface.ts +25 -0
  194. package/src/models/FieldInterface.ts +97 -0
  195. package/src/models/FieldProps.ts +116 -0
  196. package/src/models/FormInterface.ts +203 -0
  197. package/src/models/OptionsInterface.ts +9 -0
  198. package/src/models/OptionsModel.ts +100 -0
  199. package/src/models/SharedActionsInterface.ts +30 -0
  200. package/src/models/SharedEventsInterface.ts +8 -0
  201. package/src/models/SharedHelpersInterface.ts +12 -0
  202. package/src/models/SharedInitializerInterface.ts +6 -0
  203. package/src/models/SharedUtilsInterface.ts +10 -0
  204. package/src/models/StateInterface.ts +44 -0
  205. package/src/models/ValidatorInterface.ts +88 -0
  206. package/src/parser.ts +327 -0
  207. package/src/props.ts +127 -0
  208. package/src/utils.ts +218 -0
  209. package/src/validators/AJV.ts +140 -0
  210. package/src/validators/DVR.ts +145 -0
  211. package/src/validators/JOI.ts +79 -0
  212. package/src/validators/VALIBOT.ts +70 -0
  213. package/src/validators/VINEJS.ts +83 -0
  214. package/src/validators/VJF.ts +123 -0
  215. package/src/validators/YUP.ts +90 -0
  216. package/src/validators/ZOD.ts +66 -0
  217. package/umd/MobxFormkit.umd.js +3093 -0
  218. package/umd/MobxFormkit.umd.js.map +1 -0
  219. package/umd/MobxFormkit.umd.min.js +2 -0
  220. package/umd/MobxFormkit.umd.min.js.map +1 -0
  221. package/umd/MobxFormkitComposer.umd.js +183 -0
  222. package/umd/MobxFormkitComposer.umd.js.map +1 -0
  223. package/umd/MobxFormkitComposer.umd.min.js +2 -0
  224. package/umd/MobxFormkitComposer.umd.min.js.map +1 -0
  225. package/umd/MobxFormkitValidatorAJV.umd.js +113 -0
  226. package/umd/MobxFormkitValidatorAJV.umd.js.map +1 -0
  227. package/umd/MobxFormkitValidatorAJV.umd.min.js +2 -0
  228. package/umd/MobxFormkitValidatorAJV.umd.min.js.map +1 -0
  229. package/umd/MobxFormkitValidatorDVR.umd.js +110 -0
  230. package/umd/MobxFormkitValidatorDVR.umd.js.map +1 -0
  231. package/umd/MobxFormkitValidatorDVR.umd.min.js +2 -0
  232. package/umd/MobxFormkitValidatorDVR.umd.min.js.map +1 -0
  233. package/umd/MobxFormkitValidatorJOI.umd.js +62 -0
  234. package/umd/MobxFormkitValidatorJOI.umd.js.map +1 -0
  235. package/umd/MobxFormkitValidatorJOI.umd.min.js +2 -0
  236. package/umd/MobxFormkitValidatorJOI.umd.min.js.map +1 -0
  237. package/umd/MobxFormkitValidatorVALIBOT.umd.js +8032 -0
  238. package/umd/MobxFormkitValidatorVALIBOT.umd.js.map +1 -0
  239. package/umd/MobxFormkitValidatorVALIBOT.umd.min.js +2 -0
  240. package/umd/MobxFormkitValidatorVALIBOT.umd.min.js.map +1 -0
  241. package/umd/MobxFormkitValidatorVINEJS.umd.js +11737 -0
  242. package/umd/MobxFormkitValidatorVINEJS.umd.js.map +1 -0
  243. package/umd/MobxFormkitValidatorVINEJS.umd.min.js +2 -0
  244. package/umd/MobxFormkitValidatorVINEJS.umd.min.js.map +1 -0
  245. package/umd/MobxFormkitValidatorVJF.umd.js +96 -0
  246. package/umd/MobxFormkitValidatorVJF.umd.js.map +1 -0
  247. package/umd/MobxFormkitValidatorVJF.umd.min.js +2 -0
  248. package/umd/MobxFormkitValidatorVJF.umd.min.js.map +1 -0
  249. package/umd/MobxFormkitValidatorYUP.umd.js +77 -0
  250. package/umd/MobxFormkitValidatorYUP.umd.js.map +1 -0
  251. package/umd/MobxFormkitValidatorYUP.umd.min.js +2 -0
  252. package/umd/MobxFormkitValidatorYUP.umd.min.js.map +1 -0
  253. package/umd/MobxFormkitValidatorZOD.umd.js +49 -0
  254. package/umd/MobxFormkitValidatorZOD.umd.js.map +1 -0
  255. package/umd/MobxFormkitValidatorZOD.umd.min.js +2 -0
  256. package/umd/MobxFormkitValidatorZOD.umd.min.js.map +1 -0
@@ -0,0 +1,3093 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('mobx'), require('lodash')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'mobx', 'lodash'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MobxFormkit = {}, global.mobx, global._));
5
+ })(this, (function (exports, mobx, lodash) { 'use strict';
6
+
7
+ function _interopNamespaceDefault(e) {
8
+ var n = Object.create(null);
9
+ if (e) {
10
+ Object.keys(e).forEach(function (k) {
11
+ if (k !== 'default') {
12
+ var d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: function () { return e[k]; }
16
+ });
17
+ }
18
+ });
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ var mobx__namespace = /*#__PURE__*/_interopNamespaceDefault(mobx);
25
+
26
+ // `decorate` was removed in MobX 7 and `makeObservable` does not exist in
27
+ // MobX 5. Resolve both lazily through the module namespace so a static
28
+ // named import never fails at link time (MISSING_EXPORT) with MobX 7.
29
+ const M = mobx__namespace;
30
+ /**
31
+ * `makeObservable` with MobX 5 / 6 / 7 compatibility.
32
+ *
33
+ * MobX 6/7: delegates to the native `makeObservable`.
34
+ * MobX 5: `makeObservable` does not exist (introduced in 6.0). The fallback
35
+ * below re-implements the same semantics with the MobX 5 primitives:
36
+ *
37
+ * 1. every annotated member is materialized as an OWN property of the
38
+ * instance first (getters/setters are copied down from the prototype
39
+ * chain — e.g. `changed`/`submitted` live on `Base`, not on `Form`),
40
+ * 2. a single `decorate(instance, ...)` pass applies the corresponding
41
+ * `observable` / `computed` / `action` decorators.
42
+ *
43
+ * Decorating the instance (instead of the prototype) is required: MobX 5's
44
+ * `decorate` is lazy (`mobxPendingDecorators`) and its initializer accessors
45
+ * recurse infinitely when decorated members live on the prototype, while a
46
+ * computed needs the getter to be an OWN property of the decorated target.
47
+ * `extendObservable` is avoided too — passing `ComputedValue` instances as
48
+ * initial values is no longer supported in 5.15+.
49
+ *
50
+ * All other APIs used across the source (`action`, `set`, `toJS`, `observe`,
51
+ * `intercept`, `reaction`, `autorun`, `runInAction`, `untracked`,
52
+ * `configure`/`enforceActions`, `extendObservable`) exist unchanged in
53
+ * MobX 5.x, 6.x and 7.x, so no other shims are required.
54
+ */
55
+ const makeObservable = (target, annotations) => {
56
+ if (typeof M.makeObservable === "function") {
57
+ return M.makeObservable(target, annotations);
58
+ }
59
+ return fallbackMakeObservable(target, annotations);
60
+ };
61
+ /* istanbul ignore next -- MobX 5 only: no makeObservable in 5.x and no decorate in 6/7, not runnable on the MobX 6/7 test matrix */
62
+ function fallbackMakeObservable(target, annotations) {
63
+ const members = Object.entries(annotations).filter(([key]) => key in target);
64
+ // call sites pass the mobx exports themselves (e.g. `computed`, `action`,
65
+ // `observable`) — compare by value, not by string
66
+ const isComputed = (annotation) => annotation === M.computed || annotation === "computed";
67
+ const isAction = (annotation) => annotation === M.action || annotation === "action";
68
+ const descriptorFromChain = (key) => {
69
+ let currentProto = Object.getPrototypeOf(target);
70
+ let descriptor;
71
+ while (currentProto && descriptor === undefined) {
72
+ descriptor = Object.getOwnPropertyDescriptor(currentProto, key);
73
+ currentProto = Object.getPrototypeOf(currentProto);
74
+ }
75
+ return descriptor;
76
+ };
77
+ members.forEach(([key, annotation]) => {
78
+ if (isComputed(annotation)) {
79
+ const own = Object.getOwnPropertyDescriptor(target, key);
80
+ if (!own || typeof own.get !== "function") {
81
+ const chain = descriptorFromChain(key);
82
+ const chainGet = chain && typeof chain.get === "function" ? chain.get : null;
83
+ const chainSet = chain && typeof chain.set === "function" ? chain.set : null;
84
+ Object.defineProperty(target, key, {
85
+ configurable: true,
86
+ enumerable: chain ? chain.enumerable : false,
87
+ get: chainGet ? () => chainGet.call(target) : () => undefined,
88
+ set: chainSet ? (value) => chainSet.call(target, value) : undefined,
89
+ });
90
+ }
91
+ }
92
+ else if (isAction(annotation)) {
93
+ const value = target[key];
94
+ if (typeof value === "function" &&
95
+ !Object.prototype.hasOwnProperty.call(target, key)) {
96
+ Object.defineProperty(target, key, {
97
+ configurable: true,
98
+ writable: true,
99
+ enumerable: false,
100
+ value,
101
+ });
102
+ }
103
+ }
104
+ });
105
+ const decorators = {};
106
+ members.forEach(([key, annotation]) => {
107
+ if (isComputed(annotation))
108
+ decorators[key] = M.computed;
109
+ else if (isAction(annotation))
110
+ decorators[key] = M.action;
111
+ else
112
+ decorators[key] = M.observable;
113
+ });
114
+ M.decorate(target, decorators);
115
+ return target;
116
+ }
117
+
118
+ /**
119
+ * ArrayMap: an ordered key-value collection backed by an observable array.
120
+ *
121
+ * Exposes the full ObservableMap-compatible API (get, set, has, delete,
122
+ * merge, forEach, keys, values, entries, intercept, etc.) while
123
+ * maintaining insertion order via an internal observable array.
124
+ *
125
+ * The observable array backing allows array-like operations such as
126
+ * `move(fromIndex, toIndex)` which directly re-orders entries via
127
+ * splice — fully MobX reactive.
128
+ */
129
+ class ArrayMap {
130
+ /** Duck-typing marker for utility code */
131
+ _isArrayMap = true;
132
+ /** Internal observable array: entries stored as [key, value] pairs */
133
+ _entries = mobx.observable.array([]);
134
+ constructor(entries) {
135
+ if (entries && entries.length > 0) {
136
+ this._entries.replace(entries);
137
+ }
138
+ }
139
+ // ------------------------------------------------------------------
140
+ // ObservableMap-compatible API
141
+ // ------------------------------------------------------------------
142
+ get size() {
143
+ return this._entries.length;
144
+ }
145
+ get(key) {
146
+ const entry = this._entries.find(([k]) => k === key);
147
+ return entry ? entry[1] : undefined;
148
+ }
149
+ set(key, value) {
150
+ const existing = this._entries.find(([k]) => k === key);
151
+ if (existing) {
152
+ existing[1] = value;
153
+ }
154
+ else {
155
+ this._entries.push([key, value]);
156
+ }
157
+ return this;
158
+ }
159
+ has(key) {
160
+ return this._entries.some(([k]) => k === key);
161
+ }
162
+ delete(key) {
163
+ const index = this._entries.findIndex(([k]) => k === key);
164
+ if (index !== -1) {
165
+ this._entries.splice(index, 1);
166
+ return true;
167
+ }
168
+ return false;
169
+ }
170
+ clear() {
171
+ this._entries.clear();
172
+ }
173
+ keys() {
174
+ return this._entries.map(([k]) => k)[Symbol.iterator]();
175
+ }
176
+ values() {
177
+ return this._entries.map(([, v]) => v)[Symbol.iterator]();
178
+ }
179
+ entries() {
180
+ return this._entries[Symbol.iterator]();
181
+ }
182
+ forEach(callbackfn, thisArg) {
183
+ this._entries.forEach(([key, value]) => {
184
+ callbackfn.call(thisArg, value, key, this);
185
+ });
186
+ }
187
+ toJSON() {
188
+ const result = {};
189
+ this._entries.forEach(([key, value]) => {
190
+ result[String(key)] = value;
191
+ });
192
+ return result;
193
+ }
194
+ toString() {
195
+ return `[object ArrayMap]`;
196
+ }
197
+ merge(other) {
198
+ if (other && typeof other === "object") {
199
+ if (other.forEach && typeof other.forEach === "function") {
200
+ // ObservableMap or Map-like
201
+ other.forEach((value, key) => {
202
+ this.set(key, value);
203
+ });
204
+ }
205
+ else if (Array.isArray(other)) {
206
+ // Array of [key, value] pairs
207
+ other.forEach(([key, value]) => {
208
+ this.set(key, value);
209
+ });
210
+ }
211
+ else {
212
+ // Plain object { key: value }
213
+ Object.keys(other).forEach((key) => {
214
+ this.set(key, other[key]);
215
+ });
216
+ }
217
+ }
218
+ return this;
219
+ }
220
+ replace(values) {
221
+ this.clear();
222
+ return this.merge(values);
223
+ }
224
+ get intercept() {
225
+ return this._entries.intercept;
226
+ }
227
+ [Symbol.iterator]() {
228
+ return this._entries[Symbol.iterator]();
229
+ }
230
+ // ------------------------------------------------------------------
231
+ // Array-specific methods
232
+ // ------------------------------------------------------------------
233
+ /**
234
+ * Move an entry from `fromIndex` to `toIndex`.
235
+ *
236
+ * Directly splices the internal observable array, so MobX
237
+ * tracks the change as a single array splice operation.
238
+ */
239
+ move(fromIndex, toIndex) {
240
+ mobx.runInAction(() => {
241
+ if (fromIndex < 0 || fromIndex >= this._entries.length)
242
+ return;
243
+ if (toIndex < 0 || toIndex >= this._entries.length)
244
+ return;
245
+ if (fromIndex === toIndex)
246
+ return;
247
+ const [entry] = this._entries.splice(fromIndex, 1);
248
+ this._entries.splice(toIndex, 0, entry);
249
+ });
250
+ }
251
+ /**
252
+ * Expose the underlying observable array for direct MobX
253
+ * observation (e.g. `observe(arr, cb)` from mobx).
254
+ */
255
+ toArray() {
256
+ return this._entries;
257
+ }
258
+ }
259
+
260
+ var FieldPropsEnum;
261
+ (function (FieldPropsEnum) {
262
+ FieldPropsEnum["key"] = "key";
263
+ FieldPropsEnum["id"] = "id";
264
+ FieldPropsEnum["path"] = "path";
265
+ FieldPropsEnum["name"] = "name";
266
+ FieldPropsEnum["fields"] = "fields";
267
+ FieldPropsEnum["ref"] = "ref";
268
+ FieldPropsEnum["type"] = "type";
269
+ FieldPropsEnum["computed"] = "computed";
270
+ FieldPropsEnum["value"] = "value";
271
+ FieldPropsEnum["initial"] = "initial";
272
+ FieldPropsEnum["default"] = "default";
273
+ FieldPropsEnum["checked"] = "checked";
274
+ FieldPropsEnum["label"] = "label";
275
+ FieldPropsEnum["placeholder"] = "placeholder";
276
+ FieldPropsEnum["error"] = "error";
277
+ FieldPropsEnum["validatedWith"] = "validatedWith";
278
+ FieldPropsEnum["validators"] = "validators";
279
+ FieldPropsEnum["rules"] = "rules";
280
+ FieldPropsEnum["related"] = "related";
281
+ FieldPropsEnum["options"] = "options";
282
+ FieldPropsEnum["extra"] = "extra";
283
+ FieldPropsEnum["bindings"] = "bindings";
284
+ FieldPropsEnum["hooks"] = "hooks";
285
+ FieldPropsEnum["handlers"] = "handlers";
286
+ FieldPropsEnum["converter"] = "converter";
287
+ FieldPropsEnum["input"] = "input";
288
+ FieldPropsEnum["output"] = "output";
289
+ FieldPropsEnum["interceptors"] = "interceptors";
290
+ FieldPropsEnum["observers"] = "observers";
291
+ // computed
292
+ FieldPropsEnum["disabled"] = "disabled";
293
+ FieldPropsEnum["deleted"] = "deleted";
294
+ FieldPropsEnum["blurred"] = "blurred";
295
+ FieldPropsEnum["validating"] = "validating";
296
+ FieldPropsEnum["submitting"] = "submitting";
297
+ FieldPropsEnum["clearing"] = "clearing";
298
+ FieldPropsEnum["resetting"] = "resetting";
299
+ FieldPropsEnum["changed"] = "changed";
300
+ FieldPropsEnum["touched"] = "touched";
301
+ FieldPropsEnum["focused"] = "focused";
302
+ FieldPropsEnum["isEmpty"] = "isEmpty";
303
+ FieldPropsEnum["isDefault"] = "isDefault";
304
+ FieldPropsEnum["isPristine"] = "isPristine";
305
+ FieldPropsEnum["isDirty"] = "isDirty";
306
+ FieldPropsEnum["isValid"] = "isValid";
307
+ FieldPropsEnum["hasError"] = "hasError";
308
+ // handlers
309
+ FieldPropsEnum["onInit"] = "onInit";
310
+ FieldPropsEnum["onSync"] = "onSync";
311
+ FieldPropsEnum["onChange"] = "onChange";
312
+ FieldPropsEnum["onBlur"] = "onBlur";
313
+ FieldPropsEnum["onFocus"] = "onFocus";
314
+ FieldPropsEnum["onToggle"] = "onToggle";
315
+ FieldPropsEnum["onDrop"] = "onDrop";
316
+ FieldPropsEnum["onSubmit"] = "onSubmit";
317
+ FieldPropsEnum["onReset"] = "onReset";
318
+ FieldPropsEnum["onClear"] = "onClear";
319
+ FieldPropsEnum["onAdd"] = "onAdd";
320
+ FieldPropsEnum["onDel"] = "onDel";
321
+ FieldPropsEnum["autoFocus"] = "autoFocus";
322
+ FieldPropsEnum["inputMode"] = "inputMode";
323
+ FieldPropsEnum["onKeyDown"] = "onKeyDown";
324
+ FieldPropsEnum["onKeyUp"] = "onKeyUp";
325
+ FieldPropsEnum["class"] = "class";
326
+ FieldPropsEnum["nullable"] = "nullable";
327
+ FieldPropsEnum["autoComplete"] = "autoComplete";
328
+ })(FieldPropsEnum || (FieldPropsEnum = {}));
329
+ var AllowedFieldPropsTypes;
330
+ (function (AllowedFieldPropsTypes) {
331
+ AllowedFieldPropsTypes["computed"] = "computed";
332
+ AllowedFieldPropsTypes["observable"] = "observable";
333
+ AllowedFieldPropsTypes["editable"] = "editable";
334
+ AllowedFieldPropsTypes["all"] = "all";
335
+ })(AllowedFieldPropsTypes || (AllowedFieldPropsTypes = {}));
336
+ var FieldPropsOccurrence;
337
+ (function (FieldPropsOccurrence) {
338
+ FieldPropsOccurrence["some"] = "some";
339
+ FieldPropsOccurrence["every"] = "every";
340
+ })(FieldPropsOccurrence || (FieldPropsOccurrence = {}));
341
+ var SeparatedPropsMode;
342
+ (function (SeparatedPropsMode) {
343
+ SeparatedPropsMode["computed"] = "computed";
344
+ SeparatedPropsMode["values"] = "values";
345
+ SeparatedPropsMode["labels"] = "labels";
346
+ SeparatedPropsMode["placeholders"] = "placeholders";
347
+ SeparatedPropsMode["defaults"] = "defaults";
348
+ SeparatedPropsMode["initials"] = "initials";
349
+ SeparatedPropsMode["disabled"] = "disabled";
350
+ SeparatedPropsMode["deleted"] = "deleted";
351
+ SeparatedPropsMode["types"] = "types";
352
+ SeparatedPropsMode["related"] = "related";
353
+ SeparatedPropsMode["rules"] = "rules";
354
+ SeparatedPropsMode["options"] = "options";
355
+ SeparatedPropsMode["bindings"] = "bindings";
356
+ SeparatedPropsMode["extra"] = "extra";
357
+ SeparatedPropsMode["hooks"] = "hooks";
358
+ SeparatedPropsMode["handlers"] = "handlers";
359
+ SeparatedPropsMode["validatedWith"] = "validatedWith";
360
+ SeparatedPropsMode["validators"] = "validators";
361
+ SeparatedPropsMode["observers"] = "observers";
362
+ SeparatedPropsMode["interceptors"] = "interceptors";
363
+ SeparatedPropsMode["converters"] = "converters";
364
+ SeparatedPropsMode["input"] = "input";
365
+ SeparatedPropsMode["output"] = "output";
366
+ SeparatedPropsMode["autoFocus"] = "autoFocus";
367
+ SeparatedPropsMode["inputMode"] = "inputMode";
368
+ SeparatedPropsMode["refs"] = "refs";
369
+ SeparatedPropsMode["classes"] = "classes";
370
+ SeparatedPropsMode["nullable"] = "nullable";
371
+ SeparatedPropsMode["autoComplete"] = "autoComplete";
372
+ })(SeparatedPropsMode || (SeparatedPropsMode = {}));
373
+
374
+ const props = {
375
+ editable: [
376
+ FieldPropsEnum.type,
377
+ FieldPropsEnum.value,
378
+ FieldPropsEnum.initial,
379
+ FieldPropsEnum.default,
380
+ FieldPropsEnum.label,
381
+ FieldPropsEnum.placeholder,
382
+ FieldPropsEnum.related,
383
+ FieldPropsEnum.options,
384
+ FieldPropsEnum.extra,
385
+ FieldPropsEnum.bindings,
386
+ FieldPropsEnum.hooks,
387
+ FieldPropsEnum.handlers,
388
+ FieldPropsEnum.deleted,
389
+ FieldPropsEnum.disabled,
390
+ FieldPropsEnum.autoFocus,
391
+ FieldPropsEnum.inputMode,
392
+ FieldPropsEnum.ref,
393
+ FieldPropsEnum.nullable,
394
+ FieldPropsEnum.autoComplete,
395
+ ],
396
+ handlers: [
397
+ FieldPropsEnum.onChange,
398
+ FieldPropsEnum.onToggle,
399
+ FieldPropsEnum.onFocus,
400
+ FieldPropsEnum.onBlur,
401
+ FieldPropsEnum.onDrop,
402
+ FieldPropsEnum.onSubmit,
403
+ FieldPropsEnum.onReset,
404
+ FieldPropsEnum.onClear,
405
+ FieldPropsEnum.onAdd,
406
+ FieldPropsEnum.onDel,
407
+ ],
408
+ computed: [
409
+ FieldPropsEnum.error,
410
+ FieldPropsEnum.hasError,
411
+ FieldPropsEnum.isValid,
412
+ FieldPropsEnum.isDirty,
413
+ FieldPropsEnum.isPristine,
414
+ FieldPropsEnum.isDefault,
415
+ FieldPropsEnum.isEmpty,
416
+ FieldPropsEnum.focused,
417
+ FieldPropsEnum.touched,
418
+ FieldPropsEnum.changed,
419
+ FieldPropsEnum.validating,
420
+ FieldPropsEnum.submitting,
421
+ FieldPropsEnum.resetting,
422
+ FieldPropsEnum.clearing,
423
+ FieldPropsEnum.blurred,
424
+ FieldPropsEnum.deleted,
425
+ FieldPropsEnum.disabled,
426
+ ],
427
+ separated: [
428
+ SeparatedPropsMode.computed,
429
+ SeparatedPropsMode.values,
430
+ SeparatedPropsMode.labels,
431
+ SeparatedPropsMode.placeholders,
432
+ SeparatedPropsMode.defaults,
433
+ SeparatedPropsMode.initials,
434
+ SeparatedPropsMode.disabled,
435
+ SeparatedPropsMode.deleted,
436
+ SeparatedPropsMode.types,
437
+ SeparatedPropsMode.related,
438
+ SeparatedPropsMode.rules,
439
+ SeparatedPropsMode.options,
440
+ SeparatedPropsMode.bindings,
441
+ SeparatedPropsMode.extra,
442
+ SeparatedPropsMode.hooks,
443
+ SeparatedPropsMode.handlers,
444
+ SeparatedPropsMode.validatedWith,
445
+ SeparatedPropsMode.validators,
446
+ SeparatedPropsMode.observers,
447
+ SeparatedPropsMode.interceptors,
448
+ SeparatedPropsMode.converters,
449
+ SeparatedPropsMode.input,
450
+ SeparatedPropsMode.output,
451
+ SeparatedPropsMode.autoFocus,
452
+ SeparatedPropsMode.inputMode,
453
+ SeparatedPropsMode.refs,
454
+ SeparatedPropsMode.classes,
455
+ SeparatedPropsMode.nullable,
456
+ SeparatedPropsMode.autoComplete,
457
+ ],
458
+ functions: [
459
+ FieldPropsEnum.computed,
460
+ FieldPropsEnum.observers,
461
+ FieldPropsEnum.interceptors,
462
+ FieldPropsEnum.converter,
463
+ FieldPropsEnum.input,
464
+ FieldPropsEnum.output,
465
+ ],
466
+ validation: [
467
+ FieldPropsEnum.rules,
468
+ FieldPropsEnum.validators,
469
+ FieldPropsEnum.validatedWith,
470
+ ],
471
+ occurrences: {
472
+ isDirty: FieldPropsOccurrence.some,
473
+ isPristine: FieldPropsOccurrence.every,
474
+ isDefault: FieldPropsOccurrence.every,
475
+ isValid: FieldPropsOccurrence.every,
476
+ isEmpty: FieldPropsOccurrence.every,
477
+ hasError: FieldPropsOccurrence.some,
478
+ focused: FieldPropsOccurrence.some,
479
+ blurred: FieldPropsOccurrence.some,
480
+ touched: FieldPropsOccurrence.some,
481
+ deleted: FieldPropsOccurrence.every,
482
+ disabled: FieldPropsOccurrence.every,
483
+ clearing: FieldPropsOccurrence.every,
484
+ resetting: FieldPropsOccurrence.every,
485
+ },
486
+ };
487
+
488
+ const getObservableMapValues = (fields) => {
489
+ // ArrayMap duck-typing
490
+ if (fields && fields._isArrayMap) {
491
+ const result = [];
492
+ fields.forEach((value) => result.push(value));
493
+ return result;
494
+ }
495
+ return mobx.values(fields);
496
+ };
497
+ const getObservableMapKeys = (fields) => {
498
+ // ArrayMap duck-typing
499
+ if (fields && fields._isArrayMap) {
500
+ return Array.from(fields.keys());
501
+ }
502
+ return mobx.keys(fields);
503
+ };
504
+ const checkObserveItem = (change) => ({ key, to, type, exec }) => change.type === type &&
505
+ change.name === key &&
506
+ change.newValue === to &&
507
+ exec.apply(change, [change]);
508
+ const checkObserve = (collection) => (change) => collection.map(checkObserveItem(change));
509
+ const checkPropOccurrence = ({ type, data }) => {
510
+ let $check;
511
+ switch (type) {
512
+ case FieldPropsOccurrence.some:
513
+ $check = ($data) => $data.some(Boolean);
514
+ break;
515
+ case FieldPropsOccurrence.every:
516
+ $check = ($data) => $data.every(Boolean);
517
+ break;
518
+ default: throw new Error('Occurrence not found for specified prop');
519
+ }
520
+ return $check(data);
521
+ };
522
+ const hasProps = ($type, $data) => {
523
+ let $props;
524
+ switch ($type) {
525
+ case AllowedFieldPropsTypes.computed:
526
+ $props = props.computed;
527
+ break;
528
+ case AllowedFieldPropsTypes.observable:
529
+ $props = [
530
+ FieldPropsEnum.fields,
531
+ ...props.computed,
532
+ ...props.editable,
533
+ ];
534
+ break;
535
+ case AllowedFieldPropsTypes.editable:
536
+ $props = [
537
+ ...props.editable,
538
+ ...props.validation,
539
+ ...props.functions,
540
+ ...props.handlers,
541
+ ];
542
+ break;
543
+ case AllowedFieldPropsTypes.all:
544
+ $props = [
545
+ FieldPropsEnum.id,
546
+ FieldPropsEnum.key,
547
+ FieldPropsEnum.name,
548
+ FieldPropsEnum.path,
549
+ ...props.computed,
550
+ ...props.editable,
551
+ ...props.validation,
552
+ ...props.functions,
553
+ ...props.handlers,
554
+ ];
555
+ break;
556
+ default:
557
+ $props = null;
558
+ }
559
+ return $data.filter((x) => $props.includes(x)).length > 0;
560
+ };
561
+ /**
562
+ Check Allowed Properties
563
+ */
564
+ const allowedProps = (type, data) => {
565
+ if (hasProps(type, data))
566
+ return;
567
+ const $msg = "The selected property is not allowed";
568
+ throw new Error(`${$msg} (${JSON.stringify(data)})`);
569
+ };
570
+ /**
571
+ Throw Error if undefined Fields
572
+ */
573
+ const throwError = (path, fields, msg = null) => {
574
+ if (fields != null)
575
+ return;
576
+ const $msg = msg == null ? "The selected field is not defined" : msg;
577
+ throw new Error(`${$msg} (${path})`);
578
+ };
579
+ const pathToStruct = (path) => {
580
+ let struct;
581
+ struct = path.replace(/\.\d+($|\.)/g, "[].");
582
+ struct = struct.replace("..", ".");
583
+ struct = struct.replace(/^\.+|\.+$/g, "");
584
+ return struct;
585
+ };
586
+ const isArrayFromStruct = (struct, structPath) => {
587
+ if (isArrayOfStrings(struct))
588
+ return !!struct
589
+ .filter((s) => s.startsWith(structPath))
590
+ .find((s) => s.substring(structPath.length) === "[]")
591
+ || (struct?.find((e) => e === structPath)?.endsWith('[]') ?? false);
592
+ else
593
+ return false;
594
+ };
595
+ const hasSome = (obj, keys) => keys.some((key) => lodash.has(obj, key));
596
+ const isEmptyArray = (field) => lodash.isEmpty(field) && Array.isArray(field);
597
+ const isArrayOfStrings = (struct) => Array.isArray(struct) && struct.every((s) => typeof s === 'string');
598
+ const isArrayOfObjects = (fields) => Array.isArray(fields) && fields.every((f) => lodash.isPlainObject(f));
599
+ const getKeys = (fields) => fields ? [...new Set(Object.values(fields).flatMap((values) => values ? Object.keys(values) : []))] : [];
600
+ const hasUnifiedProps = ({ fields }) => !isArrayOfStrings({ fields }) && hasProps(AllowedFieldPropsTypes.editable, getKeys(fields));
601
+ const hasSeparatedProps = (initial) => hasSome(initial, props.separated) || hasSome(initial, props.validation);
602
+ const allowNested = (field, strictProps) => field !== null && typeof field === 'object' &&
603
+ !(field instanceof Date) &&
604
+ !lodash.has(field, FieldPropsEnum.fields) &&
605
+ !lodash.has(field, FieldPropsEnum.class) &&
606
+ (!hasSome(field, [
607
+ ...props.editable,
608
+ ...props.handlers,
609
+ ...props.validation,
610
+ ...props.functions,
611
+ ]) || strictProps);
612
+ const parseIntKeys = (fields) => Array.from(getObservableMapKeys(fields)).map(Number);
613
+ const hasIntKeys = (fields) => parseIntKeys(fields).every((x) => Number.isInteger(x));
614
+ const maxKey = (fields) => {
615
+ const keys = parseIntKeys(fields);
616
+ const maxVal = keys.length ? Math.max(...keys) : undefined;
617
+ return maxVal === void 0 ? 0 : maxVal + 1;
618
+ };
619
+ let _idCounter = 0;
620
+ const _localUniqueId = (prefix) => `${prefix}${++_idCounter}`;
621
+ const uniqueId = (field) => _localUniqueId([field.path.replace(/\./g, "-"), "--"].join(""));
622
+ const isEvent = (obj) => {
623
+ if (obj == null || typeof Event === "undefined")
624
+ return false;
625
+ return obj instanceof Event || obj.target != null;
626
+ };
627
+ const hasFiles = ($) => !!$?.target?.files && $.target.files.length !== 0;
628
+ const isBool = ($, val) => typeof val === 'boolean' && typeof $.target.checked === 'boolean';
629
+ const $try = (...args) => {
630
+ for (const val of args) {
631
+ if (val !== undefined)
632
+ return val;
633
+ }
634
+ return undefined;
635
+ };
636
+
637
+ const defaultValue = ({ type = undefined, value = undefined, nullable = undefined, isEmptyArray = false, fallbackValueOption = "", }) => {
638
+ if (Array.isArray(value) || isEmptyArray)
639
+ return [];
640
+ if (nullable || value instanceof Date || type === "date" || type === "datetime-local")
641
+ return null;
642
+ if (typeof value === 'number' || type === "number")
643
+ return 0;
644
+ if (typeof value === 'boolean' || type === "checkbox")
645
+ return false;
646
+ if (typeof value === 'string' || type === "file")
647
+ return "";
648
+ return fallbackValueOption;
649
+ };
650
+ const parsePath = (path) => {
651
+ let $path = String(path ?? '');
652
+ $path = $path.replace(/\[/g, ".");
653
+ $path = $path.replace(/\]/g, "");
654
+ return $path;
655
+ };
656
+ const parseInput = (input, { fallbackValueOption = "", type, isEmptyArray, separated, unified, fallback }) => input($try(separated, unified, fallback, defaultValue({
657
+ fallbackValueOption,
658
+ type,
659
+ isEmptyArray,
660
+ })));
661
+ const parseArrayProp = (val, prop, removeNullishValuesInArrays) => {
662
+ const values = Object.values(val);
663
+ const isValProp = [
664
+ FieldPropsEnum.value,
665
+ FieldPropsEnum.initial,
666
+ FieldPropsEnum.default,
667
+ ].includes(prop);
668
+ if (removeNullishValuesInArrays && isValProp) {
669
+ return values.filter(v => v !== null && v !== undefined && v !== "");
670
+ }
671
+ return values;
672
+ };
673
+ const parseCheckArray = (field, value, prop, removeNullishValuesInArrays) => {
674
+ if (field.incremental && value !== null && typeof value === 'object' && lodash.isEmpty(value))
675
+ return [];
676
+ return field.hasIncrementalKeys ? parseArrayProp(value, prop, removeNullishValuesInArrays) : value;
677
+ };
678
+ const parseCheckOutput = (field, prop, retrieveNullifiedEmptyStrings = false) => {
679
+ if (prop === FieldPropsEnum.value || prop.startsWith("value.")) {
680
+ const base = field.$output ? field.$output(field[FieldPropsEnum.value]) : field[FieldPropsEnum.value];
681
+ const value = prop.startsWith("value.") ? lodash.get(base, prop.substring(6)) : base;
682
+ if (typeof value === 'string' && lodash.isEmpty(value) && retrieveNullifiedEmptyStrings)
683
+ return null;
684
+ return value;
685
+ }
686
+ return field[prop];
687
+ };
688
+ const defineFieldsFromStruct = (struct, add = false) => struct.reduceRight(($, name) => {
689
+ const obj = {};
690
+ if (name.endsWith("[]")) {
691
+ const val = add ? [$] : [];
692
+ obj[name.replace(/\[\]$/, "")] = val;
693
+ return obj;
694
+ }
695
+ // no brakets
696
+ const prev = struct[struct.indexOf(name) - 1];
697
+ const stop = !!prev && prev.endsWith("[]") && struct[struct.length - 1] === name;
698
+ if (!add && stop)
699
+ return obj;
700
+ obj[name] = $;
701
+ return obj;
702
+ }, {});
703
+ const handleFieldsArrayOfStrings = ($fields, add = false) => {
704
+ let fields = $fields;
705
+ // handle array with field struct (strings)
706
+ if (isArrayOfStrings(fields)) {
707
+ fields = lodash.transform(fields, ($obj, $) => {
708
+ const pathStruct = $.split(".");
709
+ // as array of strings (with empty values)
710
+ if (!pathStruct.length)
711
+ return Object.assign($obj, { [$]: "" });
712
+ // define flat or nested fields from pathStruct
713
+ return lodash.merge($obj, defineFieldsFromStruct(pathStruct, add));
714
+ }, {});
715
+ }
716
+ return fields;
717
+ };
718
+ const handleFieldsArrayOfObjects = ($fields) => {
719
+ let fields = $fields;
720
+ // handle array of objects (with unified props)
721
+ if (isArrayOfObjects(fields)) {
722
+ fields = lodash.transform(fields, ($obj, field) => {
723
+ if (hasUnifiedProps({ fields: { field } }) && !lodash.has(field, FieldPropsEnum.name))
724
+ return undefined;
725
+ return Object.assign($obj, { [field.name]: field });
726
+ }, {});
727
+ }
728
+ return fields;
729
+ };
730
+ const handleFieldsNested = (fields, strictProps = true) => lodash.transform(fields, (obj, field, key) => {
731
+ if (allowNested(field, strictProps)) {
732
+ // define nested field
733
+ return Object.assign(obj, {
734
+ [key]: {
735
+ fields: isEmptyArray(field) ? [] : handleFieldsNested(field),
736
+ },
737
+ });
738
+ }
739
+ return Object.assign(obj, { [key]: field });
740
+ }, {});
741
+ /* mapNestedValuesToUnifiedValues
742
+
743
+ FROM:
744
+
745
+ {
746
+ street: '123 Fake St.',
747
+ zip: '12345',
748
+ }
749
+
750
+ TO:
751
+
752
+ [{
753
+ name: 'street'
754
+ value: '123 Fake St.',
755
+ }, {
756
+ name: 'zip'
757
+ value: '12345',
758
+ }]
759
+
760
+ */
761
+ const mapNestedValuesToUnifiedValues = (data) => lodash.isPlainObject(data)
762
+ ? Object.entries(data).map(([name, value]) => ({ value, name }))
763
+ : undefined;
764
+ /* reduceValuesToUnifiedFields
765
+
766
+ FROM:
767
+
768
+ {
769
+ name: 'fatty',
770
+ address: {
771
+ street: '123 Fake St.',
772
+ zip: '12345',
773
+ },
774
+ };
775
+
776
+ TO:
777
+
778
+ {
779
+ name: {
780
+ value: 'fatty',
781
+ fields: undefined
782
+ },
783
+ address: {
784
+ value: {
785
+ street: '123 Fake St.',
786
+ zip: '12345'
787
+ },
788
+ fields: [ ... ]
789
+ },
790
+ };
791
+
792
+ */
793
+ const reduceValuesToUnifiedFields = (values) => lodash.transform(values, (obj, value, key) => Object.assign(obj, {
794
+ [key]: {
795
+ value,
796
+ fields: mapNestedValuesToUnifiedValues(value),
797
+ },
798
+ }), {});
799
+ /*
800
+ Fallback Unified Props to Separated Mode
801
+ */
802
+ const handleFieldsPropsFallback = (fields, initial, fallback) => {
803
+ if (!lodash.has(initial, SeparatedPropsMode.values))
804
+ return fields;
805
+ // if the 'values' object is passed in constructor
806
+ // then update the fields definitions
807
+ let { values } = initial;
808
+ if (hasUnifiedProps({ fields: initial.fields })) {
809
+ values = reduceValuesToUnifiedFields(values);
810
+ }
811
+ return lodash.merge(fields, lodash.transform(values, (result, v, k) => {
812
+ if (Array.isArray(fields[k]))
813
+ result[k] = v;
814
+ if (!(k in fields) && (!isNaN(Number(k)) || fallback))
815
+ result[k] = v;
816
+ }, {}));
817
+ };
818
+ const mergeSchemaDefaults = (fields, validator) => {
819
+ if (validator) {
820
+ const schema = lodash.get(validator.plugins, "ajv.config.schema");
821
+ if (lodash.isEmpty(fields) && schema && !!schema.properties) {
822
+ lodash.each(schema.properties, (prop, key) => {
823
+ lodash.set(fields, key, {
824
+ value: prop.default,
825
+ label: prop.title,
826
+ });
827
+ });
828
+ }
829
+ }
830
+ return fields;
831
+ };
832
+ const prepareFieldsData = (initial, strictProps = true, fallback = true) => {
833
+ let fields = lodash.merge(handleFieldsArrayOfStrings(initial.fields, false), handleFieldsArrayOfStrings(initial.struct, false));
834
+ fields = handleFieldsArrayOfObjects(fields);
835
+ fields = handleFieldsPropsFallback(fields, initial, fallback);
836
+ fields = handleFieldsNested(fields, strictProps);
837
+ return fields;
838
+ };
839
+ const pathToFieldsTree = (struct, path, n = 0, add = false) => {
840
+ const $struct = (Array.isArray(struct) ? struct : Object.values(struct)).filter((item) => typeof item === 'string');
841
+ const structPath = pathToStruct(path);
842
+ const structArray = $struct.filter((item) => item.startsWith(structPath));
843
+ const $tree = handleFieldsArrayOfStrings(structArray, add);
844
+ const $structPath = structPath.replace(/\[\]/g, `[${n}]`);
845
+ const fields = handleFieldsNested(lodash.get($tree, $structPath));
846
+ // fix issues #614 & #615
847
+ $struct.length && $struct
848
+ .filter(s => s.startsWith(path + '[]'))
849
+ .map(s => s.substring((path + '[].').length))
850
+ .filter(s => s.endsWith('[]'))
851
+ .map(s => s.substring(0, s.length - 2))
852
+ .forEach(s => {
853
+ const ss = s.split('.');
854
+ let t = fields[0]?.fields;
855
+ for (let i = 0; i < ss.length; i++) {
856
+ t = t?.[ss[i]]?.[FieldPropsEnum.fields];
857
+ if (!t)
858
+ break;
859
+ }
860
+ if (t)
861
+ delete t[0];
862
+ });
863
+ return fields;
864
+ };
865
+
866
+ var OptionsEnum;
867
+ (function (OptionsEnum) {
868
+ OptionsEnum["uniqueId"] = "uniqueId";
869
+ OptionsEnum["fallback"] = "fallback";
870
+ OptionsEnum["fallbackValue"] = "fallbackValue";
871
+ OptionsEnum["defaultGenericError"] = "defaultGenericError";
872
+ OptionsEnum["submitThrowsError"] = "submitThrowsError";
873
+ OptionsEnum["showErrorsOnInit"] = "showErrorsOnInit";
874
+ OptionsEnum["showErrorsOnSubmit"] = "showErrorsOnSubmit";
875
+ OptionsEnum["showErrorsOnBlur"] = "showErrorsOnBlur";
876
+ OptionsEnum["showErrorsOnChange"] = "showErrorsOnChange";
877
+ OptionsEnum["showErrorsOnClear"] = "showErrorsOnClear";
878
+ OptionsEnum["showErrorsOnReset"] = "showErrorsOnReset";
879
+ OptionsEnum["validateOnInit"] = "validateOnInit";
880
+ OptionsEnum["validateOnSubmit"] = "validateOnSubmit";
881
+ OptionsEnum["validateOnBlur"] = "validateOnBlur";
882
+ OptionsEnum["validateOnChange"] = "validateOnChange";
883
+ OptionsEnum["validateOnChangeAfterInitialBlur"] = "validateOnChangeAfterInitialBlur";
884
+ OptionsEnum["validateOnChangeAfterSubmit"] = "validateOnChangeAfterSubmit";
885
+ OptionsEnum["validateDisabledFields"] = "validateDisabledFields";
886
+ OptionsEnum["validateDeletedFields"] = "validateDeletedFields";
887
+ OptionsEnum["validatePristineFields"] = "validatePristineFields";
888
+ OptionsEnum["validateTrimmedValue"] = "validateTrimmedValue";
889
+ OptionsEnum["validateOnClear"] = "validateOnClear";
890
+ OptionsEnum["validateOnReset"] = "validateOnReset";
891
+ OptionsEnum["strictSet"] = "strictSet";
892
+ OptionsEnum["strictUpdate"] = "strictUpdate";
893
+ OptionsEnum["strictDelete"] = "strictDelete";
894
+ OptionsEnum["strictSelect"] = "strictSelect";
895
+ OptionsEnum["softDelete"] = "softDelete";
896
+ OptionsEnum["retrieveOnlyDirtyFieldsValues"] = "retrieveOnlyDirtyFieldsValues";
897
+ OptionsEnum["retrieveOnlyEnabledFieldsValues"] = "retrieveOnlyEnabledFieldsValues";
898
+ OptionsEnum["retrieveOnlyEnabledFieldsErrors"] = "retrieveOnlyEnabledFieldsErrors";
899
+ OptionsEnum["retrieveNullifiedEmptyStrings"] = "retrieveNullifiedEmptyStrings";
900
+ OptionsEnum["removeNullishValuesInArrays"] = "removeNullishValuesInArrays";
901
+ OptionsEnum["preserveDeletedFieldsValues"] = "preserveDeletedFieldsValues";
902
+ OptionsEnum["autoTrimValue"] = "autoTrimValue";
903
+ OptionsEnum["autoParseNumbers"] = "autoParseNumbers";
904
+ OptionsEnum["validationDebounceWait"] = "validationDebounceWait";
905
+ OptionsEnum["validationDebounceOptions"] = "validationDebounceOptions";
906
+ OptionsEnum["stopValidationOnError"] = "stopValidationOnError";
907
+ OptionsEnum["validationPluginsOrder"] = "validationPluginsOrder";
908
+ OptionsEnum["resetValidationBeforeValidate"] = "resetValidationBeforeValidate";
909
+ OptionsEnum["applyInputConverterOnInit"] = "applyInputConverterOnInit";
910
+ OptionsEnum["applyInputConverterOnSet"] = "applyInputConverterOnSet";
911
+ OptionsEnum["applyInputConverterOnUpdate"] = "applyInputConverterOnUpdate";
912
+ OptionsEnum["bubbleUpErrorMessages"] = "bubbleUpErrorMessages";
913
+ })(OptionsEnum || (OptionsEnum = {}));
914
+
915
+ var ValidationHooks;
916
+ (function (ValidationHooks) {
917
+ ValidationHooks["onSuccess"] = "onSuccess";
918
+ ValidationHooks["onError"] = "onError";
919
+ })(ValidationHooks || (ValidationHooks = {}));
920
+
921
+ class Base {
922
+ noop = () => { };
923
+ state;
924
+ fields = new ArrayMap();
925
+ path;
926
+ $submitted = 0;
927
+ $submitting = false;
928
+ $validated = 0;
929
+ $validating = false;
930
+ $clearing = false;
931
+ $resetting = false;
932
+ $touched = false;
933
+ $changed = 0;
934
+ $hooks = {};
935
+ $handlers = {};
936
+ constructor() {
937
+ makeObservable(this, {
938
+ $submitted: mobx.observable,
939
+ $submitting: mobx.observable,
940
+ $validated: mobx.observable,
941
+ $validating: mobx.observable,
942
+ $clearing: mobx.observable,
943
+ $resetting: mobx.observable,
944
+ $touched: mobx.observable,
945
+ $changed: mobx.observable,
946
+ $hooks: mobx.observable,
947
+ $handlers: mobx.observable,
948
+ changed: mobx.computed,
949
+ submitted: mobx.computed,
950
+ submitting: mobx.computed,
951
+ validated: mobx.computed,
952
+ validating: mobx.computed,
953
+ clearing: mobx.computed,
954
+ resetting: mobx.computed,
955
+ hasIncrementalKeys: mobx.computed,
956
+ hasNestedFields: mobx.computed,
957
+ size: mobx.computed,
958
+ // initialization
959
+ initField: mobx.action,
960
+ // actions
961
+ submit: mobx.action,
962
+ deepUpdate: mobx.action,
963
+ set: mobx.action,
964
+ add: mobx.action,
965
+ del: mobx.action,
966
+ });
967
+ }
968
+ execHook = (name, fallback = {}, ...args) => $try(fallback[name], this.$hooks[name], this.noop).apply(this, [this, ...args]);
969
+ execHandler = (name, args, fallback = undefined, hook = null, execHook = true) => [
970
+ $try(this.$handlers[name] && this.$handlers[name].apply(this, [this]), fallback, this.noop).apply(this, [...args]),
971
+ execHook && this.execHook(hook || name, {}, ...args),
972
+ ];
973
+ get resetting() {
974
+ return this.hasNestedFields
975
+ ? this.check(FieldPropsEnum.resetting, true)
976
+ : this.$resetting;
977
+ }
978
+ get clearing() {
979
+ return this.hasNestedFields
980
+ ? this.check(FieldPropsEnum.clearing, true)
981
+ : this.$clearing;
982
+ }
983
+ get submitted() {
984
+ return mobx.toJS(this.$submitted);
985
+ }
986
+ get submitting() {
987
+ return mobx.toJS(this.$submitting);
988
+ }
989
+ get validated() {
990
+ return mobx.toJS(this.$validated);
991
+ }
992
+ get validating() {
993
+ return mobx.toJS(this.$validating);
994
+ }
995
+ get hasIncrementalKeys() {
996
+ return !!this.fields.size && hasIntKeys(this.fields);
997
+ }
998
+ get hasNestedFields() {
999
+ return this.fields.size !== 0;
1000
+ }
1001
+ get size() {
1002
+ return this.fields.size;
1003
+ }
1004
+ get changed() {
1005
+ return this.path != null && this.hasNestedFields
1006
+ ? this.reduce((acc, field) => acc + field.changed, 0) + this.$changed
1007
+ : this.$changed;
1008
+ }
1009
+ /**
1010
+ Interceptor
1011
+ */
1012
+ intercept = (opt) => this.MOBXEvent(typeof opt === "function"
1013
+ ? { type: "interceptor", call: opt }
1014
+ : { type: "interceptor", ...opt });
1015
+ /**
1016
+ Observer
1017
+ */
1018
+ observe = (opt) => this.MOBXEvent(typeof opt === "function"
1019
+ ? { type: "observer", call: opt }
1020
+ : { type: "observer", ...opt });
1021
+ /**
1022
+ Event Handler: On Clear
1023
+ */
1024
+ onClear = (...args) => this.execHandler(FieldPropsEnum.onClear, args, (e) => {
1025
+ isEvent(e) && e.preventDefault();
1026
+ this.clear(true, false);
1027
+ });
1028
+ /**
1029
+ Event Handler: On Reset
1030
+ */
1031
+ onReset = (...args) => this.execHandler(FieldPropsEnum.onReset, args, (e) => {
1032
+ isEvent(e) && e.preventDefault();
1033
+ this.reset(true, false);
1034
+ });
1035
+ /**
1036
+ Event Handler: On Submit
1037
+ */
1038
+ onSubmit = (...args) => this.execHandler(FieldPropsEnum.onSubmit, args, (e, o = {}) => {
1039
+ isEvent(e) && e.preventDefault();
1040
+ this.submit(o);
1041
+ }, null, false);
1042
+ /**
1043
+ Event Handler: On Add
1044
+ */
1045
+ onAdd = (...args) => this.execHandler(FieldPropsEnum.onAdd, args, (e, val) => {
1046
+ isEvent(e) && e.preventDefault();
1047
+ this.add(isEvent(val) ? null : val, false);
1048
+ });
1049
+ /**
1050
+ Event Handler: On Del
1051
+ */
1052
+ onDel = (...args) => this.execHandler(FieldPropsEnum.onDel, args, (e, path) => {
1053
+ isEvent(e) && e.preventDefault();
1054
+ this.del(isEvent(path) ? this.path : path, false);
1055
+ });
1056
+ /******************************************************************
1057
+ Initializer
1058
+ */
1059
+ initFields(initial, update = false) {
1060
+ const fallback = this.state.options.get(OptionsEnum.fallback);
1061
+ const $path = (key) => [this.path, key].join(".").replace(/^\.+/, "");
1062
+ let fields;
1063
+ fields = prepareFieldsData(initial, this.state.strict, fallback);
1064
+ fields = mergeSchemaDefaults(fields, this.validator);
1065
+ // create fields
1066
+ lodash.forIn(fields, (field, key) => {
1067
+ const path = $path(key);
1068
+ const $f = this.select(path, null, false);
1069
+ if ($f == null) {
1070
+ if (fallback) {
1071
+ this.initField(key, path, field, update);
1072
+ }
1073
+ else {
1074
+ const structPath = pathToStruct(path);
1075
+ const struct = this.state.struct();
1076
+ const found = struct
1077
+ .filter((s) => s.startsWith(structPath))
1078
+ .find((s) => s.charAt(structPath.length) === "." ||
1079
+ s.substring(structPath.length, structPath.length + 2) ===
1080
+ "[]" ||
1081
+ s === structPath);
1082
+ if (found)
1083
+ this.initField(key, path, field, update);
1084
+ }
1085
+ }
1086
+ });
1087
+ }
1088
+ initField(key, path, data, update = false) {
1089
+ const initial = this.state.get("current", "props");
1090
+ const struct = pathToStruct(path);
1091
+ // try to get props from separated objects
1092
+ const _try = (prop) => {
1093
+ const t = lodash.get(initial[prop], struct);
1094
+ if ([
1095
+ FieldPropsEnum.input,
1096
+ FieldPropsEnum.output,
1097
+ FieldPropsEnum.converter,
1098
+ ].includes(prop) &&
1099
+ typeof t !== "function")
1100
+ return undefined;
1101
+ return t;
1102
+ };
1103
+ const props = {
1104
+ $value: lodash.get(initial[SeparatedPropsMode.values], path),
1105
+ $computed: _try(SeparatedPropsMode.computed),
1106
+ $label: _try(SeparatedPropsMode.labels),
1107
+ $placeholder: _try(SeparatedPropsMode.placeholders),
1108
+ $default: _try(SeparatedPropsMode.defaults),
1109
+ $initial: _try(SeparatedPropsMode.initials),
1110
+ $disabled: _try(SeparatedPropsMode.disabled),
1111
+ $deleted: _try(SeparatedPropsMode.deleted),
1112
+ $type: _try(SeparatedPropsMode.types),
1113
+ $related: _try(SeparatedPropsMode.related),
1114
+ $rules: _try(SeparatedPropsMode.rules),
1115
+ $options: _try(SeparatedPropsMode.options),
1116
+ $bindings: _try(SeparatedPropsMode.bindings),
1117
+ $extra: _try(SeparatedPropsMode.extra),
1118
+ $hooks: _try(SeparatedPropsMode.hooks),
1119
+ $handlers: _try(SeparatedPropsMode.handlers),
1120
+ $validatedWith: _try(SeparatedPropsMode.validatedWith),
1121
+ $validators: _try(SeparatedPropsMode.validators),
1122
+ $observers: _try(SeparatedPropsMode.observers),
1123
+ $interceptors: _try(SeparatedPropsMode.interceptors),
1124
+ $converters: _try(SeparatedPropsMode.converters),
1125
+ $input: _try(SeparatedPropsMode.input),
1126
+ $output: _try(SeparatedPropsMode.output),
1127
+ $autoFocus: _try(SeparatedPropsMode.autoFocus),
1128
+ $ref: _try(SeparatedPropsMode.refs),
1129
+ $nullable: _try(SeparatedPropsMode.nullable),
1130
+ $autoComplete: _try(SeparatedPropsMode.autoComplete),
1131
+ };
1132
+ const field = this.state.form.makeField({
1133
+ key,
1134
+ path,
1135
+ struct,
1136
+ data,
1137
+ props,
1138
+ update,
1139
+ state: this.state,
1140
+ }, (data && data[FieldPropsEnum.class]) || _try(SeparatedPropsMode.classes));
1141
+ this.fields.merge({ [key]: field });
1142
+ return field;
1143
+ }
1144
+ /******************************************************************
1145
+ Actions
1146
+ */
1147
+ validate(opt, obj) {
1148
+ const $opt = lodash.merge({}, opt, { path: this.path });
1149
+ return this.state.form.validator.validate($opt, obj);
1150
+ }
1151
+ /**
1152
+ Submit
1153
+ */
1154
+ submit(hooks = {}, { execOnSubmitHook = true, execValidationHooks = true, validate = true, } = {}) {
1155
+ const execOnSubmit = () => this.execHook(FieldPropsEnum.onSubmit, hooks);
1156
+ const submit = execOnSubmitHook ? execOnSubmit() : undefined;
1157
+ this.$submitting = true;
1158
+ this.$submitted += 1;
1159
+ if (!validate ||
1160
+ !this.state.options.get(OptionsEnum.validateOnSubmit, this)) {
1161
+ return Promise.resolve(submit)
1162
+ .then(mobx.action(() => (this.$submitting = false)))
1163
+ .catch(mobx.action((err) => {
1164
+ this.$submitting = false;
1165
+ throw err;
1166
+ }))
1167
+ .then(() => this);
1168
+ }
1169
+ const exec = (isValid) => isValid
1170
+ ? this.execHook(ValidationHooks.onSuccess, hooks)
1171
+ : this.execHook(ValidationHooks.onError, hooks);
1172
+ return this.validate({
1173
+ showErrors: this.state.options.get(OptionsEnum.showErrorsOnSubmit, this),
1174
+ })
1175
+ .then(({ isValid }) => {
1176
+ const handler = execValidationHooks ? exec(isValid) : undefined;
1177
+ if (isValid)
1178
+ return Promise.all([submit, handler]);
1179
+ const $err = this.state.options.get(OptionsEnum.defaultGenericError, this);
1180
+ const $throw = this.state.options.get(OptionsEnum.submitThrowsError, this);
1181
+ if ($throw && $err)
1182
+ this.invalidate();
1183
+ return Promise.all([submit, handler]);
1184
+ })
1185
+ .then(mobx.action(() => (this.$submitting = false)))
1186
+ .catch(mobx.action((err) => {
1187
+ this.$submitting = false;
1188
+ throw err;
1189
+ }))
1190
+ .then(() => this);
1191
+ }
1192
+ /**
1193
+ Check Field Computed Values
1194
+ */
1195
+ check(prop, deep = false) {
1196
+ allowedProps(AllowedFieldPropsTypes.computed, [prop]);
1197
+ return deep
1198
+ ? checkPropOccurrence({
1199
+ type: props.occurrences[prop],
1200
+ data: this.deepCheck(props.occurrences[prop], prop, this.fields),
1201
+ })
1202
+ : this[prop];
1203
+ }
1204
+ deepCheck(type, prop, fields) {
1205
+ const $fields = getObservableMapValues(fields);
1206
+ return lodash.transform($fields, (check, field) => {
1207
+ if (!field.fields.size || !Array.isArray(field.initial)) {
1208
+ check.push(field[prop]);
1209
+ }
1210
+ check.push(checkPropOccurrence({
1211
+ data: this.deepCheck(type, prop, field.fields),
1212
+ type,
1213
+ }));
1214
+ return check;
1215
+ }, []);
1216
+ }
1217
+ firstError() {
1218
+ if (!this.state.options.get(OptionsEnum.bubbleUpErrorMessages, this))
1219
+ return null;
1220
+ for (const field of getObservableMapValues(this.fields)) {
1221
+ if (field.error)
1222
+ return field.error;
1223
+ if (field.fields.size) {
1224
+ const nested = field.firstError();
1225
+ if (nested)
1226
+ return nested;
1227
+ }
1228
+ }
1229
+ return null;
1230
+ }
1231
+ /**
1232
+ Update Field Values recurisvely
1233
+ OR Create Field if 'undefined'
1234
+ */
1235
+ update(fields) {
1236
+ if (!lodash.isPlainObject(fields)) {
1237
+ throw new Error("The update() method accepts only plain objects.");
1238
+ }
1239
+ this.deepUpdate(prepareFieldsData({ fields }, this.state.strict), undefined, undefined, fields);
1240
+ }
1241
+ deepUpdate(fields, path = "", recursion = true, raw) {
1242
+ lodash.each(fields, (field, key) => {
1243
+ const $key = lodash.has(field, FieldPropsEnum.name) ? field.name : key;
1244
+ const $path = `${path}.${$key}`.replace(/^\.+/, "");
1245
+ const strictUpdate = this.state.options.get(OptionsEnum.strictUpdate, this);
1246
+ const $field = this.select($path, null, strictUpdate);
1247
+ const $container = this.select(path, null, false) ||
1248
+ this.state.form.select(this.path ?? "", null, false);
1249
+ const applyInputConverterOnUpdate = this.state.options.get(OptionsEnum.applyInputConverterOnUpdate, this);
1250
+ if ($field != null && field !== void 0) {
1251
+ if (Array.isArray($field.values())) {
1252
+ const n = Math.max(-1, ...Object.keys(field.fields || {}).map(Number));
1253
+ getObservableMapValues($field.fields).forEach(($f) => {
1254
+ if (Number($f.name) > n) {
1255
+ $field.$changed++;
1256
+ $field.state.form.$changed++;
1257
+ $field.fields.delete($f.name);
1258
+ }
1259
+ });
1260
+ }
1261
+ if (field?.fields) {
1262
+ const fallback = this.state.options.get(OptionsEnum.fallback);
1263
+ const x = this.state
1264
+ .struct()
1265
+ .findIndex((s) => s.startsWith($field.path.replace(/\.\d+\./, "[].") + "[]"));
1266
+ if (!fallback && $field.fields.size === 0 && x < 0) {
1267
+ $field.value = parseInput(applyInputConverterOnUpdate ? $field.$input : (val) => val, {
1268
+ fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
1269
+ separated: lodash.get(raw, $path),
1270
+ });
1271
+ return;
1272
+ }
1273
+ }
1274
+ if (field === null || field.fields == null) {
1275
+ $field.value = parseInput(applyInputConverterOnUpdate ? $field.$input : (val) => val, {
1276
+ fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
1277
+ separated: field,
1278
+ });
1279
+ return;
1280
+ }
1281
+ }
1282
+ if ($container != null && $field == null) {
1283
+ // get full path when using update() with select() - FIX: #179
1284
+ const $newFieldPath = [this.path, $path].join(".").replace(/^\.+/, "");
1285
+ // init field into the container field
1286
+ $container.$changed++;
1287
+ $container.state.form.$changed++;
1288
+ $container.initField($key, $newFieldPath, field, true);
1289
+ }
1290
+ else if (recursion) {
1291
+ if (lodash.has(field, FieldPropsEnum.fields) && field.fields != null) {
1292
+ // handle nested fields if defined
1293
+ this.deepUpdate(field.fields, $path);
1294
+ }
1295
+ else {
1296
+ // handle nested fields if undefined or null
1297
+ const $fields = pathToFieldsTree(this.state.struct(), $path);
1298
+ this.deepUpdate($fields, $path, false);
1299
+ }
1300
+ }
1301
+ });
1302
+ }
1303
+ /**
1304
+ Get Fields Props
1305
+ */
1306
+ get(prop = null, strict = true) {
1307
+ if (prop == null) {
1308
+ return this.deepGet([...props.computed, ...props.editable, ...props.validation], this.fields, strict);
1309
+ }
1310
+ allowedProps(AllowedFieldPropsTypes.all, Array.isArray(prop) ? prop : [prop]);
1311
+ if (typeof prop === "string") {
1312
+ if ([FieldPropsEnum.hooks, FieldPropsEnum.handlers].includes(prop)) {
1313
+ return this[`$${prop}`];
1314
+ }
1315
+ if (strict && this.fields.size === 0) {
1316
+ const retrieveNullifiedEmptyStrings = this.state.options.get(OptionsEnum.retrieveNullifiedEmptyStrings, this);
1317
+ return parseCheckOutput(this, prop, strict ? retrieveNullifiedEmptyStrings : false);
1318
+ }
1319
+ const value = this.deepGet(prop, this.fields, strict);
1320
+ const removeNullishValuesInArrays = this.state.options.get(OptionsEnum.removeNullishValuesInArrays, this);
1321
+ return parseCheckArray(this, value, prop, strict ? removeNullishValuesInArrays : false);
1322
+ }
1323
+ return this.deepGet(prop, this.fields, strict);
1324
+ }
1325
+ /**
1326
+ Get Fields Props Recursively
1327
+ */
1328
+ deepGet(prop, fields, strict = true) {
1329
+ const _fieldsArr = getObservableMapValues(fields);
1330
+ const _result = lodash.transform(_fieldsArr, (obj, field) => {
1331
+ const $nested = ($fields) => $fields.size !== 0 ? this.deepGet(prop, $fields, strict) : undefined;
1332
+ Object.assign(obj, {
1333
+ [field.key]: { fields: $nested(field.fields) },
1334
+ });
1335
+ if (typeof prop === "string") {
1336
+ const opt = this.state.options;
1337
+ const removeProp = (opt.get(OptionsEnum.retrieveOnlyDirtyFieldsValues, this) &&
1338
+ prop === FieldPropsEnum.value &&
1339
+ field.isPristine) ||
1340
+ (opt.get(OptionsEnum.retrieveOnlyEnabledFieldsValues, this) &&
1341
+ prop === FieldPropsEnum.value &&
1342
+ field.disabled) ||
1343
+ (opt.get(OptionsEnum.retrieveOnlyEnabledFieldsErrors, this) &&
1344
+ prop === FieldPropsEnum.error &&
1345
+ field.disabled &&
1346
+ field.isValid &&
1347
+ (!field.error || !field.hasError)) ||
1348
+ (opt.get(OptionsEnum.softDelete, this) &&
1349
+ prop === FieldPropsEnum.value &&
1350
+ field.deleted);
1351
+ if (field.fields.size === 0) {
1352
+ delete obj[field.key];
1353
+ if (removeProp)
1354
+ return obj;
1355
+ const retrieveNullifiedEmptyStrings = this.state.options.get(OptionsEnum.retrieveNullifiedEmptyStrings, this);
1356
+ return Object.assign(obj, {
1357
+ [field.key]: parseCheckOutput(field, prop, strict ? retrieveNullifiedEmptyStrings : false),
1358
+ });
1359
+ }
1360
+ let value = this.deepGet(prop, field.fields, strict);
1361
+ if (prop === FieldPropsEnum.value)
1362
+ value = field.$output(value);
1363
+ delete obj[field.key];
1364
+ if (removeProp)
1365
+ return obj;
1366
+ const removeNullishValuesInArrays = this.state.options.get(OptionsEnum.removeNullishValuesInArrays, this);
1367
+ return Object.assign(obj, {
1368
+ [field.key]: parseCheckArray(field, value, prop, strict ? removeNullishValuesInArrays : false),
1369
+ });
1370
+ }
1371
+ lodash.each(prop, ($prop) => Object.assign(obj[field.key], {
1372
+ [$prop]: field[$prop],
1373
+ }));
1374
+ return obj;
1375
+ }, {});
1376
+ // Array fields with integer keys must preserve _entries order
1377
+ // (JavaScript Object.assign sorts integer-like keys regardless of insertion order)
1378
+ if (typeof prop === "string" &&
1379
+ _fieldsArr.length > 0 &&
1380
+ hasIntKeys(fields)) {
1381
+ const keysInResult = new Set(Object.keys(_result));
1382
+ return _fieldsArr
1383
+ .filter((f) => keysInResult.has(String(f.key)))
1384
+ .map((f) => _result[String(f.key)]);
1385
+ }
1386
+ return _result;
1387
+ }
1388
+ /**
1389
+ Set Fields Props
1390
+ */
1391
+ set(prop, data) {
1392
+ // UPDATE CUSTOM PROP
1393
+ if (typeof prop === "string" && data !== void 0) {
1394
+ allowedProps(AllowedFieldPropsTypes.editable, [prop]);
1395
+ const isPlain = [FieldPropsEnum.hooks, FieldPropsEnum.handlers].includes(prop);
1396
+ const deep = (data !== null &&
1397
+ typeof data === "object" &&
1398
+ prop === FieldPropsEnum.value) ||
1399
+ (lodash.isPlainObject(data) && !isPlain);
1400
+ if (deep && this.hasNestedFields)
1401
+ return this.deepSet(prop, data, "", true);
1402
+ if (prop === FieldPropsEnum.value) {
1403
+ const applyInputConverterOnSet = this.state.options.get(OptionsEnum.applyInputConverterOnSet, this);
1404
+ this.value = parseInput(applyInputConverterOnSet ? this.$input : (val) => val, {
1405
+ fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
1406
+ separated: data,
1407
+ });
1408
+ }
1409
+ else if (isPlain) {
1410
+ Object.assign(this[`$${prop}`], data);
1411
+ }
1412
+ else {
1413
+ lodash.set(this, `$${prop}`, data);
1414
+ }
1415
+ return;
1416
+ }
1417
+ // NO PROP NAME PROVIDED ("prop" is value)
1418
+ if (data == null) {
1419
+ if (this.hasNestedFields)
1420
+ this.deepSet(FieldPropsEnum.value, prop, "", true);
1421
+ else
1422
+ this.set(FieldPropsEnum.value, prop);
1423
+ }
1424
+ }
1425
+ /**
1426
+ Set Fields Props Recursively
1427
+ */
1428
+ deepSet(prop, data, path = "", recursion = false) {
1429
+ const err = "You are updating a not existent field:";
1430
+ const isStrict = this.state.options.get(OptionsEnum.strictSet, this);
1431
+ if (data == null) {
1432
+ this.each((field) => (field.$value = defaultValue({
1433
+ fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
1434
+ value: field.$value,
1435
+ nullable: field.$nullable,
1436
+ type: field.type,
1437
+ })));
1438
+ return;
1439
+ }
1440
+ lodash.each(data, ($val, $key) => {
1441
+ const $path = `${path}.${$key}`.replace(/^\.+/, "");
1442
+ // get the field by path joining keys recursively
1443
+ const field = this.select($path, null, isStrict);
1444
+ // if no field found when is strict update, throw error
1445
+ if (isStrict)
1446
+ throwError($path, field, err);
1447
+ // update the field/fields if defined
1448
+ if (field !== void 0) {
1449
+ // update field values or others props
1450
+ if ($val !== void 0) {
1451
+ field.set(prop, $val, recursion);
1452
+ }
1453
+ // update values recursively only if field has nested
1454
+ if (field.fields.size && $val !== null && typeof $val === "object") {
1455
+ this.deepSet(prop, $val, $path, recursion);
1456
+ }
1457
+ }
1458
+ });
1459
+ }
1460
+ /**
1461
+ Add Field
1462
+ */
1463
+ add(obj, execEvent = true) {
1464
+ if (isArrayOfObjects(obj)) {
1465
+ lodash.each(obj, (values) => this.update({
1466
+ [maxKey(this.fields)]: values,
1467
+ }));
1468
+ this.$changed++;
1469
+ this.state.form.$changed++;
1470
+ execEvent && this.execHook(FieldPropsEnum.onAdd);
1471
+ return this;
1472
+ }
1473
+ let key;
1474
+ if (lodash.has(obj, FieldPropsEnum.key))
1475
+ key = obj.key;
1476
+ if (lodash.has(obj, FieldPropsEnum.name))
1477
+ key = obj.name;
1478
+ if (!key)
1479
+ key = maxKey(this.fields);
1480
+ const $path = ($key) => [this.path, $key].join(".").replace(/^\.+/, "");
1481
+ const tree = pathToFieldsTree(this.state.struct(), this.path ?? "", 0, true);
1482
+ const field = this.initField(key, $path(key), lodash.merge(tree[0], obj));
1483
+ const hasValues = lodash.has(obj, FieldPropsEnum.value) || lodash.has(obj, FieldPropsEnum.fields);
1484
+ if (!hasValues) {
1485
+ // When the struct defines nested fields and obj is a plain object
1486
+ // without field-definition props (key, name), treat obj properties
1487
+ // directly as nested field values (e.g. add({ firstname: 'John' }))
1488
+ if (tree[0]?.fields &&
1489
+ lodash.isPlainObject(obj) &&
1490
+ !hasSome(obj, [FieldPropsEnum.key, FieldPropsEnum.name])) {
1491
+ lodash.each(obj, (val, fieldName) => {
1492
+ const nestedField = field.select(fieldName);
1493
+ if (nestedField && !nestedField.hasNestedFields) {
1494
+ nestedField.set(FieldPropsEnum.value, val);
1495
+ }
1496
+ });
1497
+ }
1498
+ else if (!this.state.options.get(OptionsEnum.preserveDeletedFieldsValues, this)) {
1499
+ const fallbackValueOption = this.state.options.get(OptionsEnum.fallbackValue, this);
1500
+ field.$value = defaultValue({
1501
+ fallbackValueOption,
1502
+ value: field.$value,
1503
+ nullable: field.$nullable,
1504
+ type: field.type,
1505
+ });
1506
+ field.each((f) => (f.$value = defaultValue({
1507
+ fallbackValueOption,
1508
+ value: f.$value,
1509
+ nullable: f.$nullable,
1510
+ type: f.type,
1511
+ })));
1512
+ }
1513
+ }
1514
+ this.$changed++;
1515
+ this.state.form.$changed++;
1516
+ execEvent && this.execHook(FieldPropsEnum.onAdd);
1517
+ return field;
1518
+ }
1519
+ /**
1520
+ Del Field
1521
+ */
1522
+ del($path = null, execEvent = true) {
1523
+ const isStrict = this.state.options.get(OptionsEnum.strictDelete, this);
1524
+ const path = parsePath($path ?? this.path ?? "");
1525
+ const fullpath = [this.path ?? "", path ?? ""]
1526
+ .join(".")
1527
+ .replace(/^\.+|\.+$/g, "");
1528
+ const container = this.container($path);
1529
+ const keys = path.split(".");
1530
+ const lastKey = keys[keys.length - 1];
1531
+ if (isStrict && !container.fields.has(lastKey)) {
1532
+ const msg = `Key "${lastKey}" not found when trying to delete field`;
1533
+ throwError(fullpath, null, msg);
1534
+ }
1535
+ container.$changed++;
1536
+ container.state.form.$changed++;
1537
+ if (this.state.options.get(OptionsEnum.softDelete, this)) {
1538
+ return this.select(fullpath).set(FieldPropsEnum.deleted, true);
1539
+ }
1540
+ container.each((field) => field.debouncedValidation.cancel());
1541
+ execEvent && this.execHook(FieldPropsEnum.onDel);
1542
+ return container.fields.delete(lastKey);
1543
+ }
1544
+ /******************************************************************
1545
+ Events
1546
+ */
1547
+ /**
1548
+ MobX Event (observe/intercept)
1549
+ */
1550
+ MOBXEvent({ prop = FieldPropsEnum.value, key = null, path = null, call, type, }) {
1551
+ let $prop = key || prop;
1552
+ allowedProps(AllowedFieldPropsTypes.observable, [$prop]);
1553
+ const $instance = this.select(path || this.path, null, false) || this;
1554
+ const $call = (change) => call.apply(null, [
1555
+ {
1556
+ change,
1557
+ form: this.state.form,
1558
+ path: $instance.path || null,
1559
+ field: $instance.path ? $instance : null,
1560
+ },
1561
+ ]);
1562
+ let fn;
1563
+ let ffn;
1564
+ if (type === "observer") {
1565
+ fn = mobx.observe;
1566
+ ffn = (cb) => mobx.observe($instance.fields.toArray(), cb); // fields
1567
+ }
1568
+ if (type === "interceptor") {
1569
+ $prop = `$${prop}`;
1570
+ fn = mobx.intercept;
1571
+ ffn = $instance.fields.intercept; // fields
1572
+ }
1573
+ const $dkey = $instance.path ? `${$prop}@${$instance.path}` : $prop;
1574
+ lodash.merge(this.state.disposers[type], {
1575
+ [$dkey]: $prop === FieldPropsEnum.fields
1576
+ ? ffn.apply((change) => $call(change))
1577
+ : fn($instance, $prop, (change) => $call(change)),
1578
+ });
1579
+ }
1580
+ /**
1581
+ Dispose MOBX Events
1582
+ */
1583
+ dispose(opt = null) {
1584
+ if (this.path && opt)
1585
+ return this.disposeSingle(opt);
1586
+ return this.disposeAll();
1587
+ }
1588
+ /**
1589
+ Dispose All Events (observe/intercept)
1590
+ */
1591
+ disposeAll() {
1592
+ const dispose = (disposer) => disposer.apply();
1593
+ lodash.each(this.state.disposers.interceptor, dispose);
1594
+ lodash.each(this.state.disposers.observer, dispose);
1595
+ this.state.disposers = { interceptor: {}, observer: {} };
1596
+ return;
1597
+ }
1598
+ /**
1599
+ Dispose Single Event (observe/intercept)
1600
+ */
1601
+ disposeSingle({ type, key = FieldPropsEnum.value, path = null }) {
1602
+ const $path = parsePath(path ?? this.path ?? "");
1603
+ // eslint-disable-next-line
1604
+ if (type === "interceptor")
1605
+ key = `$${key}`; // target observables
1606
+ const disposersType = this.state.disposers[type];
1607
+ disposersType[`${key}@${$path}`].apply();
1608
+ delete disposersType[`${key}@${$path}`];
1609
+ }
1610
+ /******************************************************************
1611
+ Utils
1612
+ */
1613
+ /**
1614
+ Fields Selector
1615
+ */
1616
+ select(path, fields = null, isStrict = true) {
1617
+ const $path = parsePath(String(path));
1618
+ const keys = $path.split(".");
1619
+ const headKey = keys[0];
1620
+ keys.shift();
1621
+ let $fields = fields == null ? this.fields.get(headKey) : fields.get(headKey);
1622
+ let stop = false;
1623
+ lodash.each(keys, ($key) => {
1624
+ if (stop)
1625
+ return;
1626
+ if ($fields == null) {
1627
+ $fields = undefined;
1628
+ stop = true;
1629
+ }
1630
+ else {
1631
+ $fields = $fields.fields.get($key);
1632
+ }
1633
+ });
1634
+ if (isStrict && this.state.options.get(OptionsEnum.strictSelect, this)) {
1635
+ throwError(String(path), $fields);
1636
+ }
1637
+ return $fields;
1638
+ }
1639
+ /**
1640
+ Get Container
1641
+ */
1642
+ container($path) {
1643
+ const path = parsePath($path ?? this.path ?? "");
1644
+ const cpath = path.replace(/[^./]+$/, "").replace(/^\.+|\.+$/g, "");
1645
+ if (!!this.path && $path == null) {
1646
+ return cpath !== ""
1647
+ ? this.state.form.select(cpath, null, false)
1648
+ : this.state.form;
1649
+ }
1650
+ return cpath !== "" ? this.select(cpath, null, false) : this;
1651
+ }
1652
+ /**
1653
+ Has Field
1654
+ */
1655
+ has(path) {
1656
+ return this.fields.has(path);
1657
+ }
1658
+ /**
1659
+ Map Fields
1660
+ */
1661
+ map(cb) {
1662
+ return getObservableMapValues(this.fields).map(cb);
1663
+ }
1664
+ /**
1665
+ * Iterates deeply over fields and invokes `iteratee` for each element.
1666
+ * The iteratee is invoked with three arguments: (value, index|key, depth).
1667
+ *
1668
+ * @param {Function} iteratee The function invoked per iteration.
1669
+ * @param {Array|Object} [fields=form.fields] fields to iterate over.
1670
+ * @param {number} [depth=1] The recursion depth for internal use.
1671
+ * @returns {Array} Returns [fields.values()] of input [fields] parameter.
1672
+ * @example
1673
+ *
1674
+ * JSON.stringify(form)
1675
+ * // => {
1676
+ * "fields": {
1677
+ * "state": {
1678
+ * "fields": {
1679
+ * "city": {
1680
+ * "fields": { "places": {
1681
+ * "fields": {},
1682
+ * "key": "places", "path": "state.city.places", "$value": "NY Places"
1683
+ * }
1684
+ * },
1685
+ * "key": "city", "path": "state.city", "$value": "New York"
1686
+ * }
1687
+ * },
1688
+ * "key": "state", "path": "state", "$value": "USA"
1689
+ * }
1690
+ * }
1691
+ * }
1692
+ *
1693
+ * const data = {};
1694
+ * form.each(field => data[field.path] = field.value);
1695
+ * // => {
1696
+ * "state": "USA",
1697
+ * "state.city": "New York",
1698
+ * "state.city.places": "NY Places"
1699
+ * }
1700
+ *
1701
+ */
1702
+ each(iteratee, fields = null, depth = 0) {
1703
+ const $fields = fields || this.fields;
1704
+ getObservableMapValues($fields).forEach((field, index) => {
1705
+ iteratee(field, index, depth);
1706
+ if (field.fields.size !== 0) {
1707
+ this.each(iteratee, field.fields, depth + 1);
1708
+ }
1709
+ });
1710
+ }
1711
+ reduce(iteratee, acc) {
1712
+ return getObservableMapValues(this.fields).reduce(iteratee, acc);
1713
+ }
1714
+ /******************************************************************
1715
+ Array Operations
1716
+ */
1717
+ /**
1718
+ Move a field from one index to another (for sortable lists).
1719
+ */
1720
+ move(fromIndex, toIndex) {
1721
+ this.fields.move(fromIndex, toIndex);
1722
+ }
1723
+ /******************************************************************
1724
+ Helpers
1725
+ */
1726
+ /**
1727
+ Fields Selector (alias of select)
1728
+ */
1729
+ $(key) {
1730
+ return this.select(key);
1731
+ }
1732
+ /**
1733
+ Fields Values (recursive with Nested Fields)
1734
+ */
1735
+ values() {
1736
+ return this.get(FieldPropsEnum.value);
1737
+ }
1738
+ /**
1739
+ Fields Errors (recursive with Nested Fields)
1740
+ */
1741
+ errors() {
1742
+ return this.get(FieldPropsEnum.error);
1743
+ }
1744
+ /**
1745
+ Fields Labels (recursive with Nested Fields)
1746
+ */
1747
+ labels() {
1748
+ return this.get(FieldPropsEnum.label);
1749
+ }
1750
+ /**
1751
+ Fields Placeholders (recursive with Nested Fields)
1752
+ */
1753
+ placeholders() {
1754
+ return this.get(FieldPropsEnum.placeholder);
1755
+ }
1756
+ /**
1757
+ Fields Default Values (recursive with Nested Fields)
1758
+ */
1759
+ defaults() {
1760
+ return this.get(FieldPropsEnum.default);
1761
+ }
1762
+ /**
1763
+ Fields Initial Values (recursive with Nested Fields)
1764
+ */
1765
+ initials() {
1766
+ return this.get(FieldPropsEnum.initial);
1767
+ }
1768
+ /**
1769
+ Fields Types (recursive with Nested Fields)
1770
+ */
1771
+ types() {
1772
+ return this.get(FieldPropsEnum.type);
1773
+ }
1774
+ }
1775
+
1776
+ class Validator {
1777
+ promises = [];
1778
+ form = null;
1779
+ drivers = {};
1780
+ plugins = {
1781
+ vjf: undefined,
1782
+ dvr: undefined,
1783
+ ajv: undefined,
1784
+ yup: undefined,
1785
+ zod: undefined,
1786
+ joi: undefined,
1787
+ valibot: undefined,
1788
+ vinejs: undefined,
1789
+ };
1790
+ error = null;
1791
+ constructor(obj) {
1792
+ makeObservable(this, {
1793
+ error: mobx.observable,
1794
+ validate: mobx.action,
1795
+ validateField: mobx.action,
1796
+ });
1797
+ this.form = obj.form;
1798
+ Object.assign(this.plugins, obj.plugins);
1799
+ this.initDrivers();
1800
+ }
1801
+ initDrivers() {
1802
+ Object.entries(this.plugins).forEach(([key, plugin]) => {
1803
+ this.drivers[key] = (plugin && plugin.class) &&
1804
+ new (plugin.class)({
1805
+ config: plugin.config,
1806
+ state: this.form.state,
1807
+ promises: this.promises,
1808
+ });
1809
+ });
1810
+ }
1811
+ validate(opt, obj) {
1812
+ const path = $try(opt?.path, opt);
1813
+ const instance = $try(opt?.field, this.form.select(path, null, false), this.form);
1814
+ const related = $try(opt?.related, obj?.related, true);
1815
+ const showErrors = $try(opt?.showErrors, obj?.showErrors, false);
1816
+ instance.$validating = true;
1817
+ instance.$validated += 1;
1818
+ this.error = null;
1819
+ return new Promise((resolve) => {
1820
+ // validate instance (form or filed)
1821
+ if (instance.path || typeof path === 'string') {
1822
+ this.validateField({
1823
+ field: instance,
1824
+ showErrors,
1825
+ related,
1826
+ path,
1827
+ });
1828
+ }
1829
+ // validate nested fields
1830
+ instance.each((field) => this.validateField({
1831
+ path: field.path,
1832
+ field: field,
1833
+ showErrors,
1834
+ related,
1835
+ }));
1836
+ // wait all promises
1837
+ resolve(Promise.all(this.promises.splice(0)));
1838
+ })
1839
+ .then(mobx.action(() => {
1840
+ instance.$validating = false;
1841
+ instance.$clearing = false;
1842
+ instance.$resetting = false;
1843
+ }))
1844
+ .catch(mobx.action((err) => {
1845
+ instance.$validating = false;
1846
+ instance.$clearing = false;
1847
+ instance.$resetting = false;
1848
+ throw err;
1849
+ }))
1850
+ .then(() => instance);
1851
+ }
1852
+ validateField({ showErrors = false, related = false, field = null, path, }) {
1853
+ const instance = field || this.form.select(path);
1854
+ const { options } = this.form.state;
1855
+ // check if the field is a valid instance
1856
+ if (!instance.path)
1857
+ throw new Error("Validation Error: Invalid Field Instance");
1858
+ // do not validate soft deleted fields
1859
+ if (instance.deleted && !options.get(OptionsEnum.validateDeletedFields, instance))
1860
+ return;
1861
+ // do not validate disabled fields
1862
+ if (instance.disabled && !options.get(OptionsEnum.validateDisabledFields, instance))
1863
+ return;
1864
+ // do not validate pristine fields
1865
+ if (instance.isPristine && !options.get(OptionsEnum.validatePristineFields, instance))
1866
+ return;
1867
+ // reset validation before validate
1868
+ if (options.get(OptionsEnum.resetValidationBeforeValidate, instance))
1869
+ instance.resetValidation();
1870
+ // trim string value before validation
1871
+ if (options.get(OptionsEnum.validateTrimmedValue, instance))
1872
+ instance.trim();
1873
+ // get stop on error
1874
+ const stopOnError = options.get(OptionsEnum.stopValidationOnError, instance);
1875
+ // get validation plugin order
1876
+ const validationPluginOrder = options.get(OptionsEnum.validationPluginsOrder, instance);
1877
+ const drivers = validationPluginOrder
1878
+ ? validationPluginOrder.map((n) => this.drivers[n])
1879
+ : this.drivers;
1880
+ // validate with all enabled drivers
1881
+ lodash.each(drivers, (driver) => {
1882
+ driver && driver.validate(instance);
1883
+ if (stopOnError && instance.hasError)
1884
+ return;
1885
+ });
1886
+ // send error to the view
1887
+ instance.showErrors(showErrors, false);
1888
+ // related validation
1889
+ if (related)
1890
+ this.validateRelatedFields(instance, showErrors);
1891
+ }
1892
+ /**
1893
+ Validate 'related' fields if specified
1894
+ and related validation allowed (recursive)
1895
+ */
1896
+ validateRelatedFields(field, showErrors) {
1897
+ if (!field.related || !field.related.length)
1898
+ return;
1899
+ field.related.map((path) => this.validateField({
1900
+ related: false,
1901
+ showErrors,
1902
+ path,
1903
+ }));
1904
+ }
1905
+ }
1906
+
1907
+ class Options {
1908
+ options = {
1909
+ uniqueId,
1910
+ fallback: true,
1911
+ fallbackValue: "",
1912
+ defaultGenericError: null,
1913
+ submitThrowsError: true,
1914
+ showErrorsOnInit: false,
1915
+ showErrorsOnSubmit: true,
1916
+ showErrorsOnBlur: true,
1917
+ showErrorsOnChange: true,
1918
+ showErrorsOnClear: false,
1919
+ showErrorsOnReset: true,
1920
+ validateOnInit: true,
1921
+ validateOnSubmit: true,
1922
+ validateOnBlur: true,
1923
+ validateOnChange: false,
1924
+ validateOnChangeAfterInitialBlur: false,
1925
+ validateOnChangeAfterSubmit: false,
1926
+ validateOnClear: false,
1927
+ validateOnReset: false,
1928
+ validateDisabledFields: false,
1929
+ validateDeletedFields: false,
1930
+ validatePristineFields: true,
1931
+ strictSet: false,
1932
+ strictUpdate: false,
1933
+ strictDelete: true,
1934
+ strictSelect: true,
1935
+ softDelete: false,
1936
+ retrieveOnlyDirtyFieldsValues: false,
1937
+ retrieveOnlyEnabledFieldsValues: false,
1938
+ retrieveOnlyEnabledFieldsErrors: false,
1939
+ retrieveNullifiedEmptyStrings: false,
1940
+ autoTrimValue: false,
1941
+ autoParseNumbers: false,
1942
+ removeNullishValuesInArrays: false,
1943
+ preserveDeletedFieldsValues: false,
1944
+ validationDebounceWait: 250,
1945
+ validationDebounceOptions: {
1946
+ leading: false,
1947
+ trailing: true,
1948
+ },
1949
+ stopValidationOnError: false,
1950
+ validationPluginsOrder: undefined,
1951
+ resetValidationBeforeValidate: true,
1952
+ validateTrimmedValue: false,
1953
+ applyInputConverterOnInit: true,
1954
+ applyInputConverterOnSet: true,
1955
+ applyInputConverterOnUpdate: true,
1956
+ bubbleUpErrorMessages: false,
1957
+ };
1958
+ constructor() {
1959
+ makeObservable(this, {
1960
+ options: mobx.observable,
1961
+ set: mobx.action,
1962
+ });
1963
+ }
1964
+ get(key = '', field = null) {
1965
+ // handle field option
1966
+ if (lodash.has(field, "path")) {
1967
+ if (lodash.has(field.$options, key)) {
1968
+ return field.$options[key];
1969
+ }
1970
+ }
1971
+ // fallback on global form options
1972
+ if (key)
1973
+ return lodash.get(this.options, key);
1974
+ return mobx.toJS(this.options);
1975
+ }
1976
+ set(options) {
1977
+ mobx.set(this.options, options);
1978
+ }
1979
+ }
1980
+
1981
+ class Bindings {
1982
+ templates = {
1983
+ // default: ({ field, form, props, keys, $try }) => ({
1984
+ // [keys.id]: $try(props.id, field.id),
1985
+ // }),
1986
+ };
1987
+ rewriters = {
1988
+ default: {
1989
+ id: FieldPropsEnum.id,
1990
+ name: FieldPropsEnum.name,
1991
+ type: FieldPropsEnum.type,
1992
+ value: FieldPropsEnum.value,
1993
+ checked: FieldPropsEnum.checked,
1994
+ label: FieldPropsEnum.label,
1995
+ placeholder: FieldPropsEnum.placeholder,
1996
+ disabled: FieldPropsEnum.disabled,
1997
+ autoComplete: FieldPropsEnum.autoComplete,
1998
+ onChange: FieldPropsEnum.onChange,
1999
+ onBlur: FieldPropsEnum.onBlur,
2000
+ onFocus: FieldPropsEnum.onFocus,
2001
+ autoFocus: FieldPropsEnum.autoFocus,
2002
+ inputMode: FieldPropsEnum.inputMode,
2003
+ onKeyUp: FieldPropsEnum.onKeyUp,
2004
+ onKeyDown: FieldPropsEnum.onKeyDown,
2005
+ },
2006
+ };
2007
+ register(bindings) {
2008
+ lodash.each(bindings, (val, key) => {
2009
+ if ((typeof val === 'function'))
2010
+ lodash.merge(this.templates, { [key]: val });
2011
+ if (lodash.isPlainObject(val))
2012
+ lodash.merge(this.rewriters, { [key]: val });
2013
+ });
2014
+ return this;
2015
+ }
2016
+ load(field, name = FieldPropsEnum.default, props) {
2017
+ const args = ({
2018
+ keys: lodash.get(this.rewriters, FieldPropsEnum.default),
2019
+ form: field.state.form,
2020
+ field,
2021
+ props,
2022
+ $try,
2023
+ });
2024
+ if (lodash.has(this.templates, name)) {
2025
+ return lodash.get(this.templates, name)(args);
2026
+ }
2027
+ if (lodash.has(this.rewriters, name)) {
2028
+ const $bindings = {};
2029
+ lodash.each(lodash.get(this.rewriters, name), ($v, $k) => lodash.merge($bindings, { [$v]: $try(props[$k], field[$k]) }));
2030
+ return $bindings;
2031
+ }
2032
+ if (lodash.has(this.templates, name)) {
2033
+ return lodash.get(this.templates, name)(args);
2034
+ }
2035
+ if (name === FieldPropsEnum.default) {
2036
+ const $bindings = {};
2037
+ lodash.each(lodash.get(this.rewriters, FieldPropsEnum.default), ($v, $k) => lodash.merge($bindings, { [$v]: $try(props[$k], field[$k]) }));
2038
+ return $bindings;
2039
+ }
2040
+ throw new Error(`Bindings: template or rewriter "${name}" does not exist \u2014 register it or use the "default" binding`);
2041
+ }
2042
+ }
2043
+
2044
+ var RuntimeMode;
2045
+ (function (RuntimeMode) {
2046
+ RuntimeMode["mixed"] = "mixed";
2047
+ RuntimeMode["unified"] = "unified";
2048
+ RuntimeMode["separated"] = "separated";
2049
+ })(RuntimeMode || (RuntimeMode = {}));
2050
+
2051
+ class State {
2052
+ mode = RuntimeMode.mixed;
2053
+ strict = false;
2054
+ form;
2055
+ options;
2056
+ bindings;
2057
+ $extra;
2058
+ $struct = [];
2059
+ disposers = {
2060
+ interceptor: {},
2061
+ observer: {},
2062
+ };
2063
+ initial = {
2064
+ props: {},
2065
+ fields: {},
2066
+ };
2067
+ current = {
2068
+ props: {},
2069
+ fields: {},
2070
+ };
2071
+ constructor({ form, initial, options, bindings }) {
2072
+ this.set("form", form);
2073
+ this.initProps(initial);
2074
+ this.options = new Options();
2075
+ this.options.set(options);
2076
+ this.bindings = new Bindings();
2077
+ this.bindings.register(bindings);
2078
+ this.observeOptions();
2079
+ }
2080
+ initProps(initial = {}) {
2081
+ const pickKeys = [
2082
+ ...props.editable,
2083
+ ...props.separated,
2084
+ ...props.validation,
2085
+ ...props.functions,
2086
+ ...props.handlers,
2087
+ ];
2088
+ const initialProps = Object.fromEntries(Object.entries(initial).filter(([k]) => pickKeys.includes(k)));
2089
+ this.set("initial", "props", initialProps);
2090
+ const $unified = hasUnifiedProps(initial);
2091
+ const $separated = hasSeparatedProps(initial);
2092
+ if (($separated || isArrayOfStrings(initial.fields)) && !$unified) {
2093
+ const struct = $try(initial.struct, initial.fields);
2094
+ this.struct(struct);
2095
+ this.strict = true;
2096
+ this.mode = RuntimeMode.separated;
2097
+ return;
2098
+ }
2099
+ this.struct(initial.struct);
2100
+ this.mode = RuntimeMode.unified;
2101
+ }
2102
+ /**
2103
+ Get/Set Fields Structure
2104
+ */
2105
+ struct(data = null) {
2106
+ if (data)
2107
+ this.$struct = data;
2108
+ return this.$struct;
2109
+ }
2110
+ /**
2111
+ Get Props/Fields
2112
+ */
2113
+ get(type, subtype) {
2114
+ return this[type][subtype];
2115
+ }
2116
+ /**
2117
+ Set Props/Fields
2118
+ */
2119
+ set(type, subtype, state = null) {
2120
+ if (type === "form") {
2121
+ // subtype is the form here
2122
+ this.form = subtype;
2123
+ }
2124
+ if (type === "initial") {
2125
+ Object.assign(this.initial[subtype], state);
2126
+ Object.assign(this.current[subtype], state);
2127
+ }
2128
+ if (type === "current") {
2129
+ Object.assign(this.current[subtype], state);
2130
+ }
2131
+ }
2132
+ extra(data = null) {
2133
+ if (typeof data === 'string')
2134
+ return lodash.get(this.$extra, data);
2135
+ if (data === null)
2136
+ return this.$extra;
2137
+ this.$extra = data;
2138
+ return null;
2139
+ }
2140
+ observeOptions() {
2141
+ // Fix Issue #201
2142
+ mobx.observe(this.options.options, checkObserve([
2143
+ {
2144
+ // start observing fields validateOnChange
2145
+ type: "update",
2146
+ key: OptionsEnum.validateOnChange,
2147
+ to: true,
2148
+ exec: () => this.form.each((field) => field.observeValidationOnChange()),
2149
+ },
2150
+ {
2151
+ // stop observing fields validateOnChange
2152
+ type: "update",
2153
+ key: OptionsEnum.validateOnChange,
2154
+ to: false,
2155
+ exec: () => this.form.each((field) => {
2156
+ if (typeof field.disposeValidationOnChange !== "function")
2157
+ return;
2158
+ field.disposeValidationOnChange();
2159
+ }),
2160
+ },
2161
+ {
2162
+ // start observing fields validateOnBlur
2163
+ type: "update",
2164
+ key: OptionsEnum.validateOnBlur,
2165
+ to: true,
2166
+ exec: () => this.form.each((field) => field.observeValidationOnBlur()),
2167
+ },
2168
+ {
2169
+ // stop observing fields validateOnBlur
2170
+ type: "update",
2171
+ key: OptionsEnum.validateOnBlur,
2172
+ to: false,
2173
+ exec: () => this.form.each((field) => {
2174
+ if (typeof field.disposeValidationOnBlur !== "function")
2175
+ return;
2176
+ field.disposeValidationOnBlur();
2177
+ }),
2178
+ },
2179
+ ]));
2180
+ }
2181
+ }
2182
+
2183
+ const applyFieldPropFunc = (instance, prop) => {
2184
+ if (typeof prop !== "function")
2185
+ return prop;
2186
+ return prop({
2187
+ field: instance,
2188
+ form: instance.state.form,
2189
+ });
2190
+ };
2191
+ const retrieveFieldPropFunc = (prop) => typeof prop === "function" ? prop : undefined;
2192
+ const propGetter = (instance, prop) => typeof instance[`_${prop}`] === "function"
2193
+ ? instance[`_${prop}`].apply(instance, [
2194
+ {
2195
+ form: instance.state.form,
2196
+ field: instance,
2197
+ },
2198
+ ])
2199
+ : instance[`$${prop}`];
2200
+ const setupFieldProps = (instance, props, data) => Object.assign(instance, {
2201
+ // retrieve functions
2202
+ _label: retrieveFieldPropFunc(props.$label ?? data?.label),
2203
+ _placeholder: retrieveFieldPropFunc(props.$placeholder ?? data?.placeholder),
2204
+ _disabled: retrieveFieldPropFunc(props.$disabled ?? data?.disabled),
2205
+ _rules: retrieveFieldPropFunc(props.$rules ?? data?.rules),
2206
+ _related: retrieveFieldPropFunc(props.$related ?? data?.related),
2207
+ _deleted: retrieveFieldPropFunc(props.$deleted ?? data?.deleted),
2208
+ _validators: retrieveFieldPropFunc(props.$validators ?? data?.validators),
2209
+ _validatedWith: retrieveFieldPropFunc(props.$validatedWith ?? data?.validatedWith),
2210
+ _bindings: retrieveFieldPropFunc(props.$bindings ?? data?.bindings),
2211
+ _extra: retrieveFieldPropFunc(props.$extra ?? data?.extra),
2212
+ _options: retrieveFieldPropFunc(props.$options ?? data?.options),
2213
+ _autoFocus: retrieveFieldPropFunc(props.$autoFocus ?? data?.autoFocus),
2214
+ _inputMode: retrieveFieldPropFunc(props.$inputMode ?? data?.inputMode),
2215
+ // apply functions or value
2216
+ $label: applyFieldPropFunc(instance, props.$label ?? data?.label ?? ""),
2217
+ $placeholder: applyFieldPropFunc(instance, props.$placeholder ?? data?.placeholder ?? ""),
2218
+ $disabled: applyFieldPropFunc(instance, props.$disabled ?? data?.disabled ?? false),
2219
+ $rules: applyFieldPropFunc(instance, props.$rules ?? data?.rules ?? null),
2220
+ $related: applyFieldPropFunc(instance, props.$related ?? data?.related ?? []),
2221
+ $deleted: applyFieldPropFunc(instance, props.$deleted ?? data?.deleted ?? false),
2222
+ $validatedWith: applyFieldPropFunc(instance, props.$validatedWith ?? data?.validatedWith ?? FieldPropsEnum.value),
2223
+ $bindings: applyFieldPropFunc(instance, props.$bindings ?? data?.bindings ?? FieldPropsEnum.default),
2224
+ $extra: applyFieldPropFunc(instance, props.$extra ?? data?.extra ?? null),
2225
+ $options: applyFieldPropFunc(instance, props.$options ?? data?.options ?? {}),
2226
+ $autoFocus: applyFieldPropFunc(instance, props.$autoFocus ?? data?.autoFocus ?? false),
2227
+ $inputMode: applyFieldPropFunc(instance, props.$inputMode ?? data?.inputMode ?? undefined),
2228
+ $validators: applyFieldPropFunc(instance, props.$validators ?? data?.validators ?? null),
2229
+ // other props
2230
+ $hooks: props.$hooks ?? data?.hooks ?? {},
2231
+ $handlers: props.$handlers ?? data?.handlers ?? {},
2232
+ $observers: props.$observers ?? data?.observers ?? null,
2233
+ $interceptors: props.$interceptors ?? data?.interceptors ?? null,
2234
+ $ref: props.$ref ?? data?.ref ?? undefined,
2235
+ $nullable: props.$nullable ?? data?.nullable ?? false,
2236
+ $autoComplete: props.$autoComplete ?? data?.autoComplete ?? undefined,
2237
+ });
2238
+ const setupDefaultProp = (instance, data, props, update, { isEmptyArray, fallbackValueOption, }) => parseInput((val) => val, {
2239
+ isEmptyArray,
2240
+ type: instance.type,
2241
+ unified: update
2242
+ ? defaultValue({
2243
+ fallbackValueOption,
2244
+ type: instance.type,
2245
+ value: instance.value,
2246
+ })
2247
+ : data?.default,
2248
+ separated: props.$default,
2249
+ fallback: instance.$initial,
2250
+ });
2251
+ class Field extends Base {
2252
+ hasInitialNestedFields = false;
2253
+ incremental = false;
2254
+ id;
2255
+ key;
2256
+ name;
2257
+ $observers;
2258
+ $interceptors;
2259
+ $converter = ($) => $;
2260
+ $input = ($) => $;
2261
+ $output = ($) => $;
2262
+ _value;
2263
+ _label;
2264
+ _placeholder;
2265
+ _disabled;
2266
+ _rules;
2267
+ _related;
2268
+ _deleted;
2269
+ _validatedWith;
2270
+ _validators;
2271
+ _bindings;
2272
+ _extra;
2273
+ _options;
2274
+ _autoFocus;
2275
+ _inputMode;
2276
+ $options = undefined;
2277
+ $value = undefined;
2278
+ $type = undefined;
2279
+ $label = undefined;
2280
+ $placeholder = undefined;
2281
+ $default = undefined;
2282
+ $initial = undefined;
2283
+ $bindings = undefined;
2284
+ $extra = undefined;
2285
+ $related = undefined;
2286
+ $validatedWith = undefined;
2287
+ $validators = undefined;
2288
+ $rules = undefined;
2289
+ $disabled = false;
2290
+ $focused = false;
2291
+ $blurred = false;
2292
+ $deleted = false;
2293
+ $autoFocus = false;
2294
+ $inputMode = undefined;
2295
+ $ref = undefined;
2296
+ $nullable = false;
2297
+ $autoComplete = undefined;
2298
+ showError = false;
2299
+ errorSync = null;
2300
+ errorAsync = null;
2301
+ validationErrorStack = [];
2302
+ validationFunctionsData = [];
2303
+ validationAsyncData = { valid: true, message: null };
2304
+ debouncedValidation;
2305
+ disposeValidationOnBlur;
2306
+ disposeValidationOnChange;
2307
+ files = undefined;
2308
+ constructor({ key, path, struct, data = {}, props = {}, update = false, state, }) {
2309
+ super();
2310
+ makeObservable(this, {
2311
+ $options: mobx.observable,
2312
+ $value: mobx.observable,
2313
+ $type: mobx.observable,
2314
+ $label: mobx.observable,
2315
+ $placeholder: mobx.observable,
2316
+ $default: mobx.observable,
2317
+ $initial: mobx.observable,
2318
+ $bindings: mobx.observable,
2319
+ $extra: mobx.observable,
2320
+ $related: mobx.observable,
2321
+ $validatedWith: mobx.observable,
2322
+ $validators: mobx.observable,
2323
+ $rules: mobx.observable,
2324
+ $disabled: mobx.observable,
2325
+ $focused: mobx.observable,
2326
+ $blurred: mobx.observable,
2327
+ $deleted: mobx.observable,
2328
+ showError: mobx.observable,
2329
+ errorSync: mobx.observable,
2330
+ errorAsync: mobx.observable,
2331
+ validationErrorStack: mobx.observable,
2332
+ validationFunctionsData: mobx.observable,
2333
+ validationAsyncData: mobx.observable,
2334
+ files: mobx.observable,
2335
+ autoFocus: mobx.computed,
2336
+ inputMode: mobx.computed,
2337
+ ref: mobx.computed,
2338
+ checkValidationErrors: mobx.computed,
2339
+ checked: mobx.computed,
2340
+ value: mobx.computed,
2341
+ initial: mobx.computed,
2342
+ default: mobx.computed,
2343
+ actionRunning: mobx.computed,
2344
+ type: mobx.computed,
2345
+ label: mobx.computed,
2346
+ placeholder: mobx.computed,
2347
+ extra: mobx.computed,
2348
+ options: mobx.computed,
2349
+ bindings: mobx.computed,
2350
+ related: mobx.computed,
2351
+ disabled: mobx.computed,
2352
+ rules: mobx.computed,
2353
+ validators: mobx.computed,
2354
+ validatedValue: mobx.computed,
2355
+ error: mobx.computed,
2356
+ hasError: mobx.computed,
2357
+ isValid: mobx.computed,
2358
+ isDefault: mobx.computed,
2359
+ isDirty: mobx.computed,
2360
+ isPristine: mobx.computed,
2361
+ isEmpty: mobx.computed,
2362
+ blurred: mobx.computed,
2363
+ touched: mobx.computed,
2364
+ deleted: mobx.computed,
2365
+ setupField: mobx.action,
2366
+ initNestedFields: mobx.action,
2367
+ invalidate: mobx.action,
2368
+ setValidationAsyncData: mobx.action,
2369
+ resetValidation: mobx.action,
2370
+ clear: mobx.action,
2371
+ reset: mobx.action,
2372
+ focus: mobx.action,
2373
+ blur: mobx.action,
2374
+ showErrors: mobx.action,
2375
+ update: mobx.action,
2376
+ });
2377
+ this.state = state;
2378
+ this.setupField(key, path, struct, data, props, update);
2379
+ // this.checkValidationPlugins();
2380
+ this.initNestedFields(data, update);
2381
+ this.incremental = this.hasIncrementalKeys;
2382
+ this.debouncedValidation = lodash.debounce(this.validate, this.state.options.get(OptionsEnum.validationDebounceWait, this), this.state.options.get(OptionsEnum.validationDebounceOptions, this));
2383
+ this.observeValidationOnBlur();
2384
+ this.observeValidationOnChange();
2385
+ this.initMOBXEvent(FieldPropsEnum.observers);
2386
+ this.initMOBXEvent(FieldPropsEnum.interceptors);
2387
+ // setup hooks & handlers from initialization methods
2388
+ mobx.runInAction(() => Object.assign(this.$hooks, this.hooks?.apply(this, [this])));
2389
+ mobx.runInAction(() => Object.assign(this.$handlers, this.handlers?.apply(this, [this])));
2390
+ this.execHook(FieldPropsEnum.onInit);
2391
+ // handle Field onChange Hook
2392
+ mobx.autorun(() => this.changed && this.execHook(FieldPropsEnum.onChange));
2393
+ }
2394
+ /* ------------------------------------------------------------------ */
2395
+ /* COMPUTED */
2396
+ get checkValidationErrors() {
2397
+ return (!this.validationAsyncData.valid ||
2398
+ !lodash.isEmpty(this.validationErrorStack) ||
2399
+ typeof this.errorAsync === 'string' ||
2400
+ typeof this.errorSync === 'string');
2401
+ }
2402
+ set value(newVal) {
2403
+ let val = newVal;
2404
+ if (typeof val === 'string' &&
2405
+ this.state.options.get(OptionsEnum.autoTrimValue, this)) {
2406
+ val = val.trim();
2407
+ }
2408
+ if (this.$value === val)
2409
+ return;
2410
+ if (this.handleSetNumberValue(val))
2411
+ return;
2412
+ this.$value = this.$converter(val);
2413
+ this.$changed++;
2414
+ if (!this.actionRunning) {
2415
+ this.state.form.$changed++;
2416
+ }
2417
+ }
2418
+ handleSetNumberValue(newVal) {
2419
+ if (!this.state.options.get(OptionsEnum.autoParseNumbers, this))
2420
+ return false;
2421
+ if (typeof this.$initial === 'number' || this.type == "number") {
2422
+ if (new RegExp("^-?\\d+(,\\d+)*(\\.\\d+([eE]\\d+)?)?$", "g").exec(newVal)) {
2423
+ this.$value = this.$converter(Number(newVal));
2424
+ this.$changed++;
2425
+ if (!this.actionRunning) {
2426
+ this.state.form.$changed++;
2427
+ }
2428
+ return true;
2429
+ }
2430
+ }
2431
+ }
2432
+ get actionRunning() {
2433
+ return this.submitting || this.clearing || this.resetting;
2434
+ }
2435
+ get checked() {
2436
+ return this.type === "checkbox" ? this.value : undefined;
2437
+ }
2438
+ get value() {
2439
+ return typeof this._value === "function" && !this.hasNestedFields
2440
+ ? propGetter(this, FieldPropsEnum.value)
2441
+ : this.getComputedProp(FieldPropsEnum.value);
2442
+ }
2443
+ get initial() {
2444
+ return this.$initial
2445
+ ? mobx.toJS(this.$initial)
2446
+ : this.getComputedProp(FieldPropsEnum.initial);
2447
+ }
2448
+ get default() {
2449
+ return this.$default
2450
+ ? mobx.toJS(this.$default)
2451
+ : this.getComputedProp(FieldPropsEnum.default);
2452
+ }
2453
+ set initial(val) {
2454
+ this.$initial = val;
2455
+ }
2456
+ set default(val) {
2457
+ this.$default = val;
2458
+ }
2459
+ get nullable() {
2460
+ return propGetter(this, FieldPropsEnum.nullable);
2461
+ }
2462
+ get autoComplete() {
2463
+ return propGetter(this, FieldPropsEnum.autoComplete);
2464
+ }
2465
+ get ref() {
2466
+ return propGetter(this, FieldPropsEnum.ref);
2467
+ }
2468
+ get extra() {
2469
+ return propGetter(this, FieldPropsEnum.extra);
2470
+ }
2471
+ get autoFocus() {
2472
+ return propGetter(this, FieldPropsEnum.autoFocus);
2473
+ }
2474
+ get inputMode() {
2475
+ return propGetter(this, FieldPropsEnum.inputMode);
2476
+ }
2477
+ get type() {
2478
+ return propGetter(this, FieldPropsEnum.type);
2479
+ }
2480
+ get label() {
2481
+ return propGetter(this, FieldPropsEnum.label);
2482
+ }
2483
+ get placeholder() {
2484
+ return propGetter(this, FieldPropsEnum.placeholder);
2485
+ }
2486
+ get options() {
2487
+ return propGetter(this, FieldPropsEnum.options);
2488
+ }
2489
+ get bindings() {
2490
+ return propGetter(this, FieldPropsEnum.bindings);
2491
+ }
2492
+ get related() {
2493
+ return propGetter(this, FieldPropsEnum.related);
2494
+ }
2495
+ get disabled() {
2496
+ return propGetter(this, FieldPropsEnum.disabled);
2497
+ }
2498
+ get rules() {
2499
+ return propGetter(this, FieldPropsEnum.rules);
2500
+ }
2501
+ get validators() {
2502
+ return propGetter(this, FieldPropsEnum.validators);
2503
+ }
2504
+ get validatedWith() {
2505
+ return propGetter(this, FieldPropsEnum.validatedWith);
2506
+ }
2507
+ get validatedValue() {
2508
+ return parseCheckOutput(this, this.validatedWith);
2509
+ }
2510
+ get error() {
2511
+ if (this.showError === false)
2512
+ return null;
2513
+ return this.errorAsync || this.errorSync || this.firstError() || null;
2514
+ }
2515
+ get hasError() {
2516
+ return (this.checkValidationErrors || this.check(FieldPropsEnum.hasError, true));
2517
+ }
2518
+ get isValid() {
2519
+ return (!this.checkValidationErrors && this.check(FieldPropsEnum.isValid, true));
2520
+ }
2521
+ get isDefault() {
2522
+ return !lodash.isNil(this.default) && lodash.isEqual(this.default, this.value);
2523
+ }
2524
+ get isDirty() {
2525
+ const value = this.changed ? this.value : this.initial;
2526
+ return !lodash.isEqual(this.initial, value);
2527
+ }
2528
+ get isPristine() {
2529
+ const value = this.changed ? this.value : this.initial;
2530
+ return lodash.isEqual(this.initial, value);
2531
+ }
2532
+ get isEmpty() {
2533
+ if (this.hasNestedFields)
2534
+ return this.check(FieldPropsEnum.isEmpty, true);
2535
+ if (typeof this.value === 'boolean')
2536
+ return !!this.$value;
2537
+ if (typeof this.value === 'number')
2538
+ return false;
2539
+ if (this.value instanceof Date)
2540
+ return false;
2541
+ if (this.value === null)
2542
+ return false;
2543
+ return lodash.isEmpty(this.value);
2544
+ }
2545
+ get focused() {
2546
+ return this.hasNestedFields
2547
+ ? this.check(FieldPropsEnum.focused, true)
2548
+ : this.$focused;
2549
+ }
2550
+ get blurred() {
2551
+ return this.hasNestedFields
2552
+ ? this.check(FieldPropsEnum.blurred, true)
2553
+ : this.$blurred;
2554
+ }
2555
+ get touched() {
2556
+ return this.hasNestedFields
2557
+ ? this.check(FieldPropsEnum.touched, true)
2558
+ : this.$touched;
2559
+ }
2560
+ get deleted() {
2561
+ return this.hasNestedFields
2562
+ ? this.check(FieldPropsEnum.deleted, true)
2563
+ : this.$deleted;
2564
+ }
2565
+ /* ------------------------------------------------------------------ */
2566
+ /* EVENTS HANDLERS */
2567
+ sync = mobx.action((e, v = null) => {
2568
+ const $get = ($) => isBool($, this.value) ? $.target.checked : $.target.value;
2569
+ // assume "v" or "e" are the values
2570
+ if (lodash.isNil(e) || lodash.isNil(e.target)) {
2571
+ if (!lodash.isNil(v) && !lodash.isNil(v.target)) {
2572
+ v = $get(v); // eslint-disable-line
2573
+ }
2574
+ this.value = $try(e, v);
2575
+ return;
2576
+ }
2577
+ if (!lodash.isNil(e.target)) {
2578
+ this.value = $get(e);
2579
+ return;
2580
+ }
2581
+ this.value = e;
2582
+ });
2583
+ onSync = (...args) => this.type === "file"
2584
+ ? this.onDrop(...args)
2585
+ : this.execHandler(FieldPropsEnum.onChange, args, this.sync, FieldPropsEnum.onSync);
2586
+ onChange = this.onSync;
2587
+ onToggle = (...args) => this.execHandler(FieldPropsEnum.onToggle, args, this.sync);
2588
+ onBlur = (...args) => this.execHandler(FieldPropsEnum.onBlur, args, mobx.action(() => {
2589
+ this.$focused = false;
2590
+ this.$blurred = true;
2591
+ }));
2592
+ onFocus = (...args) => this.execHandler(FieldPropsEnum.onFocus, args, mobx.action(() => {
2593
+ this.$focused = true;
2594
+ this.$touched = true;
2595
+ }));
2596
+ onDrop = (...args) => this.execHandler(FieldPropsEnum.onDrop, args, mobx.action(() => {
2597
+ const e = args[0];
2598
+ let files = null;
2599
+ if (isEvent(e) && hasFiles(e)) {
2600
+ files = Array.from(e.target.files);
2601
+ }
2602
+ const incoming = files || args;
2603
+ const current = this.files || [];
2604
+ // dedupe repeated file drops (fixes .vault/FIXES.md row 28)
2605
+ const seen = new Set(current.map((f) => [f?.name, f?.size, f?.lastModified].join("|")));
2606
+ this.files = [
2607
+ ...current,
2608
+ ...incoming.filter((f) => {
2609
+ if (!f || typeof f.size !== "number")
2610
+ return true;
2611
+ const signature = [f.name, f.size, f.lastModified].join("|");
2612
+ if (seen.has(signature))
2613
+ return false;
2614
+ seen.add(signature);
2615
+ return true;
2616
+ }),
2617
+ ];
2618
+ }));
2619
+ onKeyDown = (...args) => this.execHandler(FieldPropsEnum.onKeyDown, args);
2620
+ onKeyUp = (...args) => this.execHandler(FieldPropsEnum.onKeyUp, args);
2621
+ setupField($key, $path, _$struct, $data, $props, update) {
2622
+ this.key = $key;
2623
+ this.path = $path;
2624
+ this.id = this.state.options.get(OptionsEnum.uniqueId)?.apply(this, [this]);
2625
+ const fallbackValueOption = this.state.options.get(OptionsEnum.fallbackValue, this);
2626
+ const applyInputConverterOnInit = this.state.options.get(OptionsEnum.applyInputConverterOnInit, this);
2627
+ const struct = this.state.struct();
2628
+ const structPath = pathToStruct(this.path ?? "");
2629
+ const isEmptyArray = isArrayFromStruct(struct, structPath);
2630
+ const { $type, $input, $output, $converter, $converters, $computed } = $props;
2631
+ if (lodash.isPlainObject($data)) {
2632
+ const { type, input, output, converter, converters, computed } = $data;
2633
+ this.name = $data.name ?? String($key);
2634
+ this.$type = $type || type || "text";
2635
+ this.$converter = $try($converter, $converters, converter, converters, this.$converter);
2636
+ this.$input = $try($input, input, this.$input);
2637
+ this.$output = $try($output, output, this.$output);
2638
+ const value = parseInput(applyInputConverterOnInit ? this.$input : (val) => val, {
2639
+ fallbackValueOption,
2640
+ isEmptyArray,
2641
+ type: this.type,
2642
+ unified: computed || $data.value,
2643
+ separated: $computed || $props.$value,
2644
+ fallback: $props.$initial,
2645
+ });
2646
+ this._value = retrieveFieldPropFunc(value);
2647
+ this.$value =
2648
+ typeof this._value === "function"
2649
+ ? applyFieldPropFunc(this, value)
2650
+ : value;
2651
+ this.$initial = parseInput((val) => val, {
2652
+ fallbackValueOption,
2653
+ isEmptyArray,
2654
+ type: this.type,
2655
+ unified: $data.initial,
2656
+ separated: $props.$initial,
2657
+ fallback: this.$value,
2658
+ });
2659
+ this.$default = setupDefaultProp(this, $data, $props, update, {
2660
+ fallbackValueOption,
2661
+ isEmptyArray,
2662
+ });
2663
+ setupFieldProps(this, $props, $data);
2664
+ return;
2665
+ }
2666
+ /* The field IS the value here */
2667
+ this.name = String($key);
2668
+ this.$type = $type || "text";
2669
+ this.$converter = $try($converter, $converters, this.$converter);
2670
+ this.$input = $try($input, this.$input);
2671
+ this.$output = $try($output, this.$output);
2672
+ const value = parseInput(applyInputConverterOnInit ? this.$input : (val) => val, {
2673
+ fallbackValueOption,
2674
+ isEmptyArray,
2675
+ type: this.type,
2676
+ unified: $computed || $data,
2677
+ separated: $computed || $props.$value,
2678
+ });
2679
+ this._value = retrieveFieldPropFunc(value);
2680
+ this.$value =
2681
+ typeof this._value === "function"
2682
+ ? applyFieldPropFunc(this, value)
2683
+ : value;
2684
+ this.$initial = parseInput((val) => val, {
2685
+ fallbackValueOption,
2686
+ isEmptyArray,
2687
+ type: this.type,
2688
+ unified: $data,
2689
+ separated: $props.$initial,
2690
+ fallback: this.$value,
2691
+ });
2692
+ this.$default = setupDefaultProp(this, $data, $props, update, {
2693
+ fallbackValueOption,
2694
+ isEmptyArray,
2695
+ });
2696
+ setupFieldProps(this, $props, $data);
2697
+ }
2698
+ getComputedProp(key) {
2699
+ if (this.incremental || this.hasNestedFields) {
2700
+ return key === FieldPropsEnum.value
2701
+ ? this.get(key, false)
2702
+ : mobx.untracked(() => this.get(key, false));
2703
+ }
2704
+ // @ts-ignore
2705
+ const val = this[`$${key}`];
2706
+ if (Array.isArray(val) || mobx.isObservableArray(val)) {
2707
+ return [].slice.call(val);
2708
+ }
2709
+ return mobx.toJS(val);
2710
+ }
2711
+ // checkValidationPlugins(): void {
2712
+ // const { drivers } = this.state.form.validator;
2713
+ // const form = this.state.form.name ? `${this.state.form.name}/` : "";
2714
+ // if (isNil(drivers.dvr) && !isNil(this.rules)) {
2715
+ // throw new Error(
2716
+ // `The DVR validation rules are defined but no DVR plugin provided. Field: "${
2717
+ // form + this.path
2718
+ // }".`
2719
+ // );
2720
+ // }
2721
+ // if (isNil(drivers.vjf) && !isNil(this.validators)) {
2722
+ // throw new Error(
2723
+ // `The VJF validators functions are defined but no VJF plugin provided. Field: "${
2724
+ // form + this.path
2725
+ // }".`
2726
+ // );
2727
+ // }
2728
+ // }
2729
+ initNestedFields(field, update) {
2730
+ const fields = lodash.isNil(field) ? null : field.fields;
2731
+ if (Array.isArray(fields) && !lodash.isEmpty(fields)) {
2732
+ this.hasInitialNestedFields = true;
2733
+ }
2734
+ this.initFields({ fields }, update);
2735
+ if (!update && Array.isArray(fields) && lodash.isEmpty(fields)) {
2736
+ if (Array.isArray(this.value) && !lodash.isEmpty(this.value)) {
2737
+ this.hasInitialNestedFields = true;
2738
+ this.initFields({ fields, values: this.value }, update);
2739
+ }
2740
+ }
2741
+ }
2742
+ invalidate(message, deep = true, async = false) {
2743
+ if (async === true) {
2744
+ this.errorAsync = message;
2745
+ this.showErrors(true, deep);
2746
+ return;
2747
+ }
2748
+ if (Array.isArray(message)) {
2749
+ this.validationErrorStack = message;
2750
+ this.showErrors(true, deep);
2751
+ return;
2752
+ }
2753
+ this.validationErrorStack.unshift(message);
2754
+ this.showErrors(true, deep);
2755
+ }
2756
+ setValidationAsyncData(valid = false, message = null) {
2757
+ this.validationAsyncData = { valid, message };
2758
+ }
2759
+ resetValidation(deep = false) {
2760
+ this.showError = false;
2761
+ this.errorSync = null;
2762
+ this.errorAsync = null;
2763
+ this.validationAsyncData = { valid: true, message: null };
2764
+ this.validationFunctionsData = [];
2765
+ this.validationErrorStack = [];
2766
+ Promise.resolve().then(mobx.action(() => {
2767
+ this.$resetting = false;
2768
+ this.$clearing = false;
2769
+ }));
2770
+ deep && this.each((field) => field.resetValidation(deep));
2771
+ }
2772
+ clear(deep = true, execHook = true) {
2773
+ execHook && this.execHook(FieldPropsEnum.onClear);
2774
+ this.$clearing = true;
2775
+ this.$touched = false;
2776
+ this.$blurred = false;
2777
+ this.$changed = 0;
2778
+ this.files = undefined;
2779
+ this.$value = defaultValue({
2780
+ fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue),
2781
+ value: this.$value,
2782
+ nullable: this.$nullable,
2783
+ type: this.type,
2784
+ });
2785
+ deep && this.each((field) => field.clear(deep));
2786
+ this.state.options.get(OptionsEnum.validateOnClear, this)
2787
+ ? this.validate({
2788
+ showErrors: this.state.options.get(OptionsEnum.showErrorsOnClear, this),
2789
+ })
2790
+ : this.resetValidation(deep);
2791
+ }
2792
+ reset(deep = true, execHook = true) {
2793
+ execHook && this.execHook(FieldPropsEnum.onReset);
2794
+ this.$resetting = true;
2795
+ this.$touched = false;
2796
+ this.$blurred = false;
2797
+ this.$changed = 0;
2798
+ this.files = undefined;
2799
+ const useDefaultValue = this.$default !== this.$initial;
2800
+ if (useDefaultValue)
2801
+ this.value = this.$default;
2802
+ if (!useDefaultValue)
2803
+ this.value = this.$initial;
2804
+ deep && this.each((field) => field.reset(deep));
2805
+ this.state.options.get(OptionsEnum.validateOnReset, this)
2806
+ ? this.validate({
2807
+ showErrors: this.state.options.get(OptionsEnum.showErrorsOnReset, this),
2808
+ })
2809
+ : this.resetValidation(deep);
2810
+ }
2811
+ focus() {
2812
+ if (this.ref && !this.focused)
2813
+ this.ref.focus();
2814
+ this.$focused = true;
2815
+ this.$touched = true;
2816
+ }
2817
+ blur() {
2818
+ if (this.ref && this.focused)
2819
+ this.ref.blur();
2820
+ this.$focused = false;
2821
+ this.$blurred = true;
2822
+ }
2823
+ trim() {
2824
+ if (typeof this.value !== 'string')
2825
+ return;
2826
+ this.$value = this.value.trim();
2827
+ }
2828
+ showErrors(show = true, deep = true) {
2829
+ this.showError = show;
2830
+ this.errorSync = this.validationErrorStack.length ? this.validationErrorStack[0] : null;
2831
+ this.errorAsync = !this.validationAsyncData.valid
2832
+ ? this.validationAsyncData.message
2833
+ : null;
2834
+ deep && this.each((field) => field.showErrors(show, deep));
2835
+ }
2836
+ observeValidationOnBlur() {
2837
+ const opt = this.state.options;
2838
+ if (opt.get(OptionsEnum.validateOnBlur, this)) {
2839
+ this.disposeValidationOnBlur = mobx.observe(this, "$focused", (change) => change.newValue === false &&
2840
+ this.debouncedValidation({
2841
+ showErrors: opt.get(OptionsEnum.showErrorsOnBlur, this),
2842
+ }));
2843
+ }
2844
+ }
2845
+ observeValidationOnChange() {
2846
+ const opt = this.state.options;
2847
+ if (opt.get(OptionsEnum.validateOnChange, this)) {
2848
+ this.disposeValidationOnChange = mobx.observe(this, "$value", () => !this.actionRunning &&
2849
+ this.debouncedValidation({
2850
+ showErrors: opt.get(OptionsEnum.showErrorsOnChange, this),
2851
+ }));
2852
+ }
2853
+ else if (opt.get(OptionsEnum.validateOnChangeAfterInitialBlur, this) ||
2854
+ opt.get(OptionsEnum.validateOnChangeAfterSubmit, this)) {
2855
+ this.disposeValidationOnChange = mobx.observe(this, "$value", () => !this.actionRunning &&
2856
+ ((opt.get(OptionsEnum.validateOnChangeAfterInitialBlur, this) &&
2857
+ this.blurred) ||
2858
+ (opt.get(OptionsEnum.validateOnChangeAfterSubmit, this) &&
2859
+ this.state.form.submitted)) &&
2860
+ this.debouncedValidation({
2861
+ showErrors: opt.get(OptionsEnum.showErrorsOnChange, this),
2862
+ }));
2863
+ }
2864
+ }
2865
+ initMOBXEvent(type) {
2866
+ const arr = this[`$${type}`];
2867
+ if (!Array.isArray(arr))
2868
+ return;
2869
+ let fn;
2870
+ if (type === FieldPropsEnum.observers)
2871
+ fn = this.observe;
2872
+ if (type === FieldPropsEnum.interceptors)
2873
+ fn = this.intercept;
2874
+ arr.map((obj) => fn(lodash.omit(obj, FieldPropsEnum.path)));
2875
+ }
2876
+ bind(props = {}) {
2877
+ return {
2878
+ ...this.state.bindings.load(this, this.bindings, props),
2879
+ ref: ($ref) => (this.$ref = $ref),
2880
+ };
2881
+ }
2882
+ update(fields) {
2883
+ if (!lodash.isPlainObject(fields)) {
2884
+ throw new Error("The update() method accepts only plain objects.");
2885
+ }
2886
+ const fallback = this.state.options.get(OptionsEnum.fallback, this);
2887
+ const applyInputConverterOnUpdate = this.state.options.get(OptionsEnum.applyInputConverterOnUpdate, this);
2888
+ const x = this.state
2889
+ .struct()
2890
+ .findIndex((s) => s.startsWith((this.path ?? "").replace(/\.\d+\./, "[].") + "[]"));
2891
+ if (!fallback && this.fields.size === 0 && x < 0) {
2892
+ this.value = parseInput(applyInputConverterOnUpdate ? this.$input : (val) => val, {
2893
+ fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
2894
+ separated: fields,
2895
+ });
2896
+ return;
2897
+ }
2898
+ super.update(fields);
2899
+ }
2900
+ }
2901
+
2902
+ class Form extends Base {
2903
+ name;
2904
+ path = null;
2905
+ extra = {};
2906
+ validator;
2907
+ debouncedValidation = null;
2908
+ constructor(setup = {}, { name = "", options = {}, plugins = {}, bindings = {}, hooks = {}, handlers = {}, extra = {}, } = {}) {
2909
+ super();
2910
+ makeObservable(this, {
2911
+ extra: mobx.observable,
2912
+ fields: mobx.observable,
2913
+ flatMapValues: mobx.computed,
2914
+ error: mobx.computed,
2915
+ hasError: mobx.computed,
2916
+ isValid: mobx.computed,
2917
+ isPristine: mobx.computed,
2918
+ isDirty: mobx.computed,
2919
+ isDefault: mobx.computed,
2920
+ isEmpty: mobx.computed,
2921
+ focused: mobx.computed,
2922
+ touched: mobx.computed,
2923
+ disabled: mobx.computed,
2924
+ // init: action,
2925
+ invalidate: mobx.action,
2926
+ clear: mobx.action,
2927
+ reset: mobx.action,
2928
+ resetValidation: mobx.action,
2929
+ });
2930
+ this.name = name;
2931
+ this.extra = extra;
2932
+ mobx.runInAction(() => (this.$hooks = hooks));
2933
+ mobx.runInAction(() => (this.$handlers = handlers));
2934
+ // load data from initializers methods
2935
+ const initial = lodash.each({
2936
+ setup,
2937
+ options,
2938
+ plugins,
2939
+ bindings,
2940
+ }, (val, key) => typeof this[key] === "function"
2941
+ ? lodash.merge(val, this[key].apply(this, [this]))
2942
+ : val);
2943
+ // setup hooks & handlers from initialization methods
2944
+ mobx.runInAction(() => Object.assign(this.$hooks, this.hooks?.apply(this, [this])));
2945
+ mobx.runInAction(() => Object.assign(this.$handlers, this.handlers?.apply(this, [this])));
2946
+ this.state = new State({
2947
+ form: this,
2948
+ initial: initial.setup,
2949
+ options: initial.options,
2950
+ bindings: initial.bindings,
2951
+ });
2952
+ this.validator = new Validator({
2953
+ form: this,
2954
+ plugins: initial.plugins,
2955
+ });
2956
+ this.initFields(initial.setup);
2957
+ this.debouncedValidation = lodash.debounce(this.validate, this.state.options.get(OptionsEnum.validationDebounceWait), this.state.options.get(OptionsEnum.validationDebounceOptions));
2958
+ // execute validation on form initialization
2959
+ this.state.options.get(OptionsEnum.validateOnInit) &&
2960
+ this.validator.validate({
2961
+ showErrors: this.state.options.get(OptionsEnum.showErrorsOnInit),
2962
+ });
2963
+ this.execHook(FieldPropsEnum.onInit);
2964
+ // handle Form onChange Hook
2965
+ mobx.autorun(() => this.$changed && this.execHook(FieldPropsEnum.onChange));
2966
+ }
2967
+ /* ------------------------------------------------------------------ */
2968
+ /* COMPUTED */
2969
+ get flatMapValues() {
2970
+ const data = {};
2971
+ this.each(($field) => (data[$field.path] = $field.validatedValue));
2972
+ return data;
2973
+ }
2974
+ get error() {
2975
+ return this.validator.error || this.firstError() || null;
2976
+ }
2977
+ get hasError() {
2978
+ return !!this.validator.error || this.check(FieldPropsEnum.hasError, true);
2979
+ }
2980
+ get isValid() {
2981
+ return !this.validator.error && this.check(FieldPropsEnum.isValid, true);
2982
+ }
2983
+ get isPristine() {
2984
+ return this.check(FieldPropsEnum.isPristine, true);
2985
+ }
2986
+ get isDirty() {
2987
+ return this.check(FieldPropsEnum.isDirty, true);
2988
+ }
2989
+ get isDefault() {
2990
+ return this.check(FieldPropsEnum.isDefault, true);
2991
+ }
2992
+ get isEmpty() {
2993
+ return this.check(FieldPropsEnum.isEmpty, true);
2994
+ }
2995
+ get focused() {
2996
+ return this.check(FieldPropsEnum.focused, true);
2997
+ }
2998
+ get touched() {
2999
+ return this.check(FieldPropsEnum.touched, true);
3000
+ }
3001
+ get disabled() {
3002
+ return this.check(FieldPropsEnum.disabled, true);
3003
+ }
3004
+ makeField(data, FieldClass = Field) {
3005
+ return new FieldClass(data);
3006
+ }
3007
+ /**
3008
+ * Select a field by key with type inference.
3009
+ * Provides transparent autocomplete for both top-level keys (`keyof F`)
3010
+ * AND nested paths (`PathsOf<F>`) without any type annotations needed.
3011
+ *
3012
+ * @example
3013
+ * // Top-level keys — autocomplete from keyof F:
3014
+ * form.$('username'); // returns Field<string>
3015
+ *
3016
+ * @example
3017
+ * // Nested paths — autocomplete from PathsOf<F>:
3018
+ * form.$('club'); // "club"
3019
+ * form.$('club.name'); // "club.name" ← autocomplete after dot!
3020
+ * form.$('members[].firstname'); // "members[].firstname"
3021
+ */
3022
+ $(key) {
3023
+ return super.$(key);
3024
+ }
3025
+ /**
3026
+ * Select a field by path.
3027
+ * For typed autocomplete, use `$()` instead, which is typed with `keyof F`.
3028
+ */
3029
+ select(path, fields = null, isStrict = true) {
3030
+ return super.select(path, fields, isStrict);
3031
+ }
3032
+ values() {
3033
+ return super.values();
3034
+ }
3035
+ /** DEPRECATED
3036
+ Init Form Fields and Nested Fields
3037
+
3038
+ init($fields: any = null): void {
3039
+ _.set(this, "fields", observable.map({}));
3040
+
3041
+ this.state.initial.props.values = $fields; // eslint-disable-line
3042
+ this.state.current.props.values = $fields; // eslint-disable-line
3043
+
3044
+ this.initFields({
3045
+ fields: $fields || this.state.struct(),
3046
+ });
3047
+ }
3048
+ */
3049
+ invalidate(message = null, deep = true) {
3050
+ this.debouncedValidation.cancel();
3051
+ this.validator.error =
3052
+ message ||
3053
+ this.state.options.get(OptionsEnum.defaultGenericError) ||
3054
+ null;
3055
+ deep &&
3056
+ this.each((field) => field.debouncedValidation.cancel());
3057
+ }
3058
+ showErrors(show = true) {
3059
+ this.each((field) => field.showErrors(show));
3060
+ }
3061
+ resetValidation(deep = true) {
3062
+ this.validator.error = null;
3063
+ deep && this.each((field) => field.resetValidation(deep));
3064
+ }
3065
+ /**
3066
+ Clear Form Fields
3067
+ */
3068
+ clear(deep = true, execHook = true) {
3069
+ execHook && this.execHook(FieldPropsEnum.onClear);
3070
+ this.$touched = false;
3071
+ this.$changed = 0;
3072
+ deep && this.each((field) => field.clear(deep));
3073
+ }
3074
+ /**
3075
+ Reset Form Fields
3076
+ */
3077
+ reset(deep = true, execHook = true) {
3078
+ execHook && this.execHook(FieldPropsEnum.onReset);
3079
+ this.$touched = false;
3080
+ this.$changed = 0;
3081
+ deep && this.each((field) => field.reset(deep));
3082
+ }
3083
+ }
3084
+
3085
+ exports.ArrayMap = ArrayMap;
3086
+ exports.Field = Field;
3087
+ exports.Form = Form;
3088
+ exports.default = Form;
3089
+
3090
+ Object.defineProperty(exports, '__esModule', { value: true });
3091
+
3092
+ }));
3093
+ //# sourceMappingURL=MobxFormkit.umd.js.map