adaptform 2.0.1 → 2.0.2

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.mjs CHANGED
@@ -1,3 +1,527 @@
1
+ // src/core/fields/Field.ts
2
+ var Field = class {
3
+ constructor(TypeConstructor, defaultValue, options) {
4
+ this._rawValue = null;
5
+ this._valueClear = null;
6
+ this._errors = [];
7
+ this.isValid = null;
8
+ this.isTouched = false;
9
+ this.filed_type = new TypeConstructor(options ?? {});
10
+ this.defaultValue = defaultValue ?? null;
11
+ for (const plugin of this.options.plugins ?? []) {
12
+ plugin.init?.(this);
13
+ }
14
+ if (defaultValue !== void 0 && defaultValue !== null) {
15
+ this.rawValue = defaultValue;
16
+ } else {
17
+ this._rawValue = null;
18
+ this._valueClear = null;
19
+ this.isValid = null;
20
+ }
21
+ }
22
+ // ========== Геттеры/сеттеры ==========
23
+ get plugins() {
24
+ return [...this.options.plugins ?? []].sort((a, b) => {
25
+ return (a.pluginOptions?.priority ?? 0) - (b.pluginOptions?.priority ?? 0);
26
+ });
27
+ }
28
+ get options() {
29
+ return this.filed_type.options;
30
+ }
31
+ set options(options) {
32
+ let cur_options = this.filed_type.options;
33
+ this.filed_type.options = Object.assign(cur_options, options);
34
+ }
35
+ get rawValue() {
36
+ return this._rawValue;
37
+ }
38
+ set rawValue(input) {
39
+ let rawValue = input;
40
+ for (const plugin of this.plugins) {
41
+ if (plugin.toRawValue) {
42
+ rawValue = plugin.toRawValue(rawValue, this);
43
+ }
44
+ }
45
+ let valueClear = rawValue;
46
+ for (const plugin of this.plugins) {
47
+ if (plugin.toValueClear) {
48
+ valueClear = plugin.toValueClear(valueClear, this);
49
+ }
50
+ }
51
+ this._rawValue = rawValue;
52
+ this._valueClear = this.filed_type.cast(valueClear);
53
+ this._errors = [];
54
+ this.isTouched = true;
55
+ this.checkAndSetValid();
56
+ }
57
+ get errors() {
58
+ return this._errors;
59
+ }
60
+ get error() {
61
+ return this._errors[0] ?? "";
62
+ }
63
+ set error(message) {
64
+ if (message) {
65
+ this._errors = [message];
66
+ } else {
67
+ this._errors = [];
68
+ }
69
+ this.isValid = message ? false : null;
70
+ }
71
+ get valueClear() {
72
+ return this._valueClear;
73
+ }
74
+ // ========== Валидация ==========
75
+ isRequired(form) {
76
+ let isRequired;
77
+ if (typeof this.options.isRequired === "function") {
78
+ isRequired = this.options.isRequired(form ?? null);
79
+ } else {
80
+ isRequired = this.options.isRequired ?? false;
81
+ }
82
+ return isRequired;
83
+ }
84
+ checkValid(form) {
85
+ this._errors = [];
86
+ if (this.isEmpty) {
87
+ if (this.isRequired(form)) {
88
+ 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");
89
+ return false;
90
+ }
91
+ return true;
92
+ }
93
+ if (this._valueClear === null) {
94
+ this._errors.push(
95
+ this.options.messages?.type ?? `\u041E\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044F ${this.filed_type.getTypeName()}`
96
+ );
97
+ return false;
98
+ }
99
+ const typeErrors = this.filed_type.validate(this._valueClear, form);
100
+ if (typeErrors.length > 0) {
101
+ this._errors.push(...typeErrors);
102
+ return false;
103
+ }
104
+ if (this.options.validate) {
105
+ const result = this.options.validate(this._valueClear, form);
106
+ if (result === false) {
107
+ 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");
108
+ return false;
109
+ }
110
+ if (typeof result === "string") {
111
+ this._errors.push(result);
112
+ return false;
113
+ }
114
+ }
115
+ return true;
116
+ }
117
+ checkAndSetValid(form) {
118
+ this.isValid = this.checkValid(form);
119
+ return this.isValid;
120
+ }
121
+ get isEmpty() {
122
+ let isEmpty = false;
123
+ if (this._rawValue === null || this._rawValue === void 0) isEmpty = true;
124
+ else if (this._rawValue === "") isEmpty = true;
125
+ else if (Array.isArray(this._rawValue) && this._rawValue.length === 0) isEmpty = true;
126
+ return isEmpty;
127
+ }
128
+ // ========== Вспомогательные методы ==========
129
+ reset() {
130
+ if (this.defaultValue !== null && this.defaultValue !== void 0) {
131
+ this.rawValue = this.defaultValue;
132
+ this.isValid = true;
133
+ } else {
134
+ this._rawValue = null;
135
+ this._valueClear = null;
136
+ this.isValid = null;
137
+ }
138
+ this._errors = [];
139
+ this.isTouched = false;
140
+ }
141
+ };
142
+
143
+ // src/core/fields/ArrayField.ts
144
+ var ArrayField = class {
145
+ constructor(factory, options = {}, initial = []) {
146
+ this.factory = factory;
147
+ this._items = [];
148
+ this._errors = [];
149
+ this.isTouched = false;
150
+ this.options = {
151
+ isRequired: true,
152
+ messages: {},
153
+ ...options
154
+ };
155
+ this._items = initial.map((v) => this.factory(v));
156
+ }
157
+ // ===== value =====
158
+ set itemsValue(items) {
159
+ this.clear();
160
+ for (const i of items) {
161
+ this.add(i, false);
162
+ }
163
+ this.checkValid();
164
+ }
165
+ get itemsValue() {
166
+ return this._items.map((i) => i.valueClear);
167
+ }
168
+ get items() {
169
+ return this._items;
170
+ }
171
+ // ===== actions =====
172
+ add(value, force_check) {
173
+ const field = this.factory(value);
174
+ this.isTouched = true;
175
+ this._items.push(field);
176
+ if (force_check) this.checkValid();
177
+ return field;
178
+ }
179
+ remove(index) {
180
+ this._items.splice(index, 1);
181
+ this.checkValid();
182
+ }
183
+ clear() {
184
+ this._items = [];
185
+ this.checkValid();
186
+ }
187
+ // ===== validation =====
188
+ isRequired(form) {
189
+ let isRequired;
190
+ if (typeof this.options.isRequired === "function") {
191
+ isRequired = this.options.isRequired(form ?? null);
192
+ } else {
193
+ isRequired = this.options.isRequired ?? false;
194
+ }
195
+ return isRequired;
196
+ }
197
+ checkValid(form) {
198
+ this._errors = [];
199
+ if (this.isRequired(form) && this._items.length === 0) {
200
+ this._errors.push(
201
+ 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"
202
+ );
203
+ return false;
204
+ }
205
+ if (this.options.minItems != null && this._items.length < this.options.minItems) {
206
+ this._errors.push(
207
+ 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}`
208
+ );
209
+ return false;
210
+ }
211
+ if (this.options.maxItems != null && this._items.length > this.options.maxItems) {
212
+ this._errors.push(
213
+ 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}`
214
+ );
215
+ return false;
216
+ }
217
+ let valid = true;
218
+ for (const field of this._items) {
219
+ const ok = field.checkAndSetValid(form);
220
+ if (!ok) valid = false;
221
+ }
222
+ if (this.options.validate) {
223
+ const result = this.options.validate(this._items, form);
224
+ if (result === false) {
225
+ this._errors.push(
226
+ this.options.messages?.validate ?? "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0438"
227
+ );
228
+ return false;
229
+ }
230
+ if (typeof result === "string") {
231
+ this._errors.push(result);
232
+ return false;
233
+ }
234
+ }
235
+ return valid && this._errors.length === 0;
236
+ }
237
+ checkAndSetValid(form) {
238
+ return this.checkValid(form);
239
+ }
240
+ get isValid() {
241
+ return this._errors.length === 0 && this._items.every((i) => i.isValid === true);
242
+ }
243
+ get error() {
244
+ return this._errors[0] ?? "";
245
+ }
246
+ set error(message) {
247
+ if (message) {
248
+ this._errors = [message];
249
+ } else {
250
+ this._errors = [];
251
+ }
252
+ }
253
+ get errors() {
254
+ return this._errors;
255
+ }
256
+ reset() {
257
+ this._items.forEach((i) => i.reset());
258
+ this._errors = [];
259
+ this.isTouched = false;
260
+ }
261
+ };
262
+
263
+ // src/core/fields/ArrayFormField.ts
264
+ var ArrayFormField = class {
265
+ constructor(FormConstructor, options = {}, initial = []) {
266
+ this.FormConstructor = FormConstructor;
267
+ this.options = options;
268
+ this._forms = [];
269
+ this._errors = [];
270
+ this.isTouched = false;
271
+ this._forms = initial.map((data) => {
272
+ const form = new this.FormConstructor();
273
+ form.fields = data;
274
+ return form;
275
+ });
276
+ }
277
+ // ===== value =====
278
+ set forms(forms) {
279
+ this.clear();
280
+ for (const f of forms) {
281
+ this.add(f, false);
282
+ }
283
+ this.checkValid();
284
+ }
285
+ get forms() {
286
+ return this._forms;
287
+ }
288
+ get formsFieldsValue() {
289
+ return this._forms.map((i) => i.fieldsValue);
290
+ }
291
+ // ===== actions =====
292
+ add(data, force_check) {
293
+ const form = new this.FormConstructor();
294
+ if (data) form.fields = data;
295
+ this.isTouched = true;
296
+ this._forms.push(form);
297
+ if (force_check) this.checkValid();
298
+ return form;
299
+ }
300
+ remove(index) {
301
+ this._forms.splice(index, 1);
302
+ this.checkValid();
303
+ }
304
+ clear() {
305
+ this._forms = [];
306
+ this.checkValid();
307
+ }
308
+ reset() {
309
+ this._forms.forEach((f) => f.reset());
310
+ this._errors = [];
311
+ this.isTouched = false;
312
+ }
313
+ // ===== validation =====
314
+ isRequired(form) {
315
+ let isRequired;
316
+ if (typeof this.options.isRequired === "function") {
317
+ isRequired = this.options.isRequired(form ?? null);
318
+ } else {
319
+ isRequired = this.options.isRequired ?? false;
320
+ }
321
+ return isRequired;
322
+ }
323
+ checkValid(form) {
324
+ this._errors = [];
325
+ if (this.isRequired(form) && this.forms.length === 0) {
326
+ this._errors.push(
327
+ 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"
328
+ );
329
+ return false;
330
+ }
331
+ if (this.options.minForms != null && this._forms.length < this.options.minForms) {
332
+ this._errors.push(
333
+ 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}`
334
+ );
335
+ return false;
336
+ }
337
+ if (this.options.maxForms != null && this._forms.length > this.options.maxForms) {
338
+ this._errors.push(
339
+ 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}`
340
+ );
341
+ return false;
342
+ }
343
+ let valid = true;
344
+ for (const form2 of this.forms) {
345
+ const ok = form2.checkValid(form2);
346
+ if (!ok) valid = false;
347
+ }
348
+ if (this.options.validate) {
349
+ const result = this.options.validate(this.forms, form);
350
+ if (result === false) {
351
+ this._errors.push(
352
+ this.options.messages?.validate ?? "\u041E\u0448\u0438\u0431\u043A\u0430 \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u0438"
353
+ );
354
+ return false;
355
+ }
356
+ if (typeof result === "string") {
357
+ this._errors.push(result);
358
+ return false;
359
+ }
360
+ }
361
+ return valid && this._errors.length === 0;
362
+ }
363
+ checkAndSetValid(form) {
364
+ return this.checkValid(form);
365
+ }
366
+ get isValid() {
367
+ return this._errors.length === 0 && this._forms.every((i) => i.checkValid() === true);
368
+ }
369
+ get errors() {
370
+ return this._errors;
371
+ }
372
+ get error() {
373
+ return this._errors[0] ?? "";
374
+ }
375
+ set error(message) {
376
+ if (message) {
377
+ this._errors = [message];
378
+ } else {
379
+ this._errors = [];
380
+ }
381
+ }
382
+ };
383
+
384
+ // src/core/Form.ts
385
+ var Form = class {
386
+ constructor() {
387
+ this._globalErrors = {};
388
+ }
389
+ get _fields() {
390
+ const fields = {};
391
+ for (const key of Object.keys(this)) {
392
+ const property = this[key];
393
+ if (property instanceof Field || property instanceof ArrayField || property instanceof ArrayFormField) {
394
+ fields[key] = property;
395
+ }
396
+ }
397
+ return fields;
398
+ }
399
+ checkValid(form) {
400
+ let isFormValid = true;
401
+ const fields = this._fields;
402
+ for (const key of Object.keys(fields)) {
403
+ const field = fields[key];
404
+ if (!field.checkAndSetValid(form ?? this)) {
405
+ isFormValid = false;
406
+ }
407
+ }
408
+ return isFormValid;
409
+ }
410
+ get fieldsValue() {
411
+ const data = {};
412
+ const fields = this._fields;
413
+ for (const key of Object.keys(fields)) {
414
+ let valueClear = null;
415
+ const field = fields[key];
416
+ if (field instanceof Field) valueClear = field.valueClear;
417
+ else if (field instanceof ArrayField) valueClear = field.itemsValue;
418
+ else if (field instanceof ArrayFormField) valueClear = field.formsFieldsValue;
419
+ else console.error(`Invalid field "${key}" type`);
420
+ data[key] = valueClear;
421
+ }
422
+ return data;
423
+ }
424
+ set fields(data) {
425
+ const fields = this._fields;
426
+ for (const key of Object.keys(data)) {
427
+ const field = fields[key];
428
+ if (field) {
429
+ if (field instanceof Field) field.rawValue = data[key];
430
+ else if (field instanceof ArrayField) field.itemsValue = data[key];
431
+ else if (field instanceof ArrayFormField) field.forms = data[key];
432
+ else console.error(`Invalid field "${key}" type`);
433
+ }
434
+ }
435
+ }
436
+ get allErrors() {
437
+ const errors = {};
438
+ const fields = this._fields;
439
+ for (const key of Object.keys(fields)) {
440
+ const fieldErrors = fields[key].errors;
441
+ if (fieldErrors.length > 0) {
442
+ errors[key] = fieldErrors;
443
+ }
444
+ }
445
+ for (const key of Object.keys(this._globalErrors)) {
446
+ if (!errors[key]) {
447
+ errors[key] = [];
448
+ }
449
+ errors[key].push(this._globalErrors[key]);
450
+ }
451
+ return errors;
452
+ }
453
+ get globalErrors() {
454
+ return { ...this._globalErrors };
455
+ }
456
+ set errors(errors) {
457
+ const fields = this._fields;
458
+ this._globalErrors = {};
459
+ for (const key of Object.keys(errors)) {
460
+ const keys = key.split(".");
461
+ const cleanKey = keys.length > 1 ? keys[1] : key;
462
+ if (cleanKey in fields && fields[cleanKey]) {
463
+ fields[cleanKey].error = errors[key];
464
+ } else {
465
+ this._globalErrors[key] = errors[key];
466
+ }
467
+ }
468
+ }
469
+ setGlobalError(key, message) {
470
+ this._globalErrors[key] = message;
471
+ }
472
+ clearGlobalErrors() {
473
+ this._globalErrors = {};
474
+ }
475
+ reset() {
476
+ const fields = this._fields;
477
+ for (const key of Object.keys(fields)) {
478
+ fields[key].reset();
479
+ }
480
+ this._globalErrors = {};
481
+ }
482
+ get isTouched() {
483
+ const fields = this._fields;
484
+ for (const key of Object.keys(fields)) {
485
+ if (fields[key].isTouched) return true;
486
+ }
487
+ return false;
488
+ }
489
+ // Проверить, валидна ли форма
490
+ get isValid() {
491
+ const fields = this._fields;
492
+ for (const key of Object.keys(fields)) {
493
+ if (fields[key].isValid !== true) return false;
494
+ }
495
+ return Object.keys(this._globalErrors).length === 0;
496
+ }
497
+ // Получить все значения в виде FormData (для отправки на сервер)
498
+ toFormData() {
499
+ const formData = new FormData();
500
+ const data = this.fieldsValue;
501
+ for (const [key, value] of Object.entries(data)) {
502
+ if (value instanceof Date) {
503
+ formData.append(key, value.toISOString());
504
+ } else if (value !== null && value !== void 0) {
505
+ formData.append(key, String(value));
506
+ }
507
+ }
508
+ return formData;
509
+ }
510
+ // Получить все значения в виде JSON
511
+ toJSON() {
512
+ const data = this.fieldsValue;
513
+ const json = {};
514
+ for (const [key, value] of Object.entries(data)) {
515
+ if (value instanceof Date) {
516
+ json[key] = value.toISOString();
517
+ } else {
518
+ json[key] = value;
519
+ }
520
+ }
521
+ return json;
522
+ }
523
+ };
524
+
1
525
  // src/core/plugins/FieldPlugin.ts
2
526
  var BasePlugin = class {
3
527
  constructor(pluginOptions = {}) {
@@ -8,6 +532,188 @@ var BasePlugin = class {
8
532
  }
9
533
  };
10
534
 
535
+ // src/core/plugins/MaskPlugin.ts
536
+ var MaskPlugin = class extends BasePlugin {
537
+ constructor(config, pluginOptions) {
538
+ super(pluginOptions);
539
+ this.maskParts = [];
540
+ this.config = config;
541
+ }
542
+ init(field) {
543
+ this.parseMask();
544
+ }
545
+ toRawValue(value, field) {
546
+ return this.applyMask(value);
547
+ }
548
+ toValueClear(value, field) {
549
+ return this.removeMask(value);
550
+ }
551
+ parseMask() {
552
+ this.maskParts = [];
553
+ let i = 0;
554
+ let escaped = false;
555
+ while (i < this.config.maskFormat.length) {
556
+ const char = this.config.maskFormat[i];
557
+ if (char === "/" && !escaped) {
558
+ escaped = true;
559
+ i++;
560
+ continue;
561
+ }
562
+ if (char === this.config.maskPlaceholder && i + 1 < this.config.maskFormat.length && this.config.maskFormat[i + 1] === "{" && !escaped) {
563
+ const openBracket = i + 1;
564
+ const closeBracket = this.config.maskFormat.indexOf("}", openBracket);
565
+ if (closeBracket !== -1 && closeBracket > openBracket + 1) {
566
+ const configString = this.config.maskFormat.substring(openBracket + 1, closeBracket).trim();
567
+ if (configString.includes(">")) {
568
+ const parts = configString.split(">");
569
+ const allowedChars = parts[0].trim();
570
+ const replacementOnMatch = parts[1]?.trim() || "";
571
+ let replacementOnMismatch = parts[2]?.trim() || "";
572
+ let pushToNext = false;
573
+ if (parts.length > 2 && parts[2] === "" && parts[3] !== void 0) {
574
+ pushToNext = true;
575
+ replacementOnMismatch = parts[3]?.trim() || "";
576
+ } else if (replacementOnMismatch === "" && parts.length > 3) {
577
+ pushToNext = true;
578
+ replacementOnMismatch = parts[3]?.trim() || "";
579
+ }
580
+ this.maskParts.push({
581
+ char: replacementOnMatch || this.config.maskPlaceholder,
582
+ isPlaceholder: true,
583
+ isEscaped: escaped,
584
+ allowedChars,
585
+ transformOnMatch: replacementOnMatch,
586
+ transformOnMismatch: replacementOnMismatch,
587
+ defaultValue: replacementOnMatch,
588
+ pushToNext
589
+ });
590
+ } else {
591
+ this.maskParts.push({
592
+ char: configString,
593
+ isPlaceholder: true,
594
+ isEscaped: escaped,
595
+ replacementValue: configString,
596
+ defaultValue: configString
597
+ });
598
+ }
599
+ escaped = false;
600
+ i = closeBracket + 1;
601
+ continue;
602
+ }
603
+ }
604
+ const isPlaceholder = char === this.config.maskPlaceholder;
605
+ this.maskParts.push({
606
+ char,
607
+ isPlaceholder,
608
+ isEscaped: escaped
609
+ });
610
+ escaped = false;
611
+ i++;
612
+ }
613
+ }
614
+ applyMask(value) {
615
+ if (typeof value !== "string" || !value) return "";
616
+ let result = "";
617
+ let inputIndex = 0;
618
+ for (let maskIndex = 0; maskIndex < this.maskParts.length; maskIndex++) {
619
+ const part = this.maskParts[maskIndex];
620
+ if (inputIndex >= value.length) {
621
+ if (part.replacementValue) {
622
+ result += part.replacementValue;
623
+ continue;
624
+ }
625
+ if (part.transformOnMatch) {
626
+ result += part.transformOnMatch;
627
+ continue;
628
+ }
629
+ break;
630
+ }
631
+ const inputChar = value[inputIndex];
632
+ if (part.isPlaceholder) {
633
+ if (part.replacementValue) {
634
+ result += part.replacementValue;
635
+ inputIndex++;
636
+ } else if (part.allowedChars) {
637
+ if (part.allowedChars.includes(inputChar)) {
638
+ result += part.transformOnMatch || inputChar;
639
+ inputIndex++;
640
+ } else if (part.pushToNext) {
641
+ result += part.transformOnMismatch || this.config.maskPlaceholder;
642
+ } else if (part.transformOnMismatch !== void 0) {
643
+ result += part.transformOnMismatch || this.config.maskPlaceholder;
644
+ inputIndex++;
645
+ } else {
646
+ result += this.config.maskPlaceholder;
647
+ }
648
+ } else {
649
+ if (this.config.digitPattern.test(inputChar)) {
650
+ result += inputChar;
651
+ inputIndex++;
652
+ } else if (inputChar === this.config.maskPlaceholder) {
653
+ result += this.config.maskPlaceholder;
654
+ inputIndex++;
655
+ } else {
656
+ inputIndex++;
657
+ maskIndex--;
658
+ }
659
+ }
660
+ } else {
661
+ if (inputChar === part.char) {
662
+ result += part.char;
663
+ inputIndex++;
664
+ } else if (this.config.digitPattern.test(inputChar)) {
665
+ result += part.char;
666
+ } else {
667
+ result += part.char;
668
+ }
669
+ }
670
+ }
671
+ return result;
672
+ }
673
+ removeMask(value) {
674
+ if (typeof value !== "string" || !value) return "";
675
+ let result = "";
676
+ let inputIndex = 0;
677
+ for (let maskIndex = 0; maskIndex < this.maskParts.length; maskIndex++) {
678
+ const part = this.maskParts[maskIndex];
679
+ if (inputIndex >= value.length) {
680
+ if (part.replacementValue) {
681
+ result += part.replacementValue;
682
+ } else if (part.transformOnMatch) {
683
+ result += part.transformOnMatch;
684
+ }
685
+ continue;
686
+ }
687
+ const inputChar = value[inputIndex];
688
+ if (part.isPlaceholder) {
689
+ if (part.replacementValue) {
690
+ result += part.replacementValue;
691
+ } else if (part.allowedChars) {
692
+ if (part.allowedChars.includes(inputChar)) {
693
+ result += part.transformOnMatch || inputChar;
694
+ } else if (part.pushToNext) {
695
+ result += part.transformOnMismatch || "";
696
+ continue;
697
+ } else {
698
+ result += part.transformOnMatch || "";
699
+ }
700
+ } else {
701
+ if (inputChar !== this.config.maskPlaceholder && this.config.digitPattern.test(inputChar)) {
702
+ result += inputChar;
703
+ }
704
+ }
705
+ inputIndex++;
706
+ } else if (part.isEscaped) {
707
+ result += part.char;
708
+ if (inputChar === part.char) inputIndex++;
709
+ } else {
710
+ if (inputChar === part.char) inputIndex++;
711
+ }
712
+ }
713
+ return result;
714
+ }
715
+ };
716
+
11
717
  // src/core/types/FieldType.ts
12
718
  var FieldType = class {
13
719
  constructor(options) {
@@ -19,6 +725,197 @@ var FieldType = class {
19
725
  }
20
726
  };
21
727
 
728
+ // src/core/types/StringType.ts
729
+ var StringType = class extends FieldType {
730
+ cast(rawValue) {
731
+ if (rawValue === null || rawValue === void 0) return null;
732
+ if (typeof rawValue === "string") return rawValue;
733
+ return String(rawValue);
734
+ }
735
+ validate(value) {
736
+ const errors = [];
737
+ if (this.options.minLength != null && value.length < this.options.minLength) {
738
+ errors.push(
739
+ this.options.messages?.minLength ?? `\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u043B\u0438\u043D\u0430 ${this.options.minLength} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432`
740
+ );
741
+ }
742
+ if (this.options.maxLength != null && value.length > this.options.maxLength) {
743
+ errors.push(
744
+ this.options.messages?.maxLength ?? `\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u043B\u0438\u043D\u0430 ${this.options.maxLength} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432`
745
+ );
746
+ }
747
+ if (this.options.pattern != null && !this.options.pattern.test(value)) {
748
+ errors.push(this.options.messages?.pattern ?? "\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442");
749
+ }
750
+ return errors;
751
+ }
752
+ getTypeName() {
753
+ return "\u0441\u0442\u0440\u043E\u043A\u0430";
754
+ }
755
+ };
756
+
757
+ // src/core/types/NumberType.ts
758
+ var NumberType = class extends FieldType {
759
+ cast(rawValue) {
760
+ if (rawValue === null || rawValue === void 0) return null;
761
+ if (typeof rawValue === "number" && !isNaN(rawValue)) return rawValue;
762
+ if (typeof rawValue === "string") {
763
+ const num = Number(rawValue);
764
+ return isNaN(num) ? null : num;
765
+ }
766
+ return null;
767
+ }
768
+ validate(value) {
769
+ const errors = [];
770
+ if (!Number.isInteger(value)) {
771
+ errors.push(this.options.messages?.invalid ?? "\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0446\u0435\u043B\u044B\u043C \u0447\u0438\u0441\u043B\u043E\u043C");
772
+ }
773
+ if (this.options.gt != null && value <= this.options.gt) {
774
+ errors.push(
775
+ this.options.messages?.gt ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 ${this.options.gt}`
776
+ );
777
+ }
778
+ if (this.options.ge != null && value < this.options.ge) {
779
+ errors.push(
780
+ this.options.messages?.ge ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u0435\u0435 ${this.options.ge}`
781
+ );
782
+ }
783
+ if (this.options.lt != null && value >= this.options.lt) {
784
+ errors.push(
785
+ this.options.messages?.lt ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043C\u0435\u043D\u044C\u0448\u0435 ${this.options.lt}`
786
+ );
787
+ }
788
+ if (this.options.le != null && value > this.options.le) {
789
+ errors.push(
790
+ this.options.messages?.le ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0431\u043E\u043B\u0435\u0435 ${this.options.le}`
791
+ );
792
+ }
793
+ return errors;
794
+ }
795
+ getTypeName() {
796
+ return "\u0447\u0438\u0441\u043B\u043E";
797
+ }
798
+ };
799
+
800
+ // src/core/types/DecimalType.ts
801
+ var DecimalType = class extends FieldType {
802
+ constructor(options = {}) {
803
+ super({
804
+ decimalPlaces: 2,
805
+ maxDigits: 8,
806
+ ...options
807
+ });
808
+ }
809
+ cast(rawValue) {
810
+ if (rawValue === null || rawValue === void 0) return null;
811
+ if (typeof rawValue === "string") {
812
+ return this.castString(rawValue);
813
+ }
814
+ if (typeof rawValue === "number" && !isNaN(rawValue)) {
815
+ return rawValue;
816
+ }
817
+ return null;
818
+ }
819
+ castString(value) {
820
+ const trimmed = value.trim();
821
+ if (!trimmed) return null;
822
+ const normalized = trimmed.replace(",", ".");
823
+ if (!this.isValidNumberString(normalized)) {
824
+ return null;
825
+ }
826
+ return normalized;
827
+ }
828
+ validate(value) {
829
+ const errors = [];
830
+ value = typeof value === "number" ? this.numberToString(value) : value;
831
+ if (!this.isValidNumberString(value)) {
832
+ errors.push(this.options.messages?.invalid ?? "\u041F\u0440\u0438\u043C\u0435\u0440: 1.00");
833
+ return errors;
834
+ }
835
+ const maxDigits = this.options.maxDigits || 8;
836
+ const decimalPlaces = this.options.decimalPlaces || 2;
837
+ const maxIntDigits = maxDigits - decimalPlaces;
838
+ const isNegative = value.startsWith("-");
839
+ const normalizedValue = isNegative ? value.substring(1) : value;
840
+ const parts = normalizedValue.split(".");
841
+ const intPart = parts[0];
842
+ const decPart = parts.length > 1 ? parts[1] : "";
843
+ if (normalizedValue.endsWith(".")) {
844
+ if (intPart.length > maxIntDigits) {
845
+ errors.push(
846
+ 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}`
847
+ );
848
+ }
849
+ return errors;
850
+ }
851
+ if (intPart.length === 0) {
852
+ errors.push(this.options.messages?.invalid ?? "\u041F\u0440\u0438\u043C\u0435\u0440: 1.00");
853
+ return errors;
854
+ }
855
+ if (intPart.length > maxIntDigits) {
856
+ errors.push(
857
+ 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}`
858
+ );
859
+ }
860
+ if (parts.length === 2) {
861
+ if (intPart.length + decPart.length > maxDigits) {
862
+ errors.push(
863
+ 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 ${maxDigits}`
864
+ );
865
+ }
866
+ if (decPart.length === 0) {
867
+ errors.push(
868
+ this.options.messages?.invalid ?? "\u041F\u043E\u0441\u043B\u0435 \u0442\u043E\u0447\u043A\u0438 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043C\u0438\u043D\u0438\u043C\u0443\u043C 1 \u0437\u043D\u0430\u043A"
869
+ );
870
+ } else if (decPart.length > decimalPlaces) {
871
+ errors.push(
872
+ this.options.messages?.decimalPlaces ?? `\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\u043E\u0441\u043B\u0435 \u0437\u0430\u043F\u044F\u0442\u043E\u0439 ${decimalPlaces}`
873
+ );
874
+ }
875
+ }
876
+ if (errors.length > 0) return errors;
877
+ if (!value.endsWith(".")) {
878
+ const numValue = parseFloat(value);
879
+ if (!isNaN(numValue)) {
880
+ if (this.options.gt != null && numValue <= this.options.gt) {
881
+ errors.push(
882
+ this.options.messages?.gt ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 ${this.options.gt}`
883
+ );
884
+ }
885
+ if (this.options.ge != null && numValue < this.options.ge) {
886
+ errors.push(
887
+ this.options.messages?.ge ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u0435\u0435 ${this.options.ge}`
888
+ );
889
+ }
890
+ if (this.options.lt != null && numValue >= this.options.lt) {
891
+ errors.push(
892
+ this.options.messages?.lt ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043C\u0435\u043D\u044C\u0448\u0435 ${this.options.lt}`
893
+ );
894
+ }
895
+ if (this.options.le != null && numValue > this.options.le) {
896
+ errors.push(
897
+ this.options.messages?.le ?? `\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0431\u043E\u043B\u0435\u0435 ${this.options.le}`
898
+ );
899
+ }
900
+ }
901
+ }
902
+ return errors;
903
+ }
904
+ isValidNumberString(value) {
905
+ const pattern = /^-?\d+\.?\d*$/;
906
+ const dotCount = (value.match(/\./g) || []).length;
907
+ if (dotCount > 1) return false;
908
+ return pattern.test(value);
909
+ }
910
+ numberToString(value) {
911
+ const decimalPlaces = this.options.decimalPlaces;
912
+ return value.toFixed(decimalPlaces);
913
+ }
914
+ getTypeName() {
915
+ return "\u0434\u0435\u0441\u044F\u0442\u0438\u0447\u043D\u043E\u0435 \u0447\u0438\u0441\u043B\u043E";
916
+ }
917
+ };
918
+
22
919
  // src/core/types/BooleanType.ts
23
920
  var BooleanType = class extends FieldType {
24
921
  cast(rawValue) {
@@ -49,6 +946,70 @@ var BooleanType = class extends FieldType {
49
946
  }
50
947
  };
51
948
 
949
+ // src/core/types/DateType.ts
950
+ var DateType = class extends FieldType {
951
+ constructor(options = {}) {
952
+ super(options);
953
+ }
954
+ cast(rawValue) {
955
+ if (rawValue === null || rawValue === void 0) return null;
956
+ if (rawValue instanceof Date) {
957
+ return isNaN(rawValue.getTime()) ? null : rawValue;
958
+ }
959
+ if (typeof rawValue === "string") {
960
+ const date = new Date(rawValue);
961
+ return isNaN(date.getTime()) ? null : date;
962
+ }
963
+ return null;
964
+ }
965
+ validate(value) {
966
+ const errors = [];
967
+ if (isNaN(value.getTime())) {
968
+ errors.push(this.options.messages?.invalid ?? "\u041D\u0435\u0432\u0435\u0440\u043D\u0430\u044F \u0434\u0430\u0442\u0430");
969
+ return errors;
970
+ }
971
+ if (this.options.minDate) {
972
+ if (!this.compareDates(value, this.options.minDate, "min")) {
973
+ errors.push(
974
+ this.options.messages?.minDate ?? `\u0414\u0430\u0442\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043D\u0435 \u0440\u0430\u043D\u0435\u0435 ${this.options.minDate.toLocaleDateString()}`
975
+ );
976
+ }
977
+ }
978
+ if (this.options.maxDate) {
979
+ if (!this.compareDates(value, this.options.maxDate, "max")) {
980
+ errors.push(
981
+ this.options.messages?.maxDate ?? `\u0414\u0430\u0442\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043D\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0435 ${this.options.maxDate.toLocaleDateString()}`
982
+ );
983
+ }
984
+ }
985
+ return errors;
986
+ }
987
+ getTypeName() {
988
+ return this.options.isDatetime ? "\u0434\u0430\u0442\u0430 \u0438 \u0432\u0440\u0435\u043C\u044F" : "\u0434\u0430\u0442\u0430";
989
+ }
990
+ // Сравнение дат с учётом времени
991
+ compareDates(value, boundary, type) {
992
+ if (this.options.isDatetime) {
993
+ if (type === "min") {
994
+ return value >= boundary;
995
+ } else {
996
+ return value <= boundary;
997
+ }
998
+ } else {
999
+ const valueDate = this.toDateOnly(value);
1000
+ const boundaryDate = this.toDateOnly(boundary);
1001
+ if (type === "min") {
1002
+ return valueDate >= boundaryDate;
1003
+ } else {
1004
+ return valueDate <= boundaryDate;
1005
+ }
1006
+ }
1007
+ }
1008
+ toDateOnly(date) {
1009
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
1010
+ }
1011
+ };
1012
+
52
1013
  // src/core/utils/luxon-loader.ts
53
1014
  var DateTimeConstructor = null;
54
1015
  var isLoading = false;
@@ -106,6 +1067,6 @@ function resetLuxon() {
106
1067
  initLuxon().catch(() => {
107
1068
  });
108
1069
 
109
- export { BasePlugin, BooleanType, getDateTimeConstructor, initLuxon, isLuxonAvailable, resetLuxon };
1070
+ export { ArrayField, ArrayFormField, BasePlugin, BooleanType, DateType, DecimalType, Field, FieldType, Form, MaskPlugin, NumberType, StringType, getDateTimeConstructor, initLuxon, isLuxonAvailable, resetLuxon };
110
1071
  //# sourceMappingURL=index.mjs.map
111
1072
  //# sourceMappingURL=index.mjs.map