adaptform 2.1.0 → 2.2.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.
package/dist/index.cjs CHANGED
@@ -1,13 +1,334 @@
1
1
  'use strict';
2
2
 
3
+ // src/core/state/value.ts
4
+ function copyValue(value, seen = /* @__PURE__ */ new WeakMap()) {
5
+ if (value === null || typeof value !== "object") return value;
6
+ if (seen.has(value)) return seen.get(value);
7
+ const remember = (copy) => {
8
+ seen.set(value, copy);
9
+ return copy;
10
+ };
11
+ if (value instanceof Date) return remember(new Date(value.getTime()));
12
+ if (value instanceof RegExp) return remember(new RegExp(value.source, value.flags));
13
+ if (value instanceof ArrayBuffer) return remember(value.slice(0));
14
+ if (ArrayBuffer.isView(value)) {
15
+ const bytes = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);
16
+ return remember(value instanceof DataView ? new DataView(bytes) : new value.constructor(bytes));
17
+ }
18
+ if (value instanceof Map) {
19
+ const result = /* @__PURE__ */ new Map();
20
+ seen.set(value, result);
21
+ for (const [key, item] of value) result.set(copyValue(key, seen), copyValue(item, seen));
22
+ return result;
23
+ }
24
+ if (value instanceof Set) {
25
+ const result = /* @__PURE__ */ new Set();
26
+ seen.set(value, result);
27
+ for (const item of value) result.add(copyValue(item, seen));
28
+ return result;
29
+ }
30
+ if (Array.isArray(value) || Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null) {
31
+ const result = Array.isArray(value) ? new Array(value.length) : Object.create(Object.getPrototypeOf(value));
32
+ seen.set(value, result);
33
+ for (const key of Object.keys(value)) Object.defineProperty(result, key, {
34
+ value: copyValue(value[key], seen),
35
+ enumerable: true,
36
+ writable: true,
37
+ configurable: true
38
+ });
39
+ return result;
40
+ }
41
+ return value;
42
+ }
43
+ function equalValue(a, b, seen = /* @__PURE__ */ new WeakMap()) {
44
+ if (Object.is(a, b)) return true;
45
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
46
+ if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false;
47
+ if (seen.get(a)?.has(b)) return true;
48
+ const matches = seen.get(a) ?? /* @__PURE__ */ new WeakSet();
49
+ matches.add(b);
50
+ seen.set(a, matches);
51
+ if (a instanceof Date && b instanceof Date) return Object.is(a.getTime(), b.getTime());
52
+ if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
53
+ if (a instanceof ArrayBuffer && b instanceof ArrayBuffer) return equalValue(new Uint8Array(a), new Uint8Array(b), seen);
54
+ if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
55
+ const av = new Uint8Array(a.buffer, a.byteOffset, a.byteLength);
56
+ const bv = new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
57
+ return av.length === bv.length && av.every((byte, i) => byte === bv[i]);
58
+ }
59
+ if (a instanceof Map && b instanceof Map) return equalValue([...a], [...b], seen);
60
+ if (a instanceof Set && b instanceof Set) return equalValue([...a], [...b], seen);
61
+ if ("isLuxonDateTime" in a && a.isLuxonDateTime === true && "equals" in a && typeof a.equals === "function") {
62
+ return a.equals(b);
63
+ }
64
+ if (!Array.isArray(a) && Object.getPrototypeOf(a) !== Object.prototype && Object.getPrototypeOf(a) !== null) return false;
65
+ if (Array.isArray(a) && Array.isArray(b) && a.length !== b.length) return false;
66
+ const keys = Object.keys(a);
67
+ return keys.length === Object.keys(b).length && keys.every((key) => Object.prototype.hasOwnProperty.call(b, key) && equalValue(a[key], b[key], seen));
68
+ }
69
+
70
+ // src/core/state/snapshot.ts
71
+ function snapshotValue(value, seen = /* @__PURE__ */ new WeakMap()) {
72
+ if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return value;
73
+ if (typeof value !== "object") return Object.freeze({ kind: "Opaque", type: typeof value });
74
+ const previous = seen.get(value);
75
+ if (previous) return previous;
76
+ if (value instanceof Date) return Object.freeze({ kind: "Date", timestamp: value.getTime() });
77
+ if (value instanceof RegExp) return Object.freeze({ kind: "RegExp", source: value.source, flags: value.flags });
78
+ if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
79
+ const bytes = value instanceof ArrayBuffer ? new Uint8Array(value) : new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
80
+ return Object.freeze({ kind: value.constructor.name, bytes: Object.freeze([...bytes]) });
81
+ }
82
+ if ("isLuxonDateTime" in value && value.isLuxonDateTime === true && "toISO" in value && typeof value.toISO === "function") {
83
+ return Object.freeze({ kind: "DateTime", iso: value.toISO() });
84
+ }
85
+ if (value instanceof Map || value instanceof Set) {
86
+ const result = { kind: value instanceof Map ? "Map" : "Set" };
87
+ seen.set(value, result);
88
+ result.entries = snapshotValue([...value], seen);
89
+ return Object.freeze(result);
90
+ }
91
+ if (Array.isArray(value)) {
92
+ const result = [];
93
+ seen.set(value, result);
94
+ for (const item of value) result.push(snapshotValue(item, seen));
95
+ return Object.freeze(result);
96
+ }
97
+ if (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null) {
98
+ const result = /* @__PURE__ */ Object.create(null);
99
+ seen.set(value, result);
100
+ for (const [key, item] of Object.entries(value)) result[key] = snapshotValue(item, seen);
101
+ return Object.freeze(result);
102
+ }
103
+ return Object.freeze({ kind: "Opaque", type: value.constructor?.name ?? "object" });
104
+ }
105
+ function freezeSnapshot(value, seen = /* @__PURE__ */ new WeakSet()) {
106
+ if (value === null || typeof value !== "object" || seen.has(value)) return value;
107
+ seen.add(value);
108
+ for (const item of Object.values(value)) freezeSnapshot(item, seen);
109
+ return Object.freeze(value);
110
+ }
111
+
112
+ // src/core/state/ObservableNode.ts
113
+ var mutationDepth = 0;
114
+ var flushing = false;
115
+ var publishing = false;
116
+ var batchDepth = 0;
117
+ var validations = /* @__PURE__ */ new Map();
118
+ var batchRoots = /* @__PURE__ */ new Map();
119
+ var pending = /* @__PURE__ */ new Set();
120
+ function flush() {
121
+ if (mutationDepth || flushing) return;
122
+ flushing = true;
123
+ let failure;
124
+ let failed = false;
125
+ try {
126
+ while (pending.size) {
127
+ const stores = [...pending];
128
+ const before = stores.map((store) => store.committed());
129
+ pending.clear();
130
+ for (const store of stores) store.refresh();
131
+ const changed = stores.filter((store, index) => !equalValue(before[index], store.committed()));
132
+ publishing = true;
133
+ try {
134
+ for (const store of changed) {
135
+ try {
136
+ store.notify();
137
+ } catch (error) {
138
+ if (!failed) {
139
+ failure = error;
140
+ failed = true;
141
+ }
142
+ }
143
+ }
144
+ } finally {
145
+ publishing = false;
146
+ }
147
+ }
148
+ } finally {
149
+ flushing = false;
150
+ }
151
+ if (failed) throw failure;
152
+ }
153
+ var SnapshotStore = class {
154
+ constructor(capture, getChildren) {
155
+ this.capture = capture;
156
+ this.getChildren = getChildren;
157
+ this.initialized = false;
158
+ this.listeners = /* @__PURE__ */ new Set();
159
+ this.parents = /* @__PURE__ */ new Set();
160
+ this.children = /* @__PURE__ */ new Set();
161
+ }
162
+ reconcile(seen = /* @__PURE__ */ new Set()) {
163
+ if (seen.has(this)) return;
164
+ seen.add(this);
165
+ const next = new Set(this.listeners.size || this.parents.size ? this.getChildren() : []);
166
+ for (const child of this.children) {
167
+ if (!next.has(child)) {
168
+ child.parents.delete(this);
169
+ child.reconcile(seen);
170
+ }
171
+ }
172
+ const previous = this.children;
173
+ this.children = next;
174
+ for (const child of next) {
175
+ if (!previous.has(child)) {
176
+ child.parents.add(this);
177
+ child.reconcile(seen);
178
+ }
179
+ }
180
+ }
181
+ read() {
182
+ if (!mutationDepth && !publishing) this.refresh();
183
+ else if (!this.initialized) this.refresh();
184
+ return this.snapshot;
185
+ }
186
+ committed() {
187
+ return this.snapshot;
188
+ }
189
+ refresh() {
190
+ this.reconcile();
191
+ const next = freezeSnapshot(this.capture());
192
+ if (this.initialized && equalValue(this.snapshot, next)) return false;
193
+ this.snapshot = next;
194
+ this.initialized = true;
195
+ return true;
196
+ }
197
+ subscribe(listener) {
198
+ this.read();
199
+ const registration = () => listener();
200
+ this.listeners.add(registration);
201
+ this.reconcile();
202
+ return () => {
203
+ this.listeners.delete(registration);
204
+ this.reconcile();
205
+ };
206
+ }
207
+ changed(seen = /* @__PURE__ */ new Set()) {
208
+ if (seen.has(this)) return;
209
+ seen.add(this);
210
+ this.reconcile();
211
+ if (this.listeners.size || this.parents.size || this.initialized) pending.add(this);
212
+ for (const parent of this.parents) parent.changed(seen);
213
+ }
214
+ notify() {
215
+ let failure;
216
+ let failed = false;
217
+ for (const listener of [...this.listeners]) {
218
+ if (!this.listeners.has(listener)) continue;
219
+ try {
220
+ listener();
221
+ } catch (error) {
222
+ if (!failed) {
223
+ failure = error;
224
+ failed = true;
225
+ }
226
+ }
227
+ }
228
+ if (failed) throw failure;
229
+ }
230
+ };
231
+ var ObservableNode = class {
232
+ constructor() {
233
+ this._stateStore = new SnapshotStore(
234
+ () => this.captureState(),
235
+ () => this.stateChildren().map((child) => child._stateStore)
236
+ );
237
+ }
238
+ stateChildren() {
239
+ return [];
240
+ }
241
+ contains(node, seen = /* @__PURE__ */ new Set()) {
242
+ if (this === node) return true;
243
+ if (seen.has(this)) return false;
244
+ seen.add(this);
245
+ return this.stateChildren().some((child) => child.contains(node, seen));
246
+ }
247
+ validateAfterMutation(callback) {
248
+ if (batchDepth) validations.set(this, callback);
249
+ else callback();
250
+ }
251
+ batchUpdate(callback, validate) {
252
+ this.getSnapshot();
253
+ return this.update(() => {
254
+ batchDepth++;
255
+ batchRoots.set(this, validate);
256
+ let failed = false;
257
+ let failure;
258
+ let result;
259
+ try {
260
+ result = callback();
261
+ if (result !== null && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") {
262
+ throw new TypeError("batch callbacks must be synchronous");
263
+ }
264
+ } catch (error) {
265
+ failed = true;
266
+ failure = error;
267
+ } finally {
268
+ batchDepth--;
269
+ }
270
+ if (!batchDepth) {
271
+ const requested = [...validations];
272
+ const roots = [...batchRoots];
273
+ validations.clear();
274
+ batchRoots.clear();
275
+ const selected = roots.filter(([root]) => requested.some(([node]) => root.contains(node))).filter(([root], index, all) => !all.some(([other], otherIndex) => other !== root && other.contains(root) && (!root.contains(other) || otherIndex < index)));
276
+ const checks = [
277
+ ...selected.map(([, check]) => check),
278
+ ...requested.filter(([node]) => !selected.some(([root]) => root.contains(node))).map(([, check]) => check)
279
+ ];
280
+ for (const check of checks) {
281
+ try {
282
+ check();
283
+ } catch (error) {
284
+ if (!failed) {
285
+ failed = true;
286
+ failure = error;
287
+ }
288
+ }
289
+ }
290
+ }
291
+ if (failed) throw failure;
292
+ return result;
293
+ });
294
+ }
295
+ subscribe(listener) {
296
+ return this._stateStore.subscribe(listener);
297
+ }
298
+ getSnapshot() {
299
+ return this._stateStore.read();
300
+ }
301
+ update(callback) {
302
+ mutationDepth++;
303
+ let failed = false;
304
+ try {
305
+ return callback();
306
+ } catch (error) {
307
+ failed = true;
308
+ throw error;
309
+ } finally {
310
+ this._stateStore.changed();
311
+ mutationDepth--;
312
+ if (failed) {
313
+ try {
314
+ flush();
315
+ } catch {
316
+ }
317
+ } else flush();
318
+ }
319
+ }
320
+ };
321
+
3
322
  // src/core/fields/Field.ts
4
- var Field = class {
323
+ var Field = class extends ObservableNode {
5
324
  constructor(TypeConstructor, defaultValue, options) {
325
+ super();
6
326
  this._rawValue = null;
7
327
  this._valueClear = null;
328
+ this._baseline = null;
8
329
  this._errors = [];
9
- this.isValid = null;
10
- this.isTouched = false;
330
+ this._isValid = null;
331
+ this._isTouched = false;
11
332
  this.fieldType = new TypeConstructor(options ?? {});
12
333
  this.defaultValue = defaultValue ?? null;
13
334
  for (const plugin of this.options.plugins ?? []) {
@@ -21,6 +342,33 @@ var Field = class {
21
342
  this.isValid = null;
22
343
  }
23
344
  this.isTouched = false;
345
+ this.commitBaseline();
346
+ }
347
+ get isValid() {
348
+ return this._isValid;
349
+ }
350
+ set isValid(value) {
351
+ this.update(() => {
352
+ this._isValid = value;
353
+ });
354
+ }
355
+ get isTouched() {
356
+ return this._isTouched;
357
+ }
358
+ set isTouched(value) {
359
+ this.update(() => {
360
+ this._isTouched = value;
361
+ });
362
+ }
363
+ captureState() {
364
+ return {
365
+ rawValue: snapshotValue(this._rawValue),
366
+ valueClear: snapshotValue(this._valueClear),
367
+ errors: [...this._errors],
368
+ isValid: this.isValid,
369
+ isTouched: this.isTouched,
370
+ isDirty: this.isDirty
371
+ };
24
372
  }
25
373
  // ========== Getters and setters ==========
26
374
  get plugins() {
@@ -32,8 +380,10 @@ var Field = class {
32
380
  return this.fieldType.options;
33
381
  }
34
382
  set options(options) {
35
- const currentOptions = this.fieldType.options;
36
- this.fieldType.options = Object.assign(currentOptions, options);
383
+ this.update(() => {
384
+ const currentOptions = this.fieldType.options;
385
+ this.fieldType.options = Object.assign(currentOptions, options);
386
+ });
37
387
  }
38
388
  get rawValue() {
39
389
  return this._rawValue;
@@ -42,14 +392,16 @@ var Field = class {
42
392
  this.setRawValue(input);
43
393
  }
44
394
  setRawValue(input, validate = true) {
45
- this.assignRawValue(input);
46
- this._errors = [];
47
- this.isTouched = true;
48
- if (validate) {
49
- this.checkAndSetValid();
50
- } else {
51
- this.isValid = null;
52
- }
395
+ return this.update(() => {
396
+ this.assignRawValue(input);
397
+ this._errors = [];
398
+ this.isTouched = true;
399
+ if (validate) {
400
+ this.validateAfterMutation(() => this.checkAndSetValid());
401
+ } else {
402
+ this.isValid = null;
403
+ }
404
+ });
53
405
  }
54
406
  assignRawValue(input) {
55
407
  let rawValue = input;
@@ -74,16 +426,26 @@ var Field = class {
74
426
  return this._errors[0] ?? "";
75
427
  }
76
428
  set error(message) {
77
- if (message) {
78
- this._errors = [message];
79
- } else {
80
- this._errors = [];
81
- }
82
- this.isValid = message ? false : null;
429
+ this.update(() => {
430
+ if (message) {
431
+ this._errors = [message];
432
+ } else {
433
+ this._errors = [];
434
+ }
435
+ this.isValid = message ? false : null;
436
+ });
83
437
  }
84
438
  get valueClear() {
85
439
  return this._valueClear;
86
440
  }
441
+ get isDirty() {
442
+ return !equalValue(this._valueClear, this._baseline);
443
+ }
444
+ commitBaseline() {
445
+ return this.update(() => {
446
+ this._baseline = copyValue(this._valueClear);
447
+ });
448
+ }
87
449
  // ========== Validation ==========
88
450
  isRequired(form) {
89
451
  let isRequired;
@@ -95,41 +457,45 @@ var Field = class {
95
457
  return isRequired;
96
458
  }
97
459
  checkValid(form) {
98
- this._errors = [];
99
- if (this.isEmpty) {
100
- if (this.isRequired(form)) {
101
- this._errors.push(this.options.messages?.isRequired ?? "\u041F\u043E\u043B\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E \u0434\u043B\u044F \u0437\u0430\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F");
102
- return false;
460
+ return this.update(() => {
461
+ this._errors = [];
462
+ if (this.isEmpty) {
463
+ if (this.isRequired(form)) {
464
+ this._errors.push(this.options.messages?.isRequired ?? "\u041F\u043E\u043B\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E \u0434\u043B\u044F \u0437\u0430\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F");
465
+ return false;
466
+ }
467
+ return true;
103
468
  }
104
- return true;
105
- }
106
- if (this._valueClear === null) {
107
- this._errors.push(
108
- this.options.messages?.type ?? `\u041E\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044F ${this.fieldType.getTypeName()}`
109
- );
110
- return false;
111
- }
112
- const typeErrors = this.fieldType.validate(this._valueClear, form);
113
- if (typeErrors.length > 0) {
114
- this._errors.push(...typeErrors);
115
- return false;
116
- }
117
- if (this.options.validate) {
118
- const result = this.options.validate(this._valueClear, form);
119
- if (result === false) {
120
- this._errors.push(this.options.messages?.validate ?? "\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043D\u0435 \u043F\u0440\u043E\u0448\u043B\u043E \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u044E");
469
+ if (this._valueClear === null) {
470
+ this._errors.push(
471
+ this.options.messages?.type ?? `\u041E\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044F ${this.fieldType.getTypeName()}`
472
+ );
121
473
  return false;
122
474
  }
123
- if (typeof result === "string") {
124
- this._errors.push(result);
475
+ const typeErrors = this.fieldType.validate(this._valueClear, form);
476
+ if (typeErrors.length > 0) {
477
+ this._errors.push(...typeErrors);
125
478
  return false;
126
479
  }
127
- }
128
- return true;
480
+ if (this.options.validate) {
481
+ const result = this.options.validate(this._valueClear, form);
482
+ if (result === false) {
483
+ this._errors.push(this.options.messages?.validate ?? "\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043D\u0435 \u043F\u0440\u043E\u0448\u043B\u043E \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u044E");
484
+ return false;
485
+ }
486
+ if (typeof result === "string") {
487
+ this._errors.push(result);
488
+ return false;
489
+ }
490
+ }
491
+ return true;
492
+ });
129
493
  }
130
494
  checkAndSetValid(form) {
131
- this.isValid = this.checkValid(form);
132
- return this.isValid;
495
+ return this.update(() => {
496
+ this.isValid = this.checkValid(form);
497
+ return this.isValid;
498
+ });
133
499
  }
134
500
  get isEmpty() {
135
501
  let isEmpty = false;
@@ -140,15 +506,17 @@ var Field = class {
140
506
  }
141
507
  // ========== Helper methods ==========
142
508
  reset() {
143
- if (this.defaultValue !== null && this.defaultValue !== void 0) {
144
- this.assignRawValue(this.defaultValue);
145
- } else {
146
- this._rawValue = null;
147
- this._valueClear = null;
148
- }
149
- this._errors = [];
150
- this.isValid = null;
151
- this.isTouched = false;
509
+ return this.update(() => {
510
+ if (this.defaultValue !== null && this.defaultValue !== void 0) {
511
+ this.assignRawValue(this.defaultValue);
512
+ } else {
513
+ this._rawValue = null;
514
+ this._valueClear = null;
515
+ }
516
+ this._errors = [];
517
+ this.isValid = null;
518
+ this.isTouched = false;
519
+ });
152
520
  }
153
521
  };
154
522
 
@@ -158,28 +526,67 @@ function isValidArrayIndex(index, length) {
158
526
  }
159
527
 
160
528
  // src/core/fields/ArrayField.ts
161
- var ArrayField = class {
529
+ var ArrayField = class extends ObservableNode {
162
530
  constructor(factory, options = {}, initial = []) {
531
+ super();
163
532
  this.factory = factory;
164
533
  this._items = [];
165
534
  this._errors = [];
535
+ this._baseline = [];
166
536
  this._hasValidationResult = false;
167
- this.isTouched = false;
537
+ this._isTouched = false;
168
538
  this.options = {
169
539
  isRequired: true,
170
540
  messages: {},
171
541
  ...options
172
542
  };
173
543
  this._items = initial.map((value) => this.factory(value));
174
- this.checkValid();
544
+ this.validateAfterMutation(() => this.checkValid());
545
+ this.commitBaseline();
546
+ }
547
+ captureState() {
548
+ return {
549
+ itemsValue: snapshotValue(this.itemsValue),
550
+ items: this._items.map((item) => item.getSnapshot()),
551
+ errors: [...this._errors],
552
+ isValid: this.isValid,
553
+ isTouched: this.isTouched,
554
+ isDirty: this.isDirty
555
+ };
556
+ }
557
+ stateChildren() {
558
+ return this._items;
559
+ }
560
+ get isTouched() {
561
+ return this._isTouched;
562
+ }
563
+ set isTouched(value) {
564
+ this.update(() => {
565
+ this._isTouched = value;
566
+ });
567
+ }
568
+ get isDirty() {
569
+ return !equalValue(this.itemsValue, this._baseline) || this._items.some((child) => child.isDirty);
570
+ }
571
+ commitBaseline() {
572
+ return this.update(() => {
573
+ for (const child of this._items) child.commitBaseline();
574
+ this._baseline = copyValue(this.itemsValue);
575
+ });
175
576
  }
176
577
  // ===== value =====
177
578
  set itemsValue(items) {
178
- this.clear();
179
- for (const item of items) {
180
- this.add(item, false);
181
- }
182
- this.checkValid();
579
+ this.setItemsValue(items);
580
+ }
581
+ setItemsValue(items, validate = true) {
582
+ return this.update(() => {
583
+ this._items = [];
584
+ this.error = null;
585
+ for (const item of items) {
586
+ this.add(item, false);
587
+ }
588
+ if (validate) this.validateAfterMutation(() => this.checkValid());
589
+ });
183
590
  }
184
591
  get itemsValue() {
185
592
  return this._items.map((item) => item.valueClear);
@@ -189,20 +596,26 @@ var ArrayField = class {
189
596
  }
190
597
  // ===== actions =====
191
598
  add(value, force_check = true) {
192
- const field = this.factory(value);
193
- this.isTouched = true;
194
- this._items.push(field);
195
- if (force_check) this.checkValid();
196
- return field;
599
+ return this.update(() => {
600
+ const field = this.factory(value);
601
+ this.isTouched = true;
602
+ this._items.push(field);
603
+ if (force_check) this.validateAfterMutation(() => this.checkValid());
604
+ return field;
605
+ });
197
606
  }
198
607
  remove(index) {
199
- if (!isValidArrayIndex(index, this._items.length)) return;
200
- this._items.splice(index, 1);
201
- this.checkValid();
608
+ return this.update(() => {
609
+ if (!isValidArrayIndex(index, this._items.length)) return;
610
+ this._items.splice(index, 1);
611
+ this.validateAfterMutation(() => this.checkValid());
612
+ });
202
613
  }
203
614
  clear() {
204
- this._items = [];
205
- this.checkValid();
615
+ return this.update(() => {
616
+ this._items = [];
617
+ this.validateAfterMutation(() => this.checkValid());
618
+ });
206
619
  }
207
620
  // ===== validation =====
208
621
  isRequired(form) {
@@ -215,46 +628,48 @@ var ArrayField = class {
215
628
  return isRequired;
216
629
  }
217
630
  checkValid(form) {
218
- this._hasValidationResult = true;
219
- this._errors = [];
220
- if (this.isRequired(form) && this._items.length === 0) {
221
- this._errors.push(
222
- this.options.messages?.isRequired ?? "\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D \u044D\u043B\u0435\u043C\u0435\u043D\u0442"
223
- );
224
- return false;
225
- }
226
- if (this.options.minItems != null && this._items.length < this.options.minItems) {
227
- this._errors.push(
228
- this.options.messages?.minItems ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 ${this.options.minItems}`
229
- );
230
- return false;
231
- }
232
- if (this.options.maxItems != null && this._items.length > this.options.maxItems) {
233
- this._errors.push(
234
- this.options.messages?.maxItems ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${this.options.maxItems}`
235
- );
236
- return false;
237
- }
238
- let valid = true;
239
- for (const field of this._items) {
240
- const ok = field.checkAndSetValid(form);
241
- if (!ok) valid = false;
242
- }
243
- if (this.options.validate) {
244
- const values = this._items.map((item) => item.valueClear);
245
- const result = this.options.validate(values, form);
246
- if (result === false) {
631
+ return this.update(() => {
632
+ this._hasValidationResult = true;
633
+ this._errors = [];
634
+ if (this.isRequired(form) && this._items.length === 0) {
247
635
  this._errors.push(
248
- this.options.messages?.validate ?? "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0438"
636
+ this.options.messages?.isRequired ?? "\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D \u044D\u043B\u0435\u043C\u0435\u043D\u0442"
249
637
  );
250
638
  return false;
251
639
  }
252
- if (typeof result === "string") {
253
- this._errors.push(result);
640
+ if (this.options.minItems != null && this._items.length < this.options.minItems) {
641
+ this._errors.push(
642
+ this.options.messages?.minItems ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 ${this.options.minItems}`
643
+ );
254
644
  return false;
255
645
  }
256
- }
257
- return valid && this._errors.length === 0;
646
+ if (this.options.maxItems != null && this._items.length > this.options.maxItems) {
647
+ this._errors.push(
648
+ this.options.messages?.maxItems ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${this.options.maxItems}`
649
+ );
650
+ return false;
651
+ }
652
+ let valid = true;
653
+ for (const field of this._items) {
654
+ const ok = field.checkAndSetValid(form);
655
+ if (!ok) valid = false;
656
+ }
657
+ if (this.options.validate) {
658
+ const values = this._items.map((item) => item.valueClear);
659
+ const result = this.options.validate(values, form);
660
+ if (result === false) {
661
+ this._errors.push(
662
+ this.options.messages?.validate ?? "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0438"
663
+ );
664
+ return false;
665
+ }
666
+ if (typeof result === "string") {
667
+ this._errors.push(result);
668
+ return false;
669
+ }
670
+ }
671
+ return valid && this._errors.length === 0;
672
+ });
258
673
  }
259
674
  checkAndSetValid(form) {
260
675
  return this.checkValid(form);
@@ -268,51 +683,90 @@ var ArrayField = class {
268
683
  return this._errors[0] ?? "";
269
684
  }
270
685
  set error(message) {
271
- if (message) {
272
- this._errors = [message];
273
- this._hasValidationResult = true;
274
- } else {
275
- this._errors = [];
276
- this._hasValidationResult = false;
277
- }
686
+ this.update(() => {
687
+ if (message) {
688
+ this._errors = [message];
689
+ this._hasValidationResult = true;
690
+ } else {
691
+ this._errors = [];
692
+ this._hasValidationResult = false;
693
+ }
694
+ });
278
695
  }
279
696
  get errors() {
280
697
  return this._errors;
281
698
  }
282
699
  reset() {
283
- this._items.forEach((item) => item.reset());
284
- this._errors = [];
285
- this._hasValidationResult = false;
286
- this.isTouched = false;
700
+ return this.update(() => {
701
+ this._items.forEach((item) => item.reset());
702
+ this._errors = [];
703
+ this._hasValidationResult = false;
704
+ this.isTouched = false;
705
+ });
287
706
  }
288
707
  };
289
708
 
290
709
  // src/core/fields/ArrayFormField.ts
291
- var ArrayFormField = class {
710
+ var ArrayFormField = class extends ObservableNode {
292
711
  constructor(FormConstructor, options = {}, initial = []) {
712
+ super();
293
713
  this.FormConstructor = FormConstructor;
294
714
  this.options = options;
295
715
  this._forms = [];
296
716
  this._errors = [];
717
+ this._baseline = [];
297
718
  this._hasValidationResult = false;
298
- this.isTouched = false;
719
+ this._isTouched = false;
299
720
  this._forms = initial.map((data) => {
300
721
  const form = new this.FormConstructor();
301
722
  form.setFields(data, false);
302
723
  return form;
303
724
  });
304
- this.checkValid();
725
+ this.validateAfterMutation(() => this.checkValid());
726
+ this.commitBaseline();
727
+ }
728
+ captureState() {
729
+ return {
730
+ formsFieldsValue: snapshotValue(this.formsFieldsValue),
731
+ forms: this._forms.map((form) => form.getSnapshot()),
732
+ errors: [...this._errors],
733
+ isValid: this.isValid,
734
+ isTouched: this.isTouched,
735
+ isDirty: this.isDirty
736
+ };
737
+ }
738
+ stateChildren() {
739
+ return this._forms;
740
+ }
741
+ get isTouched() {
742
+ return this._isTouched;
743
+ }
744
+ set isTouched(value) {
745
+ this.update(() => {
746
+ this._isTouched = value;
747
+ });
748
+ }
749
+ get isDirty() {
750
+ return !equalValue(this.formsFieldsValue, this._baseline) || this._forms.some((child) => child.isDirty);
751
+ }
752
+ commitBaseline() {
753
+ return this.update(() => {
754
+ for (const child of this._forms) child.commitBaseline();
755
+ this._baseline = copyValue(this.formsFieldsValue);
756
+ });
305
757
  }
306
758
  // ===== value =====
307
759
  set forms(forms) {
308
760
  this.setForms(forms);
309
761
  }
310
762
  setForms(forms, validate = true) {
311
- this._forms = [];
312
- for (const formData of forms) {
313
- this.add(formData, false);
314
- }
315
- if (validate) this.checkValid();
763
+ return this.update(() => {
764
+ this._forms = [];
765
+ for (const formData of forms) {
766
+ this.add(formData, false);
767
+ }
768
+ if (validate) this.validateAfterMutation(() => this.checkValid());
769
+ });
316
770
  }
317
771
  get forms() {
318
772
  return this._forms;
@@ -322,29 +776,38 @@ var ArrayFormField = class {
322
776
  }
323
777
  // ===== actions =====
324
778
  add(data, force_check = true) {
325
- const form = new this.FormConstructor();
326
- if (data !== void 0 && data !== null) {
327
- form.setFields(data, false);
328
- }
329
- this.isTouched = true;
330
- this._forms.push(form);
331
- if (force_check) this.checkValid();
332
- return form;
779
+ return this.update(() => {
780
+ const form = new this.FormConstructor();
781
+ if (data !== void 0 && data !== null) {
782
+ form.setFields(data, false);
783
+ }
784
+ form.commitBaseline();
785
+ this.isTouched = true;
786
+ this._forms.push(form);
787
+ if (force_check) this.validateAfterMutation(() => this.checkValid());
788
+ return form;
789
+ });
333
790
  }
334
791
  remove(index) {
335
- if (!isValidArrayIndex(index, this._forms.length)) return;
336
- this._forms.splice(index, 1);
337
- this.checkValid();
792
+ return this.update(() => {
793
+ if (!isValidArrayIndex(index, this._forms.length)) return;
794
+ this._forms.splice(index, 1);
795
+ this.validateAfterMutation(() => this.checkValid());
796
+ });
338
797
  }
339
798
  clear() {
340
- this._forms = [];
341
- this.checkValid();
799
+ return this.update(() => {
800
+ this._forms = [];
801
+ this.validateAfterMutation(() => this.checkValid());
802
+ });
342
803
  }
343
804
  reset() {
344
- this._forms.forEach((form) => form.reset());
345
- this._errors = [];
346
- this._hasValidationResult = false;
347
- this.isTouched = false;
805
+ return this.update(() => {
806
+ this._forms.forEach((form) => form.reset());
807
+ this._errors = [];
808
+ this._hasValidationResult = false;
809
+ this.isTouched = false;
810
+ });
348
811
  }
349
812
  // ===== validation =====
350
813
  isRequired(form) {
@@ -357,45 +820,47 @@ var ArrayFormField = class {
357
820
  return isRequired;
358
821
  }
359
822
  checkValid(form) {
360
- this._hasValidationResult = true;
361
- this._errors = [];
362
- if (this.isRequired(form) && this._forms.length === 0) {
363
- this._errors.push(
364
- this.options.messages?.isRequired ?? "\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D \u044D\u043B\u0435\u043C\u0435\u043D\u0442"
365
- );
366
- return false;
367
- }
368
- if (this.options.minForms != null && this._forms.length < this.options.minForms) {
369
- this._errors.push(
370
- this.options.messages?.minForms ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 ${this.options.minForms}`
371
- );
372
- return false;
373
- }
374
- if (this.options.maxForms != null && this._forms.length > this.options.maxForms) {
375
- this._errors.push(
376
- this.options.messages?.maxForms ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${this.options.maxForms}`
377
- );
378
- return false;
379
- }
380
- let valid = true;
381
- for (const nestedForm of this._forms) {
382
- const ok = nestedForm.checkValid(nestedForm);
383
- if (!ok) valid = false;
384
- }
385
- if (this.options.validate) {
386
- const result = this.options.validate(this._forms, form);
387
- if (result === false) {
823
+ return this.update(() => {
824
+ this._hasValidationResult = true;
825
+ this._errors = [];
826
+ if (this.isRequired(form) && this._forms.length === 0) {
388
827
  this._errors.push(
389
- this.options.messages?.validate ?? "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0438"
828
+ this.options.messages?.isRequired ?? "\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D \u044D\u043B\u0435\u043C\u0435\u043D\u0442"
390
829
  );
391
830
  return false;
392
831
  }
393
- if (typeof result === "string") {
394
- this._errors.push(result);
832
+ if (this.options.minForms != null && this._forms.length < this.options.minForms) {
833
+ this._errors.push(
834
+ this.options.messages?.minForms ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 ${this.options.minForms}`
835
+ );
395
836
  return false;
396
837
  }
397
- }
398
- return valid && this._errors.length === 0;
838
+ if (this.options.maxForms != null && this._forms.length > this.options.maxForms) {
839
+ this._errors.push(
840
+ this.options.messages?.maxForms ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${this.options.maxForms}`
841
+ );
842
+ return false;
843
+ }
844
+ let valid = true;
845
+ for (const nestedForm of this._forms) {
846
+ const ok = nestedForm.checkValid(nestedForm);
847
+ if (!ok) valid = false;
848
+ }
849
+ if (this.options.validate) {
850
+ const result = this.options.validate(this._forms, form);
851
+ if (result === false) {
852
+ this._errors.push(
853
+ this.options.messages?.validate ?? "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0438"
854
+ );
855
+ return false;
856
+ }
857
+ if (typeof result === "string") {
858
+ this._errors.push(result);
859
+ return false;
860
+ }
861
+ }
862
+ return valid && this._errors.length === 0;
863
+ });
399
864
  }
400
865
  checkAndSetValid(form) {
401
866
  return this.checkValid(form);
@@ -412,13 +877,15 @@ var ArrayFormField = class {
412
877
  return this._errors[0] ?? "";
413
878
  }
414
879
  set error(message) {
415
- if (message) {
416
- this._errors = [message];
417
- this._hasValidationResult = true;
418
- } else {
419
- this._errors = [];
420
- this._hasValidationResult = false;
421
- }
880
+ this.update(() => {
881
+ if (message) {
882
+ this._errors = [message];
883
+ this._hasValidationResult = true;
884
+ } else {
885
+ this._errors = [];
886
+ this._hasValidationResult = false;
887
+ }
888
+ });
422
889
  }
423
890
  };
424
891
 
@@ -673,11 +1140,29 @@ var ErrorsSchema = class _ErrorsSchema {
673
1140
  var DefaultErrorsSchema = new ErrorsSchema().fallback((key) => key);
674
1141
 
675
1142
  // src/core/Form.ts
676
- var Form = class {
1143
+ var Form = class extends ObservableNode {
677
1144
  constructor() {
1145
+ super(...arguments);
678
1146
  this._globalErrors = {};
679
1147
  this.errorsShema = DefaultErrorsSchema;
680
1148
  }
1149
+ captureState() {
1150
+ return {
1151
+ fieldsValue: snapshotValue(this.fieldsValue),
1152
+ allErrors: this.allErrors,
1153
+ globalErrors: this.globalErrors,
1154
+ fields: Object.fromEntries(Object.entries(this._fields).map(([key, field]) => [key, field.getSnapshot()])),
1155
+ isValid: this.isValid,
1156
+ isTouched: this.isTouched,
1157
+ isDirty: this.isDirty
1158
+ };
1159
+ }
1160
+ stateChildren() {
1161
+ return Object.values(this._fields);
1162
+ }
1163
+ batch(callback) {
1164
+ return this.batchUpdate(callback, () => this.checkValid());
1165
+ }
681
1166
  get _fields() {
682
1167
  const fields = {};
683
1168
  for (const key of Object.keys(this)) {
@@ -689,15 +1174,17 @@ var Form = class {
689
1174
  return fields;
690
1175
  }
691
1176
  checkValid(form) {
692
- let isFormValid = true;
693
- const fields = this._fields;
694
- for (const key of Object.keys(fields)) {
695
- const field = fields[key];
696
- if (!field.checkAndSetValid(form ?? this)) {
697
- isFormValid = false;
1177
+ return this.update(() => {
1178
+ let isFormValid = true;
1179
+ const fields = this._fields;
1180
+ for (const key of Object.keys(fields)) {
1181
+ const field = fields[key];
1182
+ if (!field.checkAndSetValid(form ?? this)) {
1183
+ isFormValid = false;
1184
+ }
698
1185
  }
699
- }
700
- return isFormValid && Object.keys(this._globalErrors).length === 0;
1186
+ return isFormValid && Object.keys(this._globalErrors).length === 0;
1187
+ });
701
1188
  }
702
1189
  get fieldsValue() {
703
1190
  const data = {};
@@ -717,17 +1204,19 @@ var Form = class {
717
1204
  this.setFields(data);
718
1205
  }
719
1206
  setFields(data, validate = true) {
720
- const fields = this._fields;
721
- for (const key of Object.keys(data)) {
722
- const field = fields[key];
723
- if (field) {
724
- if (field instanceof Field) field.setRawValue(data[key], false);
725
- else if (field instanceof ArrayField) field.itemsValue = data[key];
726
- else if (field instanceof ArrayFormField) field.setForms(data[key], false);
727
- else console.error(`Invalid field "${key}" type`);
1207
+ return this.update(() => {
1208
+ const fields = this._fields;
1209
+ for (const key of Object.keys(data)) {
1210
+ const field = fields[key];
1211
+ if (field) {
1212
+ if (field instanceof Field) field.setRawValue(data[key], false);
1213
+ else if (field instanceof ArrayField) field.setItemsValue(data[key], false);
1214
+ else if (field instanceof ArrayFormField) field.setForms(data[key], false);
1215
+ else console.error(`Invalid field "${key}" type`);
1216
+ }
728
1217
  }
729
- }
730
- if (validate) this.checkValid();
1218
+ if (validate) this.validateAfterMutation(() => this.checkValid());
1219
+ });
731
1220
  }
732
1221
  get allErrors() {
733
1222
  const errors = {};
@@ -742,7 +1231,7 @@ var Form = class {
742
1231
  } else {
743
1232
  const fieldErrors = field.errors;
744
1233
  if (fieldErrors.length > 0) {
745
- errors[key] = fieldErrors;
1234
+ errors[key] = [...fieldErrors];
746
1235
  }
747
1236
  }
748
1237
  }
@@ -775,26 +1264,30 @@ var Form = class {
775
1264
  return { ...this._globalErrors };
776
1265
  }
777
1266
  set errors(errors) {
778
- this.clearErrorsRecursively();
779
- const fields = this._fields;
780
- const parsedErrors = this.errorsShema.parseErrors(errors);
781
- for (const [fieldName, errorMessage] of Object.entries(parsedErrors)) {
782
- this.applyErrorToField(fieldName, errorMessage, fields, this);
783
- }
1267
+ this.update(() => {
1268
+ this.clearErrorsRecursively();
1269
+ const fields = this._fields;
1270
+ const parsedErrors = this.errorsShema.parseErrors(errors);
1271
+ for (const [fieldName, errorMessage] of Object.entries(parsedErrors)) {
1272
+ this.applyErrorToField(fieldName, errorMessage, fields, this);
1273
+ }
1274
+ });
784
1275
  }
785
1276
  clearErrorsRecursively() {
786
- this._globalErrors = {};
787
- for (const field of Object.values(this._fields)) {
788
- if (field instanceof Field) {
789
- field.error = null;
790
- } else if (field instanceof ArrayField) {
791
- field.error = null;
792
- for (const item of field.items) item.error = null;
793
- } else if (field instanceof ArrayFormField) {
794
- field.error = null;
795
- for (const nestedForm of field.forms) nestedForm.clearErrorsRecursively();
1277
+ this.update(() => {
1278
+ this._globalErrors = {};
1279
+ for (const field of Object.values(this._fields)) {
1280
+ if (field instanceof Field) {
1281
+ field.error = null;
1282
+ } else if (field instanceof ArrayField) {
1283
+ field.error = null;
1284
+ for (const item of field.items) item.error = null;
1285
+ } else if (field instanceof ArrayFormField) {
1286
+ field.error = null;
1287
+ for (const nestedForm of field.forms) nestedForm.clearErrorsRecursively();
1288
+ }
796
1289
  }
797
- }
1290
+ });
798
1291
  }
799
1292
  /**
800
1293
  * Apply an error to the corresponding field.
@@ -846,17 +1339,31 @@ var Form = class {
846
1339
  }
847
1340
  }
848
1341
  setGlobalError(key, message) {
849
- this._globalErrors[key] = message;
1342
+ return this.update(() => {
1343
+ this._globalErrors[key] = message;
1344
+ });
850
1345
  }
851
1346
  clearGlobalErrors() {
852
- this._globalErrors = {};
1347
+ return this.update(() => {
1348
+ this._globalErrors = {};
1349
+ });
853
1350
  }
854
1351
  reset() {
855
- const fields = this._fields;
856
- for (const key of Object.keys(fields)) {
857
- fields[key].reset();
858
- }
859
- this._globalErrors = {};
1352
+ return this.update(() => {
1353
+ const fields = this._fields;
1354
+ for (const key of Object.keys(fields)) {
1355
+ fields[key].reset();
1356
+ }
1357
+ this._globalErrors = {};
1358
+ });
1359
+ }
1360
+ get isDirty() {
1361
+ return Object.values(this._fields).some((field) => field.isDirty);
1362
+ }
1363
+ commitBaseline() {
1364
+ return this.update(() => {
1365
+ for (const field of Object.values(this._fields)) field.commitBaseline();
1366
+ });
860
1367
  }
861
1368
  get isTouched() {
862
1369
  const fields = this._fields;
@@ -1247,14 +1754,6 @@ var DecimalType = class extends FieldType {
1247
1754
  const parts = normalizedValue.split(".");
1248
1755
  const intPart = parts[0];
1249
1756
  const decPart = parts.length > 1 ? parts[1] : "";
1250
- if (normalizedValue.endsWith(".")) {
1251
- if (intPart.length > maxIntDigits) {
1252
- errors.push(
1253
- this.options.messages?.maxDigits ?? `\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0437\u043D\u0430\u043A\u043E\u0432 \u043F\u0435\u0440\u0435\u0434 \u0437\u0430\u043F\u044F\u0442\u043E\u0439 ${maxIntDigits}`
1254
- );
1255
- }
1256
- return errors;
1257
- }
1258
1757
  if (intPart.length === 0) {
1259
1758
  errors.push(this.options.messages?.invalid ?? "\u041F\u0440\u0438\u043C\u0435\u0440: 1.00");
1260
1759
  return errors;