oxform-core 0.1.0 → 0.1.1

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 (39) hide show
  1. package/dist/index.cjs +751 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +443 -0
  4. package/dist/index.d.ts +443 -0
  5. package/dist/index.js +747 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +20 -15
  8. package/export/index.ts +0 -7
  9. package/export/schema.ts +0 -1
  10. package/src/field-api.constants.ts +0 -15
  11. package/src/field-api.ts +0 -139
  12. package/src/form-api.ts +0 -84
  13. package/src/form-api.types.ts +0 -148
  14. package/src/form-array-field-api.ts +0 -233
  15. package/src/form-context-api.ts +0 -232
  16. package/src/form-field-api.ts +0 -174
  17. package/src/more-types.ts +0 -178
  18. package/src/tests/array/append.spec.ts +0 -138
  19. package/src/tests/array/insert.spec.ts +0 -182
  20. package/src/tests/array/move.spec.ts +0 -175
  21. package/src/tests/array/prepend.spec.ts +0 -138
  22. package/src/tests/array/remove.spec.ts +0 -174
  23. package/src/tests/array/swap.spec.ts +0 -152
  24. package/src/tests/array/update.spec.ts +0 -148
  25. package/src/tests/field/change.spec.ts +0 -226
  26. package/src/tests/field/reset.spec.ts +0 -617
  27. package/src/tests/field/set-errors.spec.ts +0 -254
  28. package/src/tests/field-api/field-api.spec.ts +0 -341
  29. package/src/tests/form-api/reset.spec.ts +0 -535
  30. package/src/tests/form-api/submit.spec.ts +0 -409
  31. package/src/types.ts +0 -5
  32. package/src/utils/get.ts +0 -5
  33. package/src/utils/testing/sleep.ts +0 -1
  34. package/src/utils/testing/tests.ts +0 -18
  35. package/src/utils/update.ts +0 -6
  36. package/src/utils/validate.ts +0 -8
  37. package/tsconfig.json +0 -3
  38. package/tsdown.config.ts +0 -10
  39. package/vitest.config.ts +0 -3
package/dist/index.js ADDED
@@ -0,0 +1,747 @@
1
+ import { isDeepEqual, isFunction, mergeDeep, setPath, stringToPath } from "remeda";
2
+ import { Derived, Store, batch } from "@tanstack/store";
3
+
4
+ //#region src/field-api.constants.ts
5
+ const defaultMeta = {
6
+ blurred: false,
7
+ touched: false,
8
+ dirty: false
9
+ };
10
+ const defaultStatus = {
11
+ submits: 0,
12
+ submitting: false,
13
+ validating: false,
14
+ successful: false,
15
+ dirty: false
16
+ };
17
+
18
+ //#endregion
19
+ //#region src/utils/get.ts
20
+ const get = (data, path) => {
21
+ return path.reduce((acc, key) => {
22
+ if (acc === void 0) return void 0;
23
+ if (acc === null) return null;
24
+ return acc[key];
25
+ }, data);
26
+ };
27
+
28
+ //#endregion
29
+ //#region src/utils/update.ts
30
+ function update(updater, input) {
31
+ return typeof updater === "function" ? updater(input) : updater;
32
+ }
33
+
34
+ //#endregion
35
+ //#region src/form-array-field-api.ts
36
+ var FormArrayFieldApi = class {
37
+ context;
38
+ field;
39
+ constructor({ field, context }) {
40
+ this.context = context;
41
+ this.field = field;
42
+ }
43
+ insert = (name, index, value, options) => {
44
+ if (index < 0) index = 0;
45
+ this.field.change(name, (current) => {
46
+ const array = current ?? [];
47
+ return [
48
+ ...array.slice(0, index),
49
+ ...Array.from({ length: index - array.length }, () => void 0),
50
+ update(value, current),
51
+ ...array.slice(index)
52
+ ];
53
+ }, options);
54
+ this.context.persisted.setState((current) => {
55
+ const fields = { ...current.fields };
56
+ const length = get(current.values, stringToPath(name))?.length;
57
+ if (length === void 0) return current;
58
+ for (let i = index; i < length; i++) {
59
+ const moving = current.fields[`${name}.${i}`];
60
+ fields[`${name}.${i + 1}`] = moving ?? defaultMeta;
61
+ }
62
+ fields[`${name}.${index}`] = defaultMeta;
63
+ return {
64
+ ...current,
65
+ fields
66
+ };
67
+ });
68
+ };
69
+ append = (name, value, options) => {
70
+ const current = this.field.get(name);
71
+ return this.insert(name, current?.length ?? 0, value, options);
72
+ };
73
+ prepend = (name, value, options) => {
74
+ return this.insert(name, 0, value, options);
75
+ };
76
+ swap = (name, from, to, options) => {
77
+ const start = from >= 0 ? from : 0;
78
+ const end = to >= 0 ? to : 0;
79
+ this.field.change(name, (current) => {
80
+ const array = current ?? [];
81
+ if (start === end) return array;
82
+ const a = array[start];
83
+ const b = array[end];
84
+ return [
85
+ ...array.slice(0, start),
86
+ b,
87
+ ...array.slice(start + 1, end),
88
+ a,
89
+ ...array.slice(end + 1)
90
+ ];
91
+ }, options);
92
+ this.context.persisted.setState((current) => {
93
+ const fields = { ...current.fields };
94
+ fields[`${name}.${start}`] = current.fields[`${name}.${end}`] ?? defaultMeta;
95
+ fields[`${name}.${end}`] = current.fields[`${name}.${start}`] ?? defaultMeta;
96
+ return {
97
+ ...current,
98
+ fields
99
+ };
100
+ });
101
+ };
102
+ move(name, _from, _to, options) {
103
+ const from = Math.max(_from, 0);
104
+ const to = Math.max(_to, 0);
105
+ const backwards = from > to;
106
+ this.field.change(name, (current) => {
107
+ const array = current ? [...current] : [];
108
+ if (from === to) return array;
109
+ const moved = array[from];
110
+ return array.toSpliced(backwards ? to : to + 1, 0, moved).toSpliced(backwards ? from + 1 : from, 1);
111
+ }, options);
112
+ this.context.persisted.setState((current) => {
113
+ const fields = { ...current.fields };
114
+ const length = get(current.values, stringToPath(name))?.length;
115
+ const start = Math.min(from, to);
116
+ const end = Math.max(from, to);
117
+ if (length === void 0) return current;
118
+ if (!backwards) fields[`${name}.${to}`] = current.fields[`${name}.${from}`] ?? defaultMeta;
119
+ for (let i = backwards ? start + 1 : start; i < end; i++) {
120
+ const shift = backwards ? -1 : 1;
121
+ const moving = current.fields[`${name}.${i + shift}`];
122
+ fields[`${name}.${i}`] = moving ?? defaultMeta;
123
+ }
124
+ return {
125
+ ...current,
126
+ fields
127
+ };
128
+ });
129
+ }
130
+ update = (name, index, value, options) => {
131
+ this.field.change(name, (current) => {
132
+ const array = current ?? [];
133
+ const position = Math.max(Math.min(index, array.length - 1), 0);
134
+ return [
135
+ ...array.slice(0, position),
136
+ update(value, current),
137
+ ...array.slice(position + 1)
138
+ ];
139
+ }, options);
140
+ this.context.resetFieldMeta(`${name}.${index}`);
141
+ this.context.setFieldMeta(`${name}.${index}`, {
142
+ dirty: options?.should?.dirty !== false,
143
+ touched: options?.should?.touch !== false
144
+ });
145
+ };
146
+ remove(name, index, options) {
147
+ let position = index;
148
+ this.field.change(name, (current) => {
149
+ const array = current ?? [];
150
+ position = Math.max(Math.min(index, array.length - 1), 0);
151
+ return [...array.slice(0, position), ...array.slice(position + 1)];
152
+ }, {
153
+ ...options,
154
+ should: {
155
+ ...options?.should,
156
+ validate: false
157
+ }
158
+ });
159
+ this.context.persisted.setState((current) => {
160
+ const fields = { ...current.fields };
161
+ const length = get(current.values, stringToPath(name))?.length ?? 0;
162
+ for (let i = position; i < length; i++) {
163
+ const moving = current.fields[`${name}.${i + 1}`];
164
+ fields[`${name}.${i}`] = moving ?? defaultMeta;
165
+ }
166
+ delete fields[`${name}.${length}`];
167
+ return {
168
+ ...current,
169
+ fields
170
+ };
171
+ });
172
+ if (options?.should?.validate !== false) this.context.validate(name, { type: "change" });
173
+ }
174
+ replace(name, value, options) {
175
+ this.context.resetFieldMeta(name);
176
+ this.field.change(name, value, options);
177
+ }
178
+ };
179
+
180
+ //#endregion
181
+ //#region src/utils/validate.ts
182
+ const validate = async (schema, input) => {
183
+ let result = schema["~standard"].validate(input);
184
+ if (result instanceof Promise) result = await result;
185
+ return result;
186
+ };
187
+
188
+ //#endregion
189
+ //#region src/form-context-api.ts
190
+ var FormContextApi = class {
191
+ options;
192
+ persisted;
193
+ store;
194
+ constructor(options) {
195
+ const values = mergeDeep(options.defaultValues, options.values ?? {});
196
+ this.options = options;
197
+ this.persisted = new Store({
198
+ values,
199
+ fields: {},
200
+ refs: {},
201
+ status: defaultStatus,
202
+ errors: {}
203
+ });
204
+ this.store = new Derived({
205
+ deps: [this.persisted],
206
+ fn: ({ currDepVals }) => {
207
+ const persisted = currDepVals[0];
208
+ const invalid = Object.values(persisted.errors).some((issues) => issues.length > 0);
209
+ const dirty = Object.values(persisted.fields).some((meta) => meta.dirty);
210
+ const fields = Object.fromEntries(Object.entries(persisted.fields).map(([key, meta]) => {
211
+ return [key, this.buildFieldMeta(key, meta, persisted.values, persisted.errors)];
212
+ }));
213
+ return {
214
+ ...persisted,
215
+ fields,
216
+ status: {
217
+ ...persisted.status,
218
+ submitted: persisted.status.submits > 0,
219
+ valid: !invalid,
220
+ dirty: persisted.status.dirty || dirty
221
+ }
222
+ };
223
+ }
224
+ });
225
+ }
226
+ get status() {
227
+ return this.store.state.status;
228
+ }
229
+ get values() {
230
+ return this.store.state.values;
231
+ }
232
+ get validator() {
233
+ const store = this.store.state;
234
+ const validate$1 = this.options.validate;
235
+ return {
236
+ change: isFunction(validate$1?.change) ? validate$1.change(store) : validate$1?.change,
237
+ submit: isFunction(validate$1?.submit) ? validate$1.submit(store) : validate$1?.submit ?? this.options.schema,
238
+ blur: isFunction(validate$1?.blur) ? validate$1.blur(store) : validate$1?.blur,
239
+ focus: isFunction(validate$1?.focus) ? validate$1.focus(store) : validate$1?.focus
240
+ };
241
+ }
242
+ buildFieldMeta = (fieldName, persistedMeta, values, errors) => {
243
+ const path = stringToPath(fieldName);
244
+ const value = get(values, path);
245
+ const defaultValue = get(this.options.defaultValues, path);
246
+ const invalid = errors[fieldName]?.length > 0;
247
+ const baseMeta = persistedMeta ?? defaultMeta;
248
+ return {
249
+ ...baseMeta,
250
+ default: isDeepEqual(value, defaultValue),
251
+ pristine: !baseMeta.dirty,
252
+ valid: !invalid
253
+ };
254
+ };
255
+ setFieldMeta = (name, meta) => {
256
+ this.persisted.setState((current) => {
257
+ return {
258
+ ...current,
259
+ fields: {
260
+ ...current.fields,
261
+ [name]: {
262
+ ...defaultMeta,
263
+ ...this.persisted.state.fields[name],
264
+ ...meta
265
+ }
266
+ }
267
+ };
268
+ });
269
+ };
270
+ resetFieldMeta = (name) => {
271
+ this.persisted.setState((current) => {
272
+ const fields = { ...current.fields };
273
+ const affected = Object.keys(current.fields).filter((key) => key.startsWith(name));
274
+ for (const key of affected) delete fields[key];
275
+ return {
276
+ ...current,
277
+ fields
278
+ };
279
+ });
280
+ };
281
+ recomputeFieldMeta = (name) => {
282
+ this.persisted.setState((current) => {
283
+ const related = this.options.related?.[name] ?? [];
284
+ const updated = Object.keys(current.fields).filter((key) => key.startsWith(name) || related.includes(key)).reduce((acc, key) => {
285
+ return {
286
+ ...acc,
287
+ [key]: this.buildFieldMeta(key, current.fields[key], current.values, current.errors)
288
+ };
289
+ }, {});
290
+ return {
291
+ ...current,
292
+ fields: {
293
+ ...current.fields,
294
+ ...updated
295
+ }
296
+ };
297
+ });
298
+ };
299
+ setStatus = (status) => {
300
+ this.persisted.setState((current) => {
301
+ return {
302
+ ...current,
303
+ status: {
304
+ ...current.status,
305
+ ...status
306
+ }
307
+ };
308
+ });
309
+ };
310
+ validate = async (field, options) => {
311
+ const validator = options?.type ? this.validator[options.type] : this.options.schema;
312
+ if (!validator) return [];
313
+ this.setStatus({ validating: true });
314
+ const { issues: allIssues } = await validate(validator, this.store.state.values);
315
+ if (!allIssues) {
316
+ this.persisted.setState((current) => {
317
+ return {
318
+ ...current,
319
+ errors: {},
320
+ status: {
321
+ ...current.status,
322
+ validating: false
323
+ }
324
+ };
325
+ });
326
+ return [];
327
+ }
328
+ const fields = field ? Array.isArray(field) ? field : [field] : void 0;
329
+ const related = fields?.flatMap((field$1) => this.options.related?.[field$1] ?? []) ?? [];
330
+ const affected = [...fields ?? [], ...related];
331
+ const issues = allIssues.filter((issue) => {
332
+ const path = issue.path?.join(".") ?? "root";
333
+ return !fields || affected.some((key) => path.startsWith(key));
334
+ });
335
+ const errors = issues.reduce((acc, issue) => {
336
+ const path = issue.path?.join(".") ?? "root";
337
+ return {
338
+ ...acc,
339
+ [path]: [...acc[path] ?? [], issue]
340
+ };
341
+ }, {});
342
+ this.persisted.setState((current) => {
343
+ const existing = { ...current.errors };
344
+ for (const key of affected) delete existing[key];
345
+ return {
346
+ ...current,
347
+ errors: {
348
+ ...fields ? existing : {},
349
+ ...errors
350
+ }
351
+ };
352
+ });
353
+ this.setStatus({ validating: false });
354
+ return issues;
355
+ };
356
+ };
357
+
358
+ //#endregion
359
+ //#region src/form-field-api.ts
360
+ var FormFieldApi = class {
361
+ constructor(context) {
362
+ this.context = context;
363
+ }
364
+ /**
365
+ * Changes the value of a specific field with optional control over side effects.
366
+ * @param name - The name of the field to change
367
+ * @param value - The new value to set for the field
368
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
369
+ */
370
+ change = (name, updater, options) => {
371
+ const shouldDirty = options?.should?.dirty !== false;
372
+ const shouldTouch = options?.should?.touch !== false;
373
+ const shouldValidate = options?.should?.validate !== false;
374
+ this.context.persisted.setState((current) => {
375
+ const value = get(current.values, stringToPath(name));
376
+ const values = setPath(current.values, stringToPath(name), update(updater, value));
377
+ return {
378
+ ...current,
379
+ values
380
+ };
381
+ });
382
+ if (shouldValidate) this.context.validate(name, { type: "change" });
383
+ batch(() => {
384
+ if (shouldDirty) this.context.setFieldMeta(name, { dirty: true });
385
+ if (shouldTouch) this.context.setFieldMeta(name, { touched: true });
386
+ });
387
+ };
388
+ focus = (name) => {
389
+ const ref = this.context.store.state.refs[name];
390
+ if (ref) ref.focus();
391
+ this.context.setFieldMeta(name, { touched: true });
392
+ this.context.validate(name, { type: "focus" });
393
+ };
394
+ blur = (name) => {
395
+ const ref = this.context.store.state.refs[name];
396
+ if (ref) ref.blur();
397
+ this.context.setFieldMeta(name, { blurred: true });
398
+ this.context.validate(name, { type: "blur" });
399
+ };
400
+ get = (name) => {
401
+ return get(this.context.store.state.values, stringToPath(name));
402
+ };
403
+ meta = (name) => {
404
+ const meta = this.context.store.state.fields[name];
405
+ if (meta) return meta;
406
+ const updated = this.context.buildFieldMeta(name, void 0, this.context.store.state.values, this.context.store.state.errors);
407
+ this.context.setFieldMeta(name, updated);
408
+ return updated;
409
+ };
410
+ register = (name) => {
411
+ return (element) => {
412
+ if (!element) return;
413
+ this.context.persisted.setState((current) => {
414
+ return {
415
+ ...current,
416
+ refs: {
417
+ ...current.refs,
418
+ [name]: element
419
+ }
420
+ };
421
+ });
422
+ };
423
+ };
424
+ errors = (name) => {
425
+ return this.context.store.state.errors[name] ?? [];
426
+ };
427
+ setErrors = (name, errors, options) => {
428
+ this.context.persisted.setState((current) => {
429
+ const existing = current.errors[name] ?? [];
430
+ let updated;
431
+ switch (options?.mode) {
432
+ case "append":
433
+ updated = [...existing, ...errors];
434
+ break;
435
+ case "keep":
436
+ updated = existing.length > 0 ? existing : errors;
437
+ break;
438
+ case "replace":
439
+ default:
440
+ updated = errors;
441
+ break;
442
+ }
443
+ return {
444
+ ...current,
445
+ errors: {
446
+ ...current.errors,
447
+ [name]: updated
448
+ }
449
+ };
450
+ });
451
+ };
452
+ reset = (name, options) => {
453
+ const path = stringToPath(name);
454
+ const defaultValue = get(this.context.options.defaultValues, path);
455
+ const value = options?.value ?? defaultValue;
456
+ this.context.persisted.setState((current) => {
457
+ const values = setPath(current.values, path, value);
458
+ const fields = { ...current.fields };
459
+ const refs = { ...current.refs };
460
+ const errors = { ...current.errors };
461
+ if (options?.meta) fields[name] = {
462
+ ...options?.keep?.meta ? fields[name] ?? defaultMeta : defaultMeta,
463
+ ...options.meta
464
+ };
465
+ else if (!options?.keep?.meta) delete fields[name];
466
+ if (!options?.keep?.refs) delete refs[name];
467
+ if (!options?.keep?.errors) delete errors[name];
468
+ return {
469
+ ...current,
470
+ values,
471
+ fields,
472
+ refs,
473
+ errors
474
+ };
475
+ });
476
+ };
477
+ };
478
+
479
+ //#endregion
480
+ //#region src/form-api.ts
481
+ var FormApi = class {
482
+ context;
483
+ field;
484
+ array;
485
+ constructor(options) {
486
+ this.context = new FormContextApi(options);
487
+ this.field = new FormFieldApi(this.context);
488
+ this.array = new FormArrayFieldApi({
489
+ field: this.field,
490
+ context: this.context
491
+ });
492
+ }
493
+ "~mount" = () => {
494
+ return this.context.store.mount();
495
+ };
496
+ "~update" = (options) => {
497
+ this.context.options = options;
498
+ };
499
+ store = () => {
500
+ return this.context.store;
501
+ };
502
+ status = () => {
503
+ return this.context.store.state.status;
504
+ };
505
+ values = () => {
506
+ return this.context.store.state.values;
507
+ };
508
+ options = () => {
509
+ return this.context.options;
510
+ };
511
+ get validate() {
512
+ return this.context.validate;
513
+ }
514
+ submit = (onSuccess, onError) => async () => {
515
+ this.context.setStatus({
516
+ submitting: true,
517
+ dirty: true
518
+ });
519
+ const issues = await this.context.validate(void 0, { type: "submit" });
520
+ const valid = issues.length === 0;
521
+ if (valid) await onSuccess(this.context.store.state.values, this);
522
+ else await onError?.(issues, this);
523
+ this.context.setStatus({
524
+ submits: this.context.persisted.state.status.submits + 1,
525
+ submitting: false,
526
+ successful: valid
527
+ });
528
+ };
529
+ reset = (options) => {
530
+ this.context.persisted.setState((current) => {
531
+ return {
532
+ values: options?.values ?? this.context.options.defaultValues,
533
+ fields: options?.keep?.fields ? current.fields : {},
534
+ refs: options?.keep?.refs ? current.refs : {},
535
+ errors: options?.keep?.errors ? current.errors : {},
536
+ status: {
537
+ ...defaultStatus,
538
+ ...options?.status
539
+ }
540
+ };
541
+ });
542
+ };
543
+ };
544
+
545
+ //#endregion
546
+ //#region src/field-api.ts
547
+ var FieldApi = class {
548
+ _options;
549
+ form;
550
+ _store;
551
+ constructor(options) {
552
+ this._options = options;
553
+ this.form = options.form;
554
+ this._store = new Derived({
555
+ deps: [this.form.store()],
556
+ fn: ({ prevVal }) => {
557
+ const previous = prevVal;
558
+ const updated = {
559
+ value: this.form.field.get(this._options.name),
560
+ defaultValue: get(this.form.options().defaultValues, stringToPath(this._options.name)),
561
+ meta: this.form.field.meta(this._options.name),
562
+ errors: this.form.field.errors(this._options.name)
563
+ };
564
+ if (previous && isDeepEqual(previous, updated)) return previous;
565
+ return updated;
566
+ }
567
+ });
568
+ }
569
+ "~mount" = () => {
570
+ return this._store.mount();
571
+ };
572
+ "~update" = (options) => {
573
+ this._options = options;
574
+ };
575
+ options = () => {
576
+ return this._options;
577
+ };
578
+ store = () => {
579
+ return this._store;
580
+ };
581
+ state = () => {
582
+ return this._store.state;
583
+ };
584
+ focus = () => {
585
+ return this.form.field.focus(this._options.name);
586
+ };
587
+ blur = () => {
588
+ return this.form.field.blur(this._options.name);
589
+ };
590
+ /**
591
+ * Changes the value of this field with optional control over side effects.
592
+ * @param value - The new value to set for the field
593
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
594
+ */
595
+ change = (value, options) => {
596
+ return this.form.field.change(this._options.name, value, options);
597
+ };
598
+ register = () => this.form.field.register(this._options.name);
599
+ /**
600
+ * Validates this specific field using the specified validation type.
601
+ * @param options - Optional validation options specifying the validation type ('change' | 'submit' | 'blur' | 'focus')
602
+ * @returns Promise resolving to an array of validation issues for this field
603
+ */
604
+ validate = (options) => {
605
+ return this.form.validate(this._options.name, options);
606
+ };
607
+ /**
608
+ * Resets this field to its default value and optionally resets metadata and errors.
609
+ * @param options - Reset options for controlling what gets reset and what gets kept
610
+ */
611
+ reset = (options) => {
612
+ return this.form.field.reset(this._options.name, options);
613
+ };
614
+ /**
615
+ * Sets validation errors for this specific field.
616
+ * @param errors - Array of validation errors to set
617
+ * @param mode - How to handle existing errors: 'replace' (default), 'append', or 'keep'
618
+ */
619
+ setErrors = (errors, options) => {
620
+ return this.form.field.setErrors(this._options.name, errors, options);
621
+ };
622
+ };
623
+ const createFieldApi = (options) => {
624
+ return new FieldApi(options);
625
+ };
626
+
627
+ //#endregion
628
+ //#region src/array-field-api.ts
629
+ var ArrayFieldApi = class {
630
+ field;
631
+ constructor(options) {
632
+ this.field = new FieldApi(options);
633
+ }
634
+ get _options() {
635
+ return this.field.options();
636
+ }
637
+ "~mount" = () => {
638
+ return this.field.store().mount();
639
+ };
640
+ "~update" = (options) => {
641
+ this.field["~update"](options);
642
+ };
643
+ store = () => {
644
+ return this.field.store();
645
+ };
646
+ state = () => {
647
+ return this.field.store().state;
648
+ };
649
+ /**
650
+ * Appends a new item to the end of the array.
651
+ * @param value - The value to append to the array
652
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
653
+ */
654
+ append = (value, options) => {
655
+ return this._options.form.array.append(this._options.name, value, options);
656
+ };
657
+ /**
658
+ * Prepends a new item to the beginning of the array.
659
+ * @param value - The value to prepend to the array
660
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
661
+ */
662
+ prepend = (value, options) => {
663
+ return this._options.form.array.prepend(this._options.name, value, options);
664
+ };
665
+ /**
666
+ * Inserts a new item at the specified index in the array.
667
+ * @param index - The index at which to insert the value
668
+ * @param value - The value to insert into the array
669
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
670
+ */
671
+ insert = (index, value, options) => {
672
+ return this._options.form.array.insert(this._options.name, index, value, options);
673
+ };
674
+ /**
675
+ * Updates an item at the specified index in the array.
676
+ * @param index - The index of the item to update
677
+ * @param value - The new value or updater function
678
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
679
+ */
680
+ update = (index, value, options) => {
681
+ return this._options.form.array.update(this._options.name, index, value, options);
682
+ };
683
+ /**
684
+ * Removes an item at the specified index from the array.
685
+ * @param index - The index of the item to remove
686
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
687
+ */
688
+ remove = (index, options) => {
689
+ return this._options.form.array.remove(this._options.name, index, options);
690
+ };
691
+ /**
692
+ * Swaps two items in the array by their indices.
693
+ * @param from - The index of the first item
694
+ * @param to - The index of the second item
695
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
696
+ */
697
+ swap = (from, to, options) => {
698
+ return this._options.form.array.swap(this._options.name, from, to, options);
699
+ };
700
+ /**
701
+ * Moves an item from one index to another in the array.
702
+ * @param from - The index of the item to move
703
+ * @param to - The target index
704
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
705
+ */
706
+ move = (from, to, options) => {
707
+ return this._options.form.array.move(this._options.name, from, to, options);
708
+ };
709
+ /**
710
+ * Replaces the entire array with a new value.
711
+ * @param value - The new array value or updater function
712
+ * @param options - Optional configuration for controlling validation, dirty state, and touched state
713
+ */
714
+ replace = (value, options) => {
715
+ return this._options.form.array.replace(this._options.name, value, options);
716
+ };
717
+ /**
718
+ * Validates this specific array field using the specified validation type.
719
+ * @param options - Optional validation options specifying the validation type ('change' | 'submit' | 'blur' | 'focus')
720
+ * @returns Promise resolving to an array of validation issues for this field
721
+ */
722
+ validate = (options) => {
723
+ return this._options.form.validate(this._options.name, options);
724
+ };
725
+ /**
726
+ * Resets this array field to its default value and optionally resets metadata and errors.
727
+ * @param options - Reset options for controlling what gets reset and what gets kept
728
+ */
729
+ reset = (options) => {
730
+ return this._options.form.field.reset(this._options.name, options);
731
+ };
732
+ /**
733
+ * Sets validation errors for this specific array field.
734
+ * @param errors - Array of validation errors to set
735
+ * @param mode - How to handle existing errors: 'replace' (default), 'append', or 'keep'
736
+ */
737
+ setErrors = (errors, options) => {
738
+ return this._options.form.field.setErrors(this._options.name, errors, options);
739
+ };
740
+ };
741
+ const createArrayFieldApi = (options) => {
742
+ return new ArrayFieldApi(options);
743
+ };
744
+
745
+ //#endregion
746
+ export { ArrayFieldApi, FieldApi, FormApi, createArrayFieldApi, createFieldApi };
747
+ //# sourceMappingURL=index.js.map