@formisch/vue 0.7.6 → 0.9.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/README.md +8 -1
- package/dist/index.d.ts +230 -62
- package/dist/index.js +227 -96
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Formisch is also available for [Preact][formisch-preact], [Qwik][formisch-qwik],
|
|
|
9
9
|
- Small bundle size starting at 2.5 kB
|
|
10
10
|
- Schema-based validation with Valibot
|
|
11
11
|
- Type safety with autocompletion in editor
|
|
12
|
+
- Open source and fully tested with 100 % coverage
|
|
12
13
|
- It's fast – DOM updates are fine-grained
|
|
13
14
|
- Minimal, readable and well thought out API
|
|
14
15
|
- Supports all native HTML form fields
|
|
@@ -53,7 +54,13 @@ In addition, Formisch offers several functions (we call them "methods") that can
|
|
|
53
54
|
|
|
54
55
|
## Comparison
|
|
55
56
|
|
|
56
|
-
What makes Formisch unique is its framework-agnostic core, which is fully native to the framework you are using. It works by inserting framework-specific reactivity blocks when the core package is built
|
|
57
|
+
What makes Formisch unique is its framework-agnostic core, which is fully native to the framework you are using. It works by inserting framework-specific reactivity blocks when the core package is built, giving you native performance for any UI update. A modular methods API keeps bundles starting at just ~2.5 kB by only including the methods you import, and end-to-end type safety covers deeply nested paths and field arrays with TypeScript inference that stays fast even as forms grow.
|
|
58
|
+
|
|
59
|
+
For a side-by-side look at how Formisch compares to VeeValidate, FormKit, and TanStack Form, see the [comparison guide](https://formisch.dev/vue/guides/comparison/).
|
|
60
|
+
|
|
61
|
+
## Vision
|
|
62
|
+
|
|
63
|
+
My vision for Formisch is to create a framework-agnostic platform similar to [Vite](https://vite.dev/), but for forms — a shared core that lets the same mental model and codebase work natively across every modern UI framework.
|
|
57
64
|
|
|
58
65
|
## Partners
|
|
59
66
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
-
import * as
|
|
2
|
+
import * as vue0 from "vue";
|
|
3
3
|
import { ComponentPublicInstance, MaybeRefOrGetter, ShallowRef as Signal } from "vue";
|
|
4
4
|
|
|
5
5
|
//#region ../../packages/core/dist/index.vue.d.ts
|
|
@@ -9,9 +9,33 @@ import { ComponentPublicInstance, MaybeRefOrGetter, ShallowRef as Signal } from
|
|
|
9
9
|
* Schema type.
|
|
10
10
|
*/
|
|
11
11
|
type Schema = v.GenericSchema | v.GenericSchemaAsync;
|
|
12
|
+
/**
|
|
13
|
+
* Object schema type.
|
|
14
|
+
*/
|
|
15
|
+
type ObjectSchema = v.LooseObjectSchema<v.ObjectEntries, v.ErrorMessage<v.LooseObjectIssue> | undefined> | v.ObjectSchema<v.ObjectEntries, v.ErrorMessage<v.ObjectIssue> | undefined> | v.StrictObjectSchema<v.ObjectEntries, v.ErrorMessage<v.StrictObjectIssue> | undefined> | v.VariantSchema<string, v.VariantOptions<string>, v.ErrorMessage<v.VariantIssue> | undefined>;
|
|
16
|
+
/**
|
|
17
|
+
* Object schema async type.
|
|
18
|
+
*/
|
|
19
|
+
type ObjectSchemaAsync = v.LooseObjectSchemaAsync<v.ObjectEntriesAsync, v.ErrorMessage<v.LooseObjectIssue> | undefined> | v.ObjectSchemaAsync<v.ObjectEntriesAsync, v.ErrorMessage<v.ObjectIssue> | undefined> | v.StrictObjectSchemaAsync<v.ObjectEntriesAsync, v.ErrorMessage<v.StrictObjectIssue> | undefined> | v.VariantSchemaAsync<string, v.VariantOptionsAsync<string>, v.ErrorMessage<v.VariantIssue> | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Object root schema type.
|
|
22
|
+
*/
|
|
23
|
+
type ObjectRootSchema = ObjectSchema | v.IntersectSchema<ObjectSchema[], v.ErrorMessage<v.IntersectIssue> | undefined> | v.UnionSchema<ObjectSchema[], v.ErrorMessage<v.UnionIssue<v.BaseIssue<unknown>>> | undefined>;
|
|
24
|
+
/**
|
|
25
|
+
* Object root schema async type.
|
|
26
|
+
*/
|
|
27
|
+
type ObjectRootSchemaAsync = ObjectSchemaAsync | v.IntersectSchemaAsync<(ObjectSchema | ObjectSchemaAsync)[], v.ErrorMessage<v.IntersectIssue> | undefined> | v.UnionSchemaAsync<(ObjectSchema | ObjectSchemaAsync)[], v.ErrorMessage<v.UnionIssue<v.BaseIssue<unknown>>> | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Form schema type.
|
|
30
|
+
*
|
|
31
|
+
* Hint: Forms must have an object root, so only object schemas (sync or async),
|
|
32
|
+
* combinators (intersect, union, variant) whose options resolve to objects, and
|
|
33
|
+
* `lazy` schemas wrapping any of these are allowed at the top level. Use
|
|
34
|
+
* {@link Schema} for nested field schemas.
|
|
35
|
+
*/
|
|
36
|
+
type FormSchema = ObjectRootSchema | ObjectRootSchemaAsync | v.LazySchema<ObjectRootSchema> | v.LazySchemaAsync<ObjectRootSchema | ObjectRootSchemaAsync>;
|
|
12
37
|
//#endregion
|
|
13
38
|
//#region src/types/signal/signal.d.ts
|
|
14
|
-
|
|
15
39
|
/**
|
|
16
40
|
* Batch interface.
|
|
17
41
|
*/
|
|
@@ -40,6 +64,13 @@ interface InternalBaseStore {
|
|
|
40
64
|
schema: Schema;
|
|
41
65
|
/**
|
|
42
66
|
* The initial elements of the field.
|
|
67
|
+
*
|
|
68
|
+
* Hint: This may look unused, but do not remove it. `copyItemState` and
|
|
69
|
+
* `swapItemState` move the `elements` reference between field stores when
|
|
70
|
+
* array items are inserted, moved, removed or swapped, and `reset` restores
|
|
71
|
+
* each field's original element via `elements = initialElements`. Without it,
|
|
72
|
+
* focus and file reset target the wrong element after a reorder followed by a
|
|
73
|
+
* reset.
|
|
43
74
|
*/
|
|
44
75
|
initialElements: FieldElement[];
|
|
45
76
|
/**
|
|
@@ -217,7 +248,7 @@ type ValidationMode = "initial" | "touch" | "input" | "change" | "blur" | "submi
|
|
|
217
248
|
/**
|
|
218
249
|
* Form config interface.
|
|
219
250
|
*/
|
|
220
|
-
interface FormConfig<TSchema extends
|
|
251
|
+
interface FormConfig<TSchema extends FormSchema = FormSchema> {
|
|
221
252
|
/**
|
|
222
253
|
* The schema of the form.
|
|
223
254
|
*/
|
|
@@ -238,7 +269,7 @@ interface FormConfig<TSchema extends Schema = Schema> {
|
|
|
238
269
|
/**
|
|
239
270
|
* Internal form store interface.
|
|
240
271
|
*/
|
|
241
|
-
interface InternalFormStore<TSchema extends
|
|
272
|
+
interface InternalFormStore<TSchema extends FormSchema = FormSchema> extends InternalObjectStore {
|
|
242
273
|
/**
|
|
243
274
|
* The element of the form.
|
|
244
275
|
*/
|
|
@@ -275,7 +306,7 @@ interface InternalFormStore<TSchema extends Schema = Schema> extends InternalObj
|
|
|
275
306
|
/**
|
|
276
307
|
* Base form store interface.
|
|
277
308
|
*/
|
|
278
|
-
interface BaseFormStore<TSchema extends
|
|
309
|
+
interface BaseFormStore<TSchema extends FormSchema = FormSchema> {
|
|
279
310
|
/**
|
|
280
311
|
* The internal form store.
|
|
281
312
|
*
|
|
@@ -286,11 +317,11 @@ interface BaseFormStore<TSchema extends Schema = Schema> {
|
|
|
286
317
|
/**
|
|
287
318
|
* Submit handler type.
|
|
288
319
|
*/
|
|
289
|
-
type SubmitHandler<TSchema extends
|
|
320
|
+
type SubmitHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>) => MaybePromise<unknown>;
|
|
290
321
|
/**
|
|
291
322
|
* Submit event handler type.
|
|
292
323
|
*/
|
|
293
|
-
type SubmitEventHandler<TSchema extends
|
|
324
|
+
type SubmitEventHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
|
|
294
325
|
//#endregion
|
|
295
326
|
//#region src/types/path/path.d.ts
|
|
296
327
|
/**
|
|
@@ -361,7 +392,10 @@ type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExa
|
|
|
361
392
|
*/
|
|
362
393
|
type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey, ...infer TRest extends Path] ? TKey extends ExactKeysOf<ExactRequired<TValue>> ? PathValue<PropertiesOf<ExactRequired<TValue>>[TKey], TRest> : unknown : TValue;
|
|
363
394
|
/**
|
|
364
|
-
* Checks whether a value is
|
|
395
|
+
* Checks whether a value is a dynamic array or contains one anywhere in its
|
|
396
|
+
* shape. A fixed-length tuple is not itself a dynamic array, but it counts when
|
|
397
|
+
* it contains one, so paths can still navigate through tuples to reach nested
|
|
398
|
+
* arrays.
|
|
365
399
|
*
|
|
366
400
|
* Hint: The inner conditionals (`TValue extends readonly unknown[]` and
|
|
367
401
|
* `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
|
|
@@ -372,7 +406,7 @@ type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey,
|
|
|
372
406
|
* `true extends ...`, which is `true` whenever at least one union member
|
|
373
407
|
* contributed `true`.
|
|
374
408
|
*/
|
|
375
|
-
type IsOrHasArray<TValue> = true extends (IsAny<TValue> extends true ? false : TValue extends readonly unknown[] ? true : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<TValue[TKey]> }[keyof TValue] : false) ? true : false;
|
|
409
|
+
type IsOrHasArray<TValue> = true extends (IsAny<TValue> extends true ? false : TValue extends readonly unknown[] ? number extends TValue["length"] ? true : IsOrHasArray<TValue[number]> : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<TValue[TKey]> }[keyof TValue] : false) ? true : false;
|
|
376
410
|
/**
|
|
377
411
|
* Extracts the exact keys of a tuple, array or object that contain arrays.
|
|
378
412
|
*/
|
|
@@ -387,12 +421,34 @@ type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: T
|
|
|
387
421
|
/**
|
|
388
422
|
* Lazily evaluates only the first valid array path segment based on the given value.
|
|
389
423
|
*/
|
|
390
|
-
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? TValidPath : readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOfArrayPath<TValue>, ...infer TPathRest extends Path] ? LazyArrayPath<Required<PropertiesOfArrayPath<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOfArrayPath<TValue>> extends false ? readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : never;
|
|
424
|
+
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? number extends TValue["length"] ? TValidPath : IsNever<ExactKeysOfArrayPath<TValue>> extends false ? readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : never : readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOfArrayPath<TValue>, ...infer TPathRest extends Path] ? LazyArrayPath<Required<PropertiesOfArrayPath<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOfArrayPath<TValue>> extends false ? readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : never;
|
|
391
425
|
/**
|
|
392
426
|
* Returns the path if valid, otherwise the first possible valid array path
|
|
393
427
|
* based on the given value.
|
|
394
428
|
*/
|
|
395
429
|
type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
|
|
430
|
+
/**
|
|
431
|
+
* Recursive helper for `DirtyPath` that prepends `TKey` to each deeper path,
|
|
432
|
+
* or falls through to `never` when the child is not an object.
|
|
433
|
+
*/
|
|
434
|
+
type DeepDirtyPath<TChild, TKey$1 extends PathKey, TDepth extends 0[]> = TChild extends Record<PropertyKey, unknown> ? readonly [TKey$1, ...DirtyPath<TChild, [...TDepth, 0]>] : never;
|
|
435
|
+
/**
|
|
436
|
+
* Returns the union of all `RequiredPath`s that `getDirtyPaths` can emit
|
|
437
|
+
* for a given input type. Object fields contribute their own path and the
|
|
438
|
+
* paths of their descendants; arrays and tuples are atomic and contribute
|
|
439
|
+
* only their own path, because dirty arrays are returned as complete units.
|
|
440
|
+
*
|
|
441
|
+
* Narrowing is exact for the first 5 levels of nesting; deeper paths fall
|
|
442
|
+
* back to `RequiredPath` to keep the result a complete superset of any
|
|
443
|
+
* path the runtime can address.
|
|
444
|
+
*
|
|
445
|
+
* Hint: Arrays and tuples are atomic because they don't structurally
|
|
446
|
+
* extend `Record<PropertyKey, unknown>` and so fall through to `never`
|
|
447
|
+
* via `DeepDirtyPath` — no explicit array check is needed. `TDepth` is
|
|
448
|
+
* a tuple-length counter capped at 5 to bound TypeScript instantiation
|
|
449
|
+
* cost.
|
|
450
|
+
*/
|
|
451
|
+
type DirtyPath<TValue, TDepth extends 0[] = []> = TDepth["length"] extends 5 ? RequiredPath : TValue extends Record<PropertyKey, unknown> ? { [TKey in ExactKeysOf<TValue>]: readonly [TKey] | DeepDirtyPath<NonNullable<PropertiesOf<TValue>[TKey]>, TKey, TDepth> }[ExactKeysOf<TValue>] : never;
|
|
396
452
|
//#endregion
|
|
397
453
|
//#region src/array/copyItemState/copyItemState.d.ts
|
|
398
454
|
/**
|
|
@@ -411,21 +467,21 @@ type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArra
|
|
|
411
467
|
/**
|
|
412
468
|
* Focus field config interface.
|
|
413
469
|
*/
|
|
414
|
-
interface FocusFieldConfig<TSchema extends
|
|
470
|
+
interface FocusFieldConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
415
471
|
/**
|
|
416
472
|
* The path to the field to focus.
|
|
417
473
|
*/
|
|
418
474
|
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
419
475
|
}
|
|
420
476
|
/**
|
|
421
|
-
* Focuses the first input element of a field. This is useful for
|
|
477
|
+
* Focuses the first focusable input element of a field. This is useful for
|
|
422
478
|
* programmatically setting focus to a specific field, such as after
|
|
423
479
|
* validation errors or user interactions.
|
|
424
480
|
*
|
|
425
481
|
* @param form The form store containing the field.
|
|
426
482
|
* @param config The focus field configuration.
|
|
427
483
|
*/
|
|
428
|
-
declare function focus<TSchema extends
|
|
484
|
+
declare function focus<TSchema extends FormSchema, TFieldPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: FocusFieldConfig<TSchema, TFieldPath>): void;
|
|
429
485
|
//#endregion
|
|
430
486
|
//#region src/getAllErrors/getAllErrors.d.ts
|
|
431
487
|
/**
|
|
@@ -439,6 +495,93 @@ declare function focus<TSchema extends Schema, TFieldPath extends RequiredPath>(
|
|
|
439
495
|
*/
|
|
440
496
|
declare function getAllErrors(form: BaseFormStore): [string, ...string[]] | null;
|
|
441
497
|
//#endregion
|
|
498
|
+
//#region src/getDirtyInput/getDirtyInput.d.ts
|
|
499
|
+
/**
|
|
500
|
+
* Get form dirty input config interface.
|
|
501
|
+
*/
|
|
502
|
+
interface GetFormDirtyInputConfig {
|
|
503
|
+
/**
|
|
504
|
+
* The path to a field. Leave undefined to get the dirty input of the entire
|
|
505
|
+
* form.
|
|
506
|
+
*/
|
|
507
|
+
readonly path?: undefined;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Get field dirty input config interface.
|
|
511
|
+
*/
|
|
512
|
+
interface GetFieldDirtyInputConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
513
|
+
/**
|
|
514
|
+
* The path to the field to retrieve the dirty input from.
|
|
515
|
+
*/
|
|
516
|
+
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Retrieves only the dirty input values of a specific field or the entire
|
|
520
|
+
* form. Arrays are treated as atomic and returned in full if any item is
|
|
521
|
+
* dirty, while object keys without a dirty descendant are omitted. Returns
|
|
522
|
+
* `undefined` if no field in the inspected subtree is dirty.
|
|
523
|
+
*
|
|
524
|
+
* @param form The form store to retrieve dirty input from.
|
|
525
|
+
*
|
|
526
|
+
* @returns The dirty input of the form or specified field, or `undefined`.
|
|
527
|
+
*/
|
|
528
|
+
declare function getDirtyInput<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): DeepPartial<v.InferInput<TSchema>> | undefined;
|
|
529
|
+
/**
|
|
530
|
+
* Retrieves only the dirty input values of a specific field or the entire
|
|
531
|
+
* form. Arrays are treated as atomic and returned in full if any item is
|
|
532
|
+
* dirty, while object keys without a dirty descendant are omitted. Returns
|
|
533
|
+
* `undefined` if no field in the inspected subtree is dirty.
|
|
534
|
+
*
|
|
535
|
+
* @param form The form store to retrieve dirty input from.
|
|
536
|
+
* @param config The get dirty input configuration.
|
|
537
|
+
*
|
|
538
|
+
* @returns The dirty input of the form or specified field, or `undefined`.
|
|
539
|
+
*/
|
|
540
|
+
declare function getDirtyInput<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldDirtyInputConfig<TSchema, TFieldPath> : GetFormDirtyInputConfig): DeepPartial<TFieldPath extends RequiredPath ? PathValue<v.InferInput<TSchema>, TFieldPath> : v.InferInput<TSchema>> | undefined;
|
|
541
|
+
//#endregion
|
|
542
|
+
//#region src/getDirtyPaths/getDirtyPaths.d.ts
|
|
543
|
+
/**
|
|
544
|
+
* Get form dirty paths config interface.
|
|
545
|
+
*/
|
|
546
|
+
interface GetFormDirtyPathsConfig {
|
|
547
|
+
/**
|
|
548
|
+
* The path to a field. Leave undefined to inspect the entire form.
|
|
549
|
+
*/
|
|
550
|
+
readonly path?: undefined;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Get field dirty paths config interface.
|
|
554
|
+
*/
|
|
555
|
+
interface GetFieldDirtyPathsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
556
|
+
/**
|
|
557
|
+
* The path to the field to inspect.
|
|
558
|
+
*/
|
|
559
|
+
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Returns a list of paths to the dirty fields of a specific field or the
|
|
563
|
+
* entire form. Arrays are treated as atomic and contribute only their own
|
|
564
|
+
* path if any item is dirty, while object branches are recursed into. Returns
|
|
565
|
+
* an empty list if no field in the inspected subtree is dirty.
|
|
566
|
+
*
|
|
567
|
+
* @param form The form store to inspect.
|
|
568
|
+
*
|
|
569
|
+
* @returns The list of paths to the dirty fields.
|
|
570
|
+
*/
|
|
571
|
+
declare function getDirtyPaths<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): DirtyPath<v.InferInput<TSchema>>[];
|
|
572
|
+
/**
|
|
573
|
+
* Returns a list of paths to the dirty fields of a specific field or the
|
|
574
|
+
* entire form. Arrays are treated as atomic and contribute only their own
|
|
575
|
+
* path if any item is dirty, while object branches are recursed into. Returns
|
|
576
|
+
* an empty list if no field in the inspected subtree is dirty.
|
|
577
|
+
*
|
|
578
|
+
* @param form The form store to inspect.
|
|
579
|
+
* @param config The get dirty paths configuration.
|
|
580
|
+
*
|
|
581
|
+
* @returns The list of paths to the dirty fields.
|
|
582
|
+
*/
|
|
583
|
+
declare function getDirtyPaths<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldDirtyPathsConfig<TSchema, TFieldPath> : GetFormDirtyPathsConfig): DirtyPath<v.InferInput<TSchema>>[];
|
|
584
|
+
//#endregion
|
|
442
585
|
//#region src/getErrors/getErrors.d.ts
|
|
443
586
|
/**
|
|
444
587
|
* Get form errors config interface.
|
|
@@ -452,7 +595,7 @@ interface GetFormErrorsConfig {
|
|
|
452
595
|
/**
|
|
453
596
|
* Get field errors config interface.
|
|
454
597
|
*/
|
|
455
|
-
interface GetFieldErrorsConfig<TSchema extends
|
|
598
|
+
interface GetFieldErrorsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
456
599
|
/**
|
|
457
600
|
* The path to the field to retrieve errors from.
|
|
458
601
|
*/
|
|
@@ -467,7 +610,7 @@ interface GetFieldErrorsConfig<TSchema extends Schema, TFieldPath extends Requir
|
|
|
467
610
|
*
|
|
468
611
|
* @returns A non-empty array of error messages, or null if no errors exist.
|
|
469
612
|
*/
|
|
470
|
-
declare function getErrors<TSchema extends
|
|
613
|
+
declare function getErrors<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): [string, ...string[]] | null;
|
|
471
614
|
/**
|
|
472
615
|
* Retrieves error messages from the form. When called without a config,
|
|
473
616
|
* returns form-level errors. When called with a path, returns errors for
|
|
@@ -478,7 +621,7 @@ declare function getErrors<TSchema extends Schema>(form: BaseFormStore<TSchema>)
|
|
|
478
621
|
*
|
|
479
622
|
* @returns A non-empty array of error messages, or null if no errors exist.
|
|
480
623
|
*/
|
|
481
|
-
declare function getErrors<TSchema extends
|
|
624
|
+
declare function getErrors<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldErrorsConfig<TSchema, TFieldPath> : GetFormErrorsConfig): [string, ...string[]] | null;
|
|
482
625
|
//#endregion
|
|
483
626
|
//#region src/getInput/getInput.d.ts
|
|
484
627
|
/**
|
|
@@ -493,7 +636,7 @@ interface GetFormInputConfig {
|
|
|
493
636
|
/**
|
|
494
637
|
* Get field input config interface.
|
|
495
638
|
*/
|
|
496
|
-
interface GetFieldInputConfig<TSchema extends
|
|
639
|
+
interface GetFieldInputConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
497
640
|
/**
|
|
498
641
|
* The path to the field to retrieve input from.
|
|
499
642
|
*/
|
|
@@ -507,7 +650,7 @@ interface GetFieldInputConfig<TSchema extends Schema, TFieldPath extends Require
|
|
|
507
650
|
*
|
|
508
651
|
* @returns The partial input values of the form or the specified field.
|
|
509
652
|
*/
|
|
510
|
-
declare function getInput<TSchema extends
|
|
653
|
+
declare function getInput<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): PartialValues<v.InferInput<TSchema>>;
|
|
511
654
|
/**
|
|
512
655
|
* Retrieves the current input value of a specific field or the entire form.
|
|
513
656
|
* Returns a partial object as not all fields may have been set.
|
|
@@ -517,7 +660,7 @@ declare function getInput<TSchema extends Schema>(form: BaseFormStore<TSchema>):
|
|
|
517
660
|
*
|
|
518
661
|
* @returns The partial input values of the form or the specified field.
|
|
519
662
|
*/
|
|
520
|
-
declare function getInput<TSchema extends
|
|
663
|
+
declare function getInput<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldInputConfig<TSchema, TFieldPath> : GetFormInputConfig): PartialValues<TFieldPath extends RequiredPath ? PathValue<v.InferInput<TSchema>, TFieldPath> : v.InferInput<TSchema>>;
|
|
521
664
|
//#endregion
|
|
522
665
|
//#region src/handleSubmit/handleSubmit.d.ts
|
|
523
666
|
/**
|
|
@@ -530,7 +673,7 @@ declare function getInput<TSchema extends Schema, TFieldPath extends RequiredPat
|
|
|
530
673
|
*
|
|
531
674
|
* @returns A submit event handler function to attach to the form element.
|
|
532
675
|
*/
|
|
533
|
-
declare function handleSubmit<TSchema extends
|
|
676
|
+
declare function handleSubmit<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, handler: SubmitHandler<TSchema>): () => Promise<void>;
|
|
534
677
|
/**
|
|
535
678
|
* Creates a submit event handler for the form that prevents default browser
|
|
536
679
|
* submission, validates the form input, and calls the provided handler if
|
|
@@ -541,13 +684,13 @@ declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchem
|
|
|
541
684
|
*
|
|
542
685
|
* @returns A submit event handler function to attach to the form element.
|
|
543
686
|
*/
|
|
544
|
-
declare function handleSubmit<TSchema extends
|
|
687
|
+
declare function handleSubmit<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, handler: SubmitEventHandler<TSchema>): (event: SubmitEvent) => Promise<void>;
|
|
545
688
|
//#endregion
|
|
546
689
|
//#region src/insert/insert.d.ts
|
|
547
690
|
/**
|
|
548
691
|
* Insert array field config interface.
|
|
549
692
|
*/
|
|
550
|
-
interface InsertConfig<TSchema extends
|
|
693
|
+
interface InsertConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
|
|
551
694
|
/**
|
|
552
695
|
* The path to the field array to insert into.
|
|
553
696
|
*/
|
|
@@ -568,13 +711,13 @@ interface InsertConfig<TSchema extends Schema, TFieldArrayPath extends RequiredP
|
|
|
568
711
|
* @param form The form store containing the field array.
|
|
569
712
|
* @param config The insert configuration specifying the path, index, and initial value.
|
|
570
713
|
*/
|
|
571
|
-
declare function insert<TSchema extends
|
|
714
|
+
declare function insert<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: InsertConfig<TSchema, TFieldArrayPath>): void;
|
|
572
715
|
//#endregion
|
|
573
716
|
//#region src/move/move.d.ts
|
|
574
717
|
/**
|
|
575
718
|
* Move array field config interface.
|
|
576
719
|
*/
|
|
577
|
-
interface MoveConfig<TSchema extends
|
|
720
|
+
interface MoveConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
|
|
578
721
|
/**
|
|
579
722
|
* The path to the field array to move an item within.
|
|
580
723
|
*/
|
|
@@ -595,13 +738,38 @@ interface MoveConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPat
|
|
|
595
738
|
* @param form The form store containing the field array.
|
|
596
739
|
* @param config The move configuration specifying the path and source/destination indices.
|
|
597
740
|
*/
|
|
598
|
-
declare function move<TSchema extends
|
|
741
|
+
declare function move<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: MoveConfig<TSchema, TFieldArrayPath>): void;
|
|
742
|
+
//#endregion
|
|
743
|
+
//#region src/pickDirty/pickDirty.d.ts
|
|
744
|
+
/**
|
|
745
|
+
* Pick dirty config interface.
|
|
746
|
+
*/
|
|
747
|
+
interface PickDirtyConfig<TValue extends object> {
|
|
748
|
+
/**
|
|
749
|
+
* The value to filter down to its dirty parts. Must be structurally
|
|
750
|
+
* compatible with the form's schema.
|
|
751
|
+
*/
|
|
752
|
+
readonly from: TValue;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Picks only the dirty parts of the given value, using the form's dirty fields
|
|
756
|
+
* as a structural mask. Arrays are treated as atomic and object keys without a
|
|
757
|
+
* dirty descendant are omitted. Returns `undefined` if no field is dirty.
|
|
758
|
+
* Useful for filtering a validated output down to its changed parts before
|
|
759
|
+
* submitting.
|
|
760
|
+
*
|
|
761
|
+
* @param form The form store providing the dirty mask.
|
|
762
|
+
* @param config The pick dirty configuration.
|
|
763
|
+
*
|
|
764
|
+
* @returns The dirty parts of the value, or `undefined`.
|
|
765
|
+
*/
|
|
766
|
+
declare function pickDirty<TSchema extends FormSchema, TValue extends object>(form: BaseFormStore<TSchema>, config: PickDirtyConfig<TValue>): DeepPartial<TValue> | undefined;
|
|
599
767
|
//#endregion
|
|
600
768
|
//#region src/remove/remove.d.ts
|
|
601
769
|
/**
|
|
602
770
|
* Remove array field config interface.
|
|
603
771
|
*/
|
|
604
|
-
interface RemoveConfig<TSchema extends
|
|
772
|
+
interface RemoveConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
|
|
605
773
|
/**
|
|
606
774
|
* The path to the field array to remove an item from.
|
|
607
775
|
*/
|
|
@@ -618,13 +786,13 @@ interface RemoveConfig<TSchema extends Schema, TFieldArrayPath extends RequiredP
|
|
|
618
786
|
* @param form The form store containing the field array.
|
|
619
787
|
* @param config The remove configuration specifying the path and index.
|
|
620
788
|
*/
|
|
621
|
-
declare function remove<TSchema extends
|
|
789
|
+
declare function remove<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: RemoveConfig<TSchema, TFieldArrayPath>): void;
|
|
622
790
|
//#endregion
|
|
623
791
|
//#region src/replace/replace.d.ts
|
|
624
792
|
/**
|
|
625
793
|
* Replace array field config interface.
|
|
626
794
|
*/
|
|
627
|
-
interface ReplaceConfig<TSchema extends
|
|
795
|
+
interface ReplaceConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
|
|
628
796
|
/**
|
|
629
797
|
* The path to the field array to replace an item within.
|
|
630
798
|
*/
|
|
@@ -644,7 +812,7 @@ interface ReplaceConfig<TSchema extends Schema, TFieldArrayPath extends Required
|
|
|
644
812
|
* @param form The form store containing the field array.
|
|
645
813
|
* @param config The replace configuration specifying the path, index, and initial input.
|
|
646
814
|
*/
|
|
647
|
-
declare function replace<TSchema extends
|
|
815
|
+
declare function replace<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: ReplaceConfig<TSchema, TFieldArrayPath>): void;
|
|
648
816
|
//#endregion
|
|
649
817
|
//#region src/reset/reset.d.ts
|
|
650
818
|
/**
|
|
@@ -667,7 +835,7 @@ interface ResetBaseConfig {
|
|
|
667
835
|
/**
|
|
668
836
|
* Reset form config interface.
|
|
669
837
|
*/
|
|
670
|
-
interface ResetFormConfig<TSchema extends
|
|
838
|
+
interface ResetFormConfig<TSchema extends FormSchema> extends ResetBaseConfig {
|
|
671
839
|
/**
|
|
672
840
|
* The path to a field. Leave undefined to reset the entire form.
|
|
673
841
|
*/
|
|
@@ -685,7 +853,7 @@ interface ResetFormConfig<TSchema extends Schema> extends ResetBaseConfig {
|
|
|
685
853
|
/**
|
|
686
854
|
* Reset field config interface.
|
|
687
855
|
*/
|
|
688
|
-
interface ResetFieldConfig<TSchema extends
|
|
856
|
+
interface ResetFieldConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> extends ResetBaseConfig {
|
|
689
857
|
/**
|
|
690
858
|
* The path to the field to reset.
|
|
691
859
|
*/
|
|
@@ -712,7 +880,7 @@ declare function reset(form: BaseFormStore): void;
|
|
|
712
880
|
* @param form The form store to reset.
|
|
713
881
|
* @param config The reset configuration specifying what to reset and what to keep.
|
|
714
882
|
*/
|
|
715
|
-
declare function reset<TSchema extends
|
|
883
|
+
declare function reset<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? ResetFieldConfig<TSchema, TFieldPath> : ResetFormConfig<TSchema>): void;
|
|
716
884
|
//#endregion
|
|
717
885
|
//#region src/setErrors/setErrors.d.ts
|
|
718
886
|
/**
|
|
@@ -731,7 +899,7 @@ interface SetFormErrorsConfig {
|
|
|
731
899
|
/**
|
|
732
900
|
* Set field errors config interface.
|
|
733
901
|
*/
|
|
734
|
-
interface SetFieldErrorsConfig<TSchema extends
|
|
902
|
+
interface SetFieldErrorsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
735
903
|
/**
|
|
736
904
|
* The path to the field to set errors on.
|
|
737
905
|
*/
|
|
@@ -749,13 +917,13 @@ interface SetFieldErrorsConfig<TSchema extends Schema, TFieldPath extends Requir
|
|
|
749
917
|
* @param form The form store to set errors on.
|
|
750
918
|
* @param config The set errors configuration specifying the path and error messages.
|
|
751
919
|
*/
|
|
752
|
-
declare function setErrors<TSchema extends
|
|
920
|
+
declare function setErrors<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? SetFieldErrorsConfig<TSchema, TFieldPath> : SetFormErrorsConfig): void;
|
|
753
921
|
//#endregion
|
|
754
922
|
//#region src/setInput/setInput.d.ts
|
|
755
923
|
/**
|
|
756
924
|
* Set form input config interface.
|
|
757
925
|
*/
|
|
758
|
-
interface SetFormInputConfig<TSchema extends
|
|
926
|
+
interface SetFormInputConfig<TSchema extends FormSchema> {
|
|
759
927
|
/**
|
|
760
928
|
* The path to a field. Leave undefined to set the entire form input.
|
|
761
929
|
*/
|
|
@@ -768,7 +936,7 @@ interface SetFormInputConfig<TSchema extends Schema> {
|
|
|
768
936
|
/**
|
|
769
937
|
* Set field input config interface.
|
|
770
938
|
*/
|
|
771
|
-
interface SetFieldInputConfig<TSchema extends
|
|
939
|
+
interface SetFieldInputConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
|
|
772
940
|
/**
|
|
773
941
|
* The path to the field to set input on.
|
|
774
942
|
*/
|
|
@@ -786,7 +954,7 @@ interface SetFieldInputConfig<TSchema extends Schema, TFieldPath extends Require
|
|
|
786
954
|
* @param form The form store to set input on.
|
|
787
955
|
* @param config The set form input configuration specifying the new input values.
|
|
788
956
|
*/
|
|
789
|
-
declare function setInput<TSchema extends
|
|
957
|
+
declare function setInput<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, config: SetFormInputConfig<TSchema>): void;
|
|
790
958
|
/**
|
|
791
959
|
* Sets the input value of a specific field or the entire form. This updates
|
|
792
960
|
* the field value(s) and triggers validation if required by the form's
|
|
@@ -795,7 +963,7 @@ declare function setInput<TSchema extends Schema>(form: BaseFormStore<TSchema>,
|
|
|
795
963
|
* @param form The form store to set input on.
|
|
796
964
|
* @param config The set input configuration specifying the path and new value.
|
|
797
965
|
*/
|
|
798
|
-
declare function setInput<TSchema extends
|
|
966
|
+
declare function setInput<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? SetFieldInputConfig<TSchema, TFieldPath> : SetFormInputConfig<TSchema>): void;
|
|
799
967
|
//#endregion
|
|
800
968
|
//#region src/submit/submit.d.ts
|
|
801
969
|
/**
|
|
@@ -810,7 +978,7 @@ declare function submit(form: BaseFormStore): void;
|
|
|
810
978
|
/**
|
|
811
979
|
* Swap array field config interface.
|
|
812
980
|
*/
|
|
813
|
-
interface SwapConfig<TSchema extends
|
|
981
|
+
interface SwapConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
|
|
814
982
|
/**
|
|
815
983
|
* The path to the field array to swap items within.
|
|
816
984
|
*/
|
|
@@ -830,7 +998,7 @@ interface SwapConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPat
|
|
|
830
998
|
* @param form The form store containing the field array.
|
|
831
999
|
* @param config The swap configuration specifying the path and indices to swap.
|
|
832
1000
|
*/
|
|
833
|
-
declare function swap<TSchema extends
|
|
1001
|
+
declare function swap<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: SwapConfig<TSchema, TFieldArrayPath>): void;
|
|
834
1002
|
//#endregion
|
|
835
1003
|
//#region src/validate/validate.d.ts
|
|
836
1004
|
/**
|
|
@@ -852,7 +1020,7 @@ interface ValidateFormConfig {
|
|
|
852
1020
|
*
|
|
853
1021
|
* @returns A promise resolving to the validation result.
|
|
854
1022
|
*/
|
|
855
|
-
declare function validate<TSchema extends
|
|
1023
|
+
declare function validate<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, config?: ValidateFormConfig): Promise<v.SafeParseResult<TSchema>>;
|
|
856
1024
|
//#endregion
|
|
857
1025
|
//#endregion
|
|
858
1026
|
//#region src/types/field.d.ts
|
|
@@ -888,7 +1056,7 @@ interface FieldElementProps {
|
|
|
888
1056
|
/**
|
|
889
1057
|
* Field store interface.
|
|
890
1058
|
*/
|
|
891
|
-
interface FieldStore<TSchema extends
|
|
1059
|
+
interface FieldStore<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
|
|
892
1060
|
/**
|
|
893
1061
|
* The path to the field within the form.
|
|
894
1062
|
*/
|
|
@@ -925,7 +1093,7 @@ interface FieldStore<TSchema extends Schema = Schema, TFieldPath extends Require
|
|
|
925
1093
|
/**
|
|
926
1094
|
* Field array store interface.
|
|
927
1095
|
*/
|
|
928
|
-
interface FieldArrayStore<TSchema extends
|
|
1096
|
+
interface FieldArrayStore<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
|
|
929
1097
|
/**
|
|
930
1098
|
* The path to the array field within the form.
|
|
931
1099
|
*/
|
|
@@ -956,7 +1124,7 @@ interface FieldArrayStore<TSchema extends Schema = Schema, TFieldArrayPath exten
|
|
|
956
1124
|
/**
|
|
957
1125
|
* Form store interface.
|
|
958
1126
|
*/
|
|
959
|
-
interface FormStore<TSchema extends
|
|
1127
|
+
interface FormStore<TSchema extends FormSchema = FormSchema> extends BaseFormStore<TSchema> {
|
|
960
1128
|
/**
|
|
961
1129
|
* Whether the form is currently submitting.
|
|
962
1130
|
*/
|
|
@@ -994,7 +1162,7 @@ interface FormStore<TSchema extends Schema = Schema> extends BaseFormStore<TSche
|
|
|
994
1162
|
/**
|
|
995
1163
|
* Field component props interface.
|
|
996
1164
|
*/
|
|
997
|
-
interface FieldProps<TSchema extends
|
|
1165
|
+
interface FieldProps<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
|
|
998
1166
|
/**
|
|
999
1167
|
* The form store to which the field belongs.
|
|
1000
1168
|
*/
|
|
@@ -1004,15 +1172,15 @@ interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends Require
|
|
|
1004
1172
|
*/
|
|
1005
1173
|
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
1006
1174
|
}
|
|
1007
|
-
declare const __VLS_export$2: <TSchema extends
|
|
1008
|
-
props: __VLS_PrettifyLocal$2<FieldProps<TSchema, TFieldPath>> &
|
|
1175
|
+
declare const __VLS_export$2: <TSchema extends FormSchema, TFieldPath extends RequiredPath>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal$2<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
1176
|
+
props: __VLS_PrettifyLocal$2<FieldProps<TSchema, TFieldPath>> & vue0.PublicProps;
|
|
1009
1177
|
expose: (exposed: {}) => void;
|
|
1010
1178
|
attrs: any;
|
|
1011
1179
|
slots: {
|
|
1012
1180
|
default(props: FieldStore<TSchema, TFieldPath>): any;
|
|
1013
1181
|
};
|
|
1014
1182
|
emit: {};
|
|
1015
|
-
}>) =>
|
|
1183
|
+
}>) => vue0.VNode & {
|
|
1016
1184
|
__ctx?: Awaited<typeof __VLS_setup>;
|
|
1017
1185
|
};
|
|
1018
1186
|
declare const _default: typeof __VLS_export$2;
|
|
@@ -1022,7 +1190,7 @@ type __VLS_PrettifyLocal$2<T> = { [K in keyof T as K]: T[K] } & {};
|
|
|
1022
1190
|
/**
|
|
1023
1191
|
* Field array component props interface.
|
|
1024
1192
|
*/
|
|
1025
|
-
interface FieldArrayProps<TSchema extends
|
|
1193
|
+
interface FieldArrayProps<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
|
|
1026
1194
|
/**
|
|
1027
1195
|
* The form store to which the field array belongs.
|
|
1028
1196
|
*/
|
|
@@ -1032,15 +1200,15 @@ interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath exten
|
|
|
1032
1200
|
*/
|
|
1033
1201
|
readonly path: ValidArrayPath<v.InferInput<TSchema>, TFieldArrayPath>;
|
|
1034
1202
|
}
|
|
1035
|
-
declare const __VLS_export$1: <TSchema extends
|
|
1036
|
-
props: __VLS_PrettifyLocal$1<FieldArrayProps<TSchema, TFieldArrayPath>> &
|
|
1203
|
+
declare const __VLS_export$1: <TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal$1<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
1204
|
+
props: __VLS_PrettifyLocal$1<FieldArrayProps<TSchema, TFieldArrayPath>> & vue0.PublicProps;
|
|
1037
1205
|
expose: (exposed: {}) => void;
|
|
1038
1206
|
attrs: any;
|
|
1039
1207
|
slots: {
|
|
1040
1208
|
default(props: FieldArrayStore<TSchema, TFieldArrayPath>): any;
|
|
1041
1209
|
};
|
|
1042
1210
|
emit: {};
|
|
1043
|
-
}>) =>
|
|
1211
|
+
}>) => vue0.VNode & {
|
|
1044
1212
|
__ctx?: Awaited<typeof __VLS_setup>;
|
|
1045
1213
|
};
|
|
1046
1214
|
declare const _default$1: typeof __VLS_export$1;
|
|
@@ -1050,7 +1218,7 @@ type __VLS_PrettifyLocal$1<T> = { [K in keyof T as K]: T[K] } & {};
|
|
|
1050
1218
|
/**
|
|
1051
1219
|
* Form component props interface.
|
|
1052
1220
|
*/
|
|
1053
|
-
interface FormProps<TSchema extends
|
|
1221
|
+
interface FormProps<TSchema extends FormSchema = FormSchema> {
|
|
1054
1222
|
/**
|
|
1055
1223
|
* The form store instance.
|
|
1056
1224
|
*/
|
|
@@ -1060,15 +1228,15 @@ interface FormProps<TSchema extends Schema = Schema> {
|
|
|
1060
1228
|
*/
|
|
1061
1229
|
onSubmit: SubmitEventHandler<TSchema>;
|
|
1062
1230
|
}
|
|
1063
|
-
declare const __VLS_export: <TSchema extends
|
|
1064
|
-
props: __VLS_PrettifyLocal<FormProps<TSchema>> &
|
|
1231
|
+
declare const __VLS_export: <TSchema extends FormSchema = FormSchema>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
1232
|
+
props: __VLS_PrettifyLocal<FormProps<TSchema>> & vue0.PublicProps;
|
|
1065
1233
|
expose: (exposed: {}) => void;
|
|
1066
1234
|
attrs: any;
|
|
1067
1235
|
slots: {
|
|
1068
1236
|
default?: (props: {}) => any;
|
|
1069
1237
|
};
|
|
1070
1238
|
emit: {};
|
|
1071
|
-
}>) =>
|
|
1239
|
+
}>) => vue0.VNode & {
|
|
1072
1240
|
__ctx?: Awaited<typeof __VLS_setup>;
|
|
1073
1241
|
};
|
|
1074
1242
|
declare const _default$2: typeof __VLS_export;
|
|
@@ -1078,7 +1246,7 @@ type __VLS_PrettifyLocal<T> = { [K in keyof T as K]: T[K] } & {};
|
|
|
1078
1246
|
/**
|
|
1079
1247
|
* Use field config interface.
|
|
1080
1248
|
*/
|
|
1081
|
-
interface UseFieldConfig<TSchema extends
|
|
1249
|
+
interface UseFieldConfig<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
|
|
1082
1250
|
/**
|
|
1083
1251
|
* The path to the field within the form schema.
|
|
1084
1252
|
*/
|
|
@@ -1092,13 +1260,13 @@ interface UseFieldConfig<TSchema extends Schema = Schema, TFieldPath extends Req
|
|
|
1092
1260
|
*
|
|
1093
1261
|
* @returns The field store with reactive properties and element props.
|
|
1094
1262
|
*/
|
|
1095
|
-
declare function useField<TSchema extends
|
|
1263
|
+
declare function useField<TSchema extends FormSchema, TFieldPath extends RequiredPath>(form: MaybeRefOrGetter<FormStore<TSchema>>, config: MaybeRefOrGetter<UseFieldConfig<TSchema, TFieldPath>>): FieldStore<TSchema, TFieldPath>;
|
|
1096
1264
|
//#endregion
|
|
1097
1265
|
//#region src/composables/useFieldArray/useFieldArray.d.ts
|
|
1098
1266
|
/**
|
|
1099
1267
|
* Use field array config interface.
|
|
1100
1268
|
*/
|
|
1101
|
-
interface UseFieldArrayConfig<TSchema extends
|
|
1269
|
+
interface UseFieldArrayConfig<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
|
|
1102
1270
|
/**
|
|
1103
1271
|
* The path to the field array within the form schema.
|
|
1104
1272
|
*/
|
|
@@ -1112,7 +1280,7 @@ interface UseFieldArrayConfig<TSchema extends Schema = Schema, TFieldArrayPath e
|
|
|
1112
1280
|
*
|
|
1113
1281
|
* @returns The field array store with reactive properties for array management.
|
|
1114
1282
|
*/
|
|
1115
|
-
declare function useFieldArray<TSchema extends
|
|
1283
|
+
declare function useFieldArray<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: MaybeRefOrGetter<FormStore<TSchema>>, config: MaybeRefOrGetter<UseFieldArrayConfig<TSchema, TFieldArrayPath>>): FieldArrayStore<TSchema, TFieldArrayPath>;
|
|
1116
1284
|
//#endregion
|
|
1117
1285
|
//#region src/composables/useForm/useForm.d.ts
|
|
1118
1286
|
/**
|
|
@@ -1123,6 +1291,6 @@ declare function useFieldArray<TSchema extends Schema, TFieldArrayPath extends R
|
|
|
1123
1291
|
*
|
|
1124
1292
|
* @returns The form store with reactive properties.
|
|
1125
1293
|
*/
|
|
1126
|
-
declare function useForm<TSchema extends
|
|
1294
|
+
declare function useForm<TSchema extends FormSchema>(config: FormConfig<TSchema>): FormStore<TSchema>;
|
|
1127
1295
|
//#endregion
|
|
1128
|
-
export { type DeepPartial, _default as Field, _default$1 as FieldArray, FieldArrayStore, type FieldElement, FieldElementProps, FieldStore, FocusFieldConfig, _default$2 as Form, type FormConfig, FormStore, GetFieldErrorsConfig, GetFieldInputConfig, GetFormErrorsConfig, GetFormInputConfig, InsertConfig, MoveConfig, type PartialValues, type PathValue, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, SetFieldInputConfig, SetFormErrorsConfig, SetFormInputConfig, type SubmitEventHandler, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };
|
|
1296
|
+
export { type DeepPartial, _default as Field, _default$1 as FieldArray, FieldArrayStore, type FieldElement, FieldElementProps, FieldStore, FocusFieldConfig, _default$2 as Form, type FormConfig, type FormSchema, FormStore, GetFieldDirtyInputConfig, GetFieldDirtyPathsConfig, GetFieldErrorsConfig, GetFieldInputConfig, GetFormDirtyInputConfig, GetFormDirtyPathsConfig, GetFormErrorsConfig, GetFormInputConfig, InsertConfig, MoveConfig, type PartialValues, type PathValue, PickDirtyConfig, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, SetFieldInputConfig, SetFormErrorsConfig, SetFormInputConfig, type SubmitEventHandler, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, focus, getAllErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };
|
package/dist/index.js
CHANGED
|
@@ -162,31 +162,45 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
162
162
|
* form reset functionality.
|
|
163
163
|
*
|
|
164
164
|
* @param internalFieldStore The field store to reset.
|
|
165
|
-
* @param
|
|
165
|
+
* @param input The new input value (can be any type including array or object).
|
|
166
|
+
* @param keepStart Whether to keep `startInput` and `startItems` as the dirty
|
|
167
|
+
* baseline instead of resetting them to the new input. Used when a field store
|
|
168
|
+
* is reused for an in-place edit so its dirty state is detected correctly.
|
|
166
169
|
*/
|
|
167
|
-
function resetItemState(internalFieldStore,
|
|
170
|
+
function resetItemState(internalFieldStore, input, keepStart = false) {
|
|
168
171
|
batch(() => {
|
|
169
|
-
|
|
172
|
+
const elements = [];
|
|
173
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) internalFieldStore.initialElements = elements;
|
|
174
|
+
internalFieldStore.elements = elements;
|
|
170
175
|
internalFieldStore.errors.value = null;
|
|
171
176
|
internalFieldStore.isTouched.value = false;
|
|
172
177
|
internalFieldStore.isDirty.value = false;
|
|
173
178
|
if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
|
|
174
|
-
const objectInput =
|
|
175
|
-
internalFieldStore.startInput.value = objectInput;
|
|
179
|
+
const objectInput = input == null ? input : true;
|
|
180
|
+
if (!keepStart) internalFieldStore.startInput.value = objectInput;
|
|
176
181
|
internalFieldStore.input.value = objectInput;
|
|
177
|
-
if (internalFieldStore.kind === "array") if (
|
|
178
|
-
const
|
|
179
|
-
|
|
182
|
+
if (internalFieldStore.kind === "array") if (input) {
|
|
183
|
+
const length = internalFieldStore.schema.type === "array" ? input.length : internalFieldStore.children.length;
|
|
184
|
+
const newItems = Array.from({ length }, createId);
|
|
185
|
+
if (!keepStart) internalFieldStore.startItems.value = newItems;
|
|
180
186
|
internalFieldStore.items.value = newItems;
|
|
181
|
-
|
|
187
|
+
let path;
|
|
188
|
+
for (let index = 0; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], input[index], keepStart);
|
|
189
|
+
else {
|
|
190
|
+
path ??= JSON.parse(internalFieldStore.name);
|
|
191
|
+
internalFieldStore.children[index] = {};
|
|
192
|
+
path.push(index);
|
|
193
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, input[index], path);
|
|
194
|
+
path.pop();
|
|
195
|
+
}
|
|
182
196
|
} else {
|
|
183
|
-
internalFieldStore.startItems.value = [];
|
|
197
|
+
if (!keepStart) internalFieldStore.startItems.value = [];
|
|
184
198
|
internalFieldStore.items.value = [];
|
|
185
199
|
}
|
|
186
|
-
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key],
|
|
200
|
+
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
|
|
187
201
|
} else {
|
|
188
|
-
internalFieldStore.startInput.value =
|
|
189
|
-
internalFieldStore.input.value =
|
|
202
|
+
if (!keepStart) internalFieldStore.startInput.value = input;
|
|
203
|
+
internalFieldStore.input.value = input;
|
|
190
204
|
}
|
|
191
205
|
});
|
|
192
206
|
}
|
|
@@ -253,20 +267,67 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
|
253
267
|
});
|
|
254
268
|
}
|
|
255
269
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
270
|
+
* Focuses the first focusable element of a field store. The elements are tried
|
|
271
|
+
* in order and the first one that actually receives focus wins, so detached,
|
|
272
|
+
* disabled or hidden elements are skipped. The browser decides focusability,
|
|
273
|
+
* which is read back via the element's root `activeElement` so elements in a
|
|
274
|
+
* shadow root or another document are handled correctly.
|
|
259
275
|
*
|
|
260
|
-
*
|
|
276
|
+
* Hint: A `display: none` or `hidden` element is correctly skipped in real
|
|
277
|
+
* browsers, but jsdom has no layout and focuses it anyway, so that case cannot
|
|
278
|
+
* be covered by unit tests.
|
|
261
279
|
*
|
|
262
|
-
* @
|
|
280
|
+
* @param internalFieldStore The field store to focus.
|
|
281
|
+
*
|
|
282
|
+
* @returns Whether an element was focused.
|
|
283
|
+
*/
|
|
284
|
+
function focusFieldElement(internalFieldStore) {
|
|
285
|
+
for (const element of internalFieldStore.elements) {
|
|
286
|
+
element.focus();
|
|
287
|
+
if (element.getRootNode().activeElement === element) return true;
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Returns whether the specified boolean property is true for the field store
|
|
293
|
+
* or any of its nested children. Recursively checks arrays and objects.
|
|
294
|
+
*
|
|
295
|
+
* @param internalFieldStore The field store to check.
|
|
296
|
+
* @param type The boolean property type to check.
|
|
297
|
+
*
|
|
298
|
+
* @returns Whether the property is true.
|
|
263
299
|
*/
|
|
264
300
|
/* @__NO_SIDE_EFFECTS__ */
|
|
265
|
-
function
|
|
301
|
+
function getFieldBool(internalFieldStore, type) {
|
|
302
|
+
if (internalFieldStore[type].value) return true;
|
|
303
|
+
if (internalFieldStore.kind === "array") {
|
|
304
|
+
for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
if (internalFieldStore.kind == "object") {
|
|
308
|
+
for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Returns only the dirty input of the field store. Arrays are treated as
|
|
315
|
+
* atomic and returned in full if any item is dirty, while object keys without
|
|
316
|
+
* a dirty descendant are omitted. Returns `undefined` if no descendant is
|
|
317
|
+
* dirty.
|
|
318
|
+
*
|
|
319
|
+
* @param internalFieldStore The field store to get dirty input from.
|
|
320
|
+
* @param dirtyOnly Whether to only include dirty fields. Defaults to `true`.
|
|
321
|
+
*
|
|
322
|
+
* @returns The dirty input, or `undefined` if no descendant is dirty.
|
|
323
|
+
*/
|
|
324
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
325
|
+
function getDirtyFieldInput(internalFieldStore, dirtyOnly = true) {
|
|
326
|
+
if (dirtyOnly && !/* @__PURE__ */ getFieldBool(internalFieldStore, "isDirty")) return;
|
|
266
327
|
if (internalFieldStore.kind === "array") {
|
|
267
328
|
if (internalFieldStore.input.value) {
|
|
268
329
|
const value = [];
|
|
269
|
-
for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */
|
|
330
|
+
for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */ getDirtyFieldInput(internalFieldStore.children[index], false);
|
|
270
331
|
return value;
|
|
271
332
|
}
|
|
272
333
|
return internalFieldStore.input.value;
|
|
@@ -274,7 +335,10 @@ function getFieldInput(internalFieldStore) {
|
|
|
274
335
|
if (internalFieldStore.kind === "object") {
|
|
275
336
|
if (internalFieldStore.input.value) {
|
|
276
337
|
const value = {};
|
|
277
|
-
for (const key in internalFieldStore.children)
|
|
338
|
+
for (const key in internalFieldStore.children) {
|
|
339
|
+
const child = internalFieldStore.children[key];
|
|
340
|
+
if (!dirtyOnly || /* @__PURE__ */ getFieldBool(child, "isDirty")) value[key] = /* @__PURE__ */ getDirtyFieldInput(child, dirtyOnly);
|
|
341
|
+
}
|
|
278
342
|
return value;
|
|
279
343
|
}
|
|
280
344
|
return internalFieldStore.input.value;
|
|
@@ -282,26 +346,33 @@ function getFieldInput(internalFieldStore) {
|
|
|
282
346
|
return internalFieldStore.input.value;
|
|
283
347
|
}
|
|
284
348
|
/**
|
|
285
|
-
* Returns
|
|
286
|
-
*
|
|
349
|
+
* Returns the current input of the field store. For arrays and objects,
|
|
350
|
+
* recursively collects input from all children. Returns `null` or `undefined`
|
|
351
|
+
* for nullish array/object inputs, or the primitive value for value fields.
|
|
287
352
|
*
|
|
288
|
-
* @param internalFieldStore The field store to
|
|
289
|
-
* @param type The boolean property type to check.
|
|
353
|
+
* @param internalFieldStore The field store to get input from.
|
|
290
354
|
*
|
|
291
|
-
* @returns
|
|
355
|
+
* @returns The field input.
|
|
292
356
|
*/
|
|
293
357
|
/* @__NO_SIDE_EFFECTS__ */
|
|
294
|
-
function
|
|
295
|
-
if (internalFieldStore[type].value) return true;
|
|
358
|
+
function getFieldInput(internalFieldStore) {
|
|
296
359
|
if (internalFieldStore.kind === "array") {
|
|
297
|
-
|
|
298
|
-
|
|
360
|
+
if (internalFieldStore.input.value) {
|
|
361
|
+
const value = [];
|
|
362
|
+
for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */ getFieldInput(internalFieldStore.children[index]);
|
|
363
|
+
return value;
|
|
364
|
+
}
|
|
365
|
+
return internalFieldStore.input.value;
|
|
299
366
|
}
|
|
300
|
-
if (internalFieldStore.kind
|
|
301
|
-
|
|
302
|
-
|
|
367
|
+
if (internalFieldStore.kind === "object") {
|
|
368
|
+
if (internalFieldStore.input.value) {
|
|
369
|
+
const value = {};
|
|
370
|
+
for (const key in internalFieldStore.children) value[key] = /* @__PURE__ */ getFieldInput(internalFieldStore.children[key]);
|
|
371
|
+
return value;
|
|
372
|
+
}
|
|
373
|
+
return internalFieldStore.input.value;
|
|
303
374
|
}
|
|
304
|
-
return
|
|
375
|
+
return internalFieldStore.input.value;
|
|
305
376
|
}
|
|
306
377
|
/**
|
|
307
378
|
* Returns the field store at the specified path by traversing the form store's
|
|
@@ -328,11 +399,9 @@ function getFieldStore(internalFormStore, path) {
|
|
|
328
399
|
*/
|
|
329
400
|
function setFieldBool(internalFieldStore, type, bool) {
|
|
330
401
|
batch(() => {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
} else if (internalFieldStore.kind == "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
335
|
-
else internalFieldStore[type].value = bool;
|
|
402
|
+
internalFieldStore[type].value = bool;
|
|
403
|
+
if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) setFieldBool(internalFieldStore.children[index], type, bool);
|
|
404
|
+
else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
336
405
|
});
|
|
337
406
|
}
|
|
338
407
|
/**
|
|
@@ -347,20 +416,20 @@ function setNestedInput(internalFieldStore, input) {
|
|
|
347
416
|
if (internalFieldStore.kind === "array") {
|
|
348
417
|
const arrayInput = input ?? [];
|
|
349
418
|
const items = internalFieldStore.items.value;
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
419
|
+
const length = internalFieldStore.schema.type === "array" ? arrayInput.length : internalFieldStore.children.length;
|
|
420
|
+
if (length < items.length) internalFieldStore.items.value = items.slice(0, length);
|
|
421
|
+
else if (length > items.length) {
|
|
422
|
+
const path = JSON.parse(internalFieldStore.name);
|
|
423
|
+
for (let index = items.length; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], arrayInput[index], true);
|
|
424
|
+
else {
|
|
425
|
+
internalFieldStore.children[index] = {};
|
|
426
|
+
path.push(index);
|
|
427
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
428
|
+
path.pop();
|
|
360
429
|
}
|
|
361
|
-
internalFieldStore.items.value = [...items, ...
|
|
430
|
+
internalFieldStore.items.value = [...items, ...Array.from({ length: length - items.length }, createId)];
|
|
362
431
|
}
|
|
363
|
-
for (let index = 0; index <
|
|
432
|
+
for (let index = 0; index < length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
|
|
364
433
|
internalFieldStore.input.value = input == null ? input : true;
|
|
365
434
|
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== internalFieldStore.items.value.length;
|
|
366
435
|
} else if (internalFieldStore.kind === "object") {
|
|
@@ -404,21 +473,22 @@ function setFieldInput(internalFormStore, path, input) {
|
|
|
404
473
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
405
474
|
batch(() => {
|
|
406
475
|
if (internalFieldStore.kind === "array") {
|
|
407
|
-
internalFieldStore.
|
|
476
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
408
477
|
const initialArrayInput = initialInput ?? [];
|
|
409
|
-
|
|
478
|
+
const length = internalFieldStore.schema.type === "array" ? initialArrayInput.length : internalFieldStore.children.length;
|
|
479
|
+
if (length > internalFieldStore.children.length) {
|
|
410
480
|
const path = JSON.parse(internalFieldStore.name);
|
|
411
|
-
for (let index = internalFieldStore.children.length; index <
|
|
481
|
+
for (let index = internalFieldStore.children.length; index < length; index++) {
|
|
412
482
|
internalFieldStore.children[index] = {};
|
|
413
483
|
path.push(index);
|
|
414
484
|
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
415
485
|
path.pop();
|
|
416
486
|
}
|
|
417
487
|
}
|
|
418
|
-
internalFieldStore.initialItems.value =
|
|
488
|
+
internalFieldStore.initialItems.value = Array.from({ length }, createId);
|
|
419
489
|
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
420
490
|
} else if (internalFieldStore.kind === "object") {
|
|
421
|
-
internalFieldStore.
|
|
491
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
422
492
|
for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
423
493
|
} else internalFieldStore.initialInput.value = initialInput;
|
|
424
494
|
});
|
|
@@ -470,44 +540,49 @@ function createFormStore(config, parse) {
|
|
|
470
540
|
async function validateFormInput(internalFormStore, config) {
|
|
471
541
|
internalFormStore.validators++;
|
|
472
542
|
internalFormStore.isValidating.value = true;
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const path
|
|
480
|
-
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
const name = JSON.stringify(path);
|
|
488
|
-
const fieldErrors = nestedErrors[name];
|
|
489
|
-
if (fieldErrors) fieldErrors.push(issue.message);
|
|
490
|
-
else nestedErrors[name] = [issue.message];
|
|
491
|
-
} else if (rootErrors) rootErrors.push(issue.message);
|
|
492
|
-
else rootErrors = [issue.message];
|
|
493
|
-
}
|
|
494
|
-
let shouldFocus = config?.shouldFocus ?? false;
|
|
495
|
-
batch(() => {
|
|
496
|
-
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
497
|
-
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
498
|
-
else {
|
|
499
|
-
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
500
|
-
internalFieldStore.errors.value = fieldErrors;
|
|
501
|
-
if (shouldFocus && fieldErrors) {
|
|
502
|
-
internalFieldStore.elements[0]?.focus();
|
|
503
|
-
shouldFocus = false;
|
|
543
|
+
try {
|
|
544
|
+
const result = await internalFormStore.parse(untrack(() => /* @__PURE__ */ getFieldInput(internalFormStore)));
|
|
545
|
+
let rootErrors;
|
|
546
|
+
let nestedErrors;
|
|
547
|
+
if (result.issues) {
|
|
548
|
+
nestedErrors = {};
|
|
549
|
+
for (const issue of result.issues) if (issue.path) {
|
|
550
|
+
const path = [];
|
|
551
|
+
for (const pathItem of issue.path) {
|
|
552
|
+
const key = pathItem.key;
|
|
553
|
+
const keyType = typeof key;
|
|
554
|
+
const itemType = pathItem.type;
|
|
555
|
+
if (keyType !== "string" && keyType !== "number" || itemType === "map" || itemType === "set") break;
|
|
556
|
+
path.push(key);
|
|
504
557
|
}
|
|
505
|
-
|
|
558
|
+
const name = JSON.stringify(path);
|
|
559
|
+
const fieldErrors = nestedErrors[name];
|
|
560
|
+
if (fieldErrors) fieldErrors.push(issue.message);
|
|
561
|
+
else nestedErrors[name] = [issue.message];
|
|
562
|
+
} else if (rootErrors) rootErrors.push(issue.message);
|
|
563
|
+
else rootErrors = [issue.message];
|
|
564
|
+
}
|
|
565
|
+
let shouldFocus = config?.shouldFocus ?? false;
|
|
566
|
+
batch(() => {
|
|
567
|
+
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
568
|
+
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
569
|
+
else {
|
|
570
|
+
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
571
|
+
internalFieldStore.errors.value = fieldErrors;
|
|
572
|
+
if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
internalFormStore.validators--;
|
|
576
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
506
577
|
});
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
578
|
+
return result;
|
|
579
|
+
} catch (error) {
|
|
580
|
+
batch(() => {
|
|
581
|
+
internalFormStore.validators--;
|
|
582
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
583
|
+
});
|
|
584
|
+
throw error;
|
|
585
|
+
}
|
|
511
586
|
}
|
|
512
587
|
/**
|
|
513
588
|
* Validates the form input if required based on the validation mode and form
|
|
@@ -529,7 +604,7 @@ const INTERNAL = "~internal";
|
|
|
529
604
|
//#endregion
|
|
530
605
|
//#region ../../packages/methods/dist/index.vue.js
|
|
531
606
|
/**
|
|
532
|
-
* Focuses the first input element of a field. This is useful for
|
|
607
|
+
* Focuses the first focusable input element of a field. This is useful for
|
|
533
608
|
* programmatically setting focus to a specific field, such as after
|
|
534
609
|
* validation errors or user interactions.
|
|
535
610
|
*
|
|
@@ -537,7 +612,7 @@ const INTERNAL = "~internal";
|
|
|
537
612
|
* @param config The focus field configuration.
|
|
538
613
|
*/
|
|
539
614
|
function focus(form, config) {
|
|
540
|
-
getFieldStore(form[INTERNAL], config.path)
|
|
615
|
+
focusFieldElement(getFieldStore(form[INTERNAL], config.path));
|
|
541
616
|
}
|
|
542
617
|
/**
|
|
543
618
|
* Retrieves all error messages from all fields in the form by walking through
|
|
@@ -560,6 +635,17 @@ function getAllErrors(form) {
|
|
|
560
635
|
return allErrors;
|
|
561
636
|
}
|
|
562
637
|
/* @__NO_SIDE_EFFECTS__ */
|
|
638
|
+
function getDirtyInput(form, config) {
|
|
639
|
+
return getDirtyFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
|
|
640
|
+
}
|
|
641
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
642
|
+
function getDirtyPaths(form, config) {
|
|
643
|
+
config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
|
|
644
|
+
const paths = [];
|
|
645
|
+
config?.path && [...config.path];
|
|
646
|
+
return paths;
|
|
647
|
+
}
|
|
648
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
563
649
|
function getErrors(form, config) {
|
|
564
650
|
return (config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value;
|
|
565
651
|
}
|
|
@@ -653,6 +739,48 @@ function move(form, config) {
|
|
|
653
739
|
});
|
|
654
740
|
}
|
|
655
741
|
/**
|
|
742
|
+
* Picks only the dirty parts of the given value, using the form's dirty fields
|
|
743
|
+
* as a structural mask. Arrays are treated as atomic and object keys without a
|
|
744
|
+
* dirty descendant are omitted. Returns `undefined` if no field is dirty.
|
|
745
|
+
* Useful for filtering a validated output down to its changed parts before
|
|
746
|
+
* submitting.
|
|
747
|
+
*
|
|
748
|
+
* @param form The form store providing the dirty mask.
|
|
749
|
+
* @param config The pick dirty configuration.
|
|
750
|
+
*
|
|
751
|
+
* @returns The dirty parts of the value, or `undefined`.
|
|
752
|
+
*/
|
|
753
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
754
|
+
function pickDirty(form, config) {
|
|
755
|
+
if (!getFieldBool(form[INTERNAL], "isDirty")) return;
|
|
756
|
+
const result = /* @__PURE__ */ pickFieldValue(form[INTERNAL], config.from);
|
|
757
|
+
return Object.keys(result).length ? result : void 0;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Recursively picks the dirty parts of a value using the field store as a
|
|
761
|
+
* structural mask, reading from the supplied value rather than the form's own
|
|
762
|
+
* input. Objects with non-nullish input recurse into their dirty children that
|
|
763
|
+
* are present in the value, while arrays, primitives, nullish-cleared fields
|
|
764
|
+
* and shape-diverging values are returned as-is.
|
|
765
|
+
*
|
|
766
|
+
* @param internalFieldStore The field store used as the dirty mask.
|
|
767
|
+
* @param value The value to pick the dirty parts from.
|
|
768
|
+
*
|
|
769
|
+
* @returns The dirty parts of the value.
|
|
770
|
+
*/
|
|
771
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
772
|
+
function pickFieldValue(internalFieldStore, value) {
|
|
773
|
+
if (internalFieldStore.kind === "object" && internalFieldStore.input.value && value && typeof value === "object" && !Array.isArray(value)) {
|
|
774
|
+
const result = {};
|
|
775
|
+
for (const key in internalFieldStore.children) {
|
|
776
|
+
const child = internalFieldStore.children[key];
|
|
777
|
+
if (getFieldBool(child, "isDirty") && key in value) result[key] = /* @__PURE__ */ pickFieldValue(child, value[key]);
|
|
778
|
+
}
|
|
779
|
+
return result;
|
|
780
|
+
}
|
|
781
|
+
return value;
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
656
784
|
* Removes an item from a field array at the specified index. All items after
|
|
657
785
|
* the removed item are shifted down by one index.
|
|
658
786
|
*
|
|
@@ -787,7 +915,10 @@ function useField(form, config) {
|
|
|
787
915
|
const internalFormStore = computed(() => toValue(form)[INTERNAL]);
|
|
788
916
|
const internalFieldStore = computed(() => getFieldStore(internalFormStore.value, path.value));
|
|
789
917
|
onUnmounted(() => {
|
|
790
|
-
|
|
918
|
+
const internalFieldStoreValue = internalFieldStore.value;
|
|
919
|
+
const elements = internalFieldStoreValue.elements.filter((element) => element.isConnected);
|
|
920
|
+
if (internalFieldStoreValue.elements === internalFieldStoreValue.initialElements) internalFieldStoreValue.initialElements = elements;
|
|
921
|
+
internalFieldStoreValue.elements = elements;
|
|
791
922
|
});
|
|
792
923
|
const input = computed(() => getFieldInput(internalFieldStore.value));
|
|
793
924
|
const isTouched = computed(() => getFieldBool(internalFieldStore.value, "isTouched"));
|
|
@@ -977,4 +1108,4 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
|
|
|
977
1108
|
var Form_default = Form_vue_vue_type_script_setup_true_lang_default;
|
|
978
1109
|
|
|
979
1110
|
//#endregion
|
|
980
|
-
export { Field_default as Field, FieldArray_default as FieldArray, Form_default as Form, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };
|
|
1111
|
+
export { Field_default as Field, FieldArray_default as FieldArray, Form_default as Form, focus, getAllErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formisch/vue",
|
|
3
3
|
"description": "The lightweight, schema-first, and fully type-safe form library for Vue",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fabian Hiller",
|
|
7
7
|
"homepage": "https://formisch.dev",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@formisch/methods": "workspace:*",
|
|
48
48
|
"@testing-library/jest-dom": "^6.6.0",
|
|
49
49
|
"@types/node": "^24.1.0",
|
|
50
|
-
"@vitest/coverage-v8": "^
|
|
50
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
51
51
|
"@vue/eslint-config-typescript": "^14.6.0",
|
|
52
52
|
"@vue/test-utils": "^2.4.6",
|
|
53
53
|
"eslint": "^9.32.0",
|
|
@@ -56,14 +56,14 @@
|
|
|
56
56
|
"tsdown": "^0.16.8",
|
|
57
57
|
"typescript": "~5.8.3",
|
|
58
58
|
"unplugin-vue": "^7.0.0",
|
|
59
|
-
"valibot": "^1.
|
|
60
|
-
"vitest": "^
|
|
59
|
+
"valibot": "^1.4.1",
|
|
60
|
+
"vitest": "^4.1.7",
|
|
61
61
|
"vue": "^3.5.18",
|
|
62
62
|
"vue-tsc": "^3.0.4"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"typescript": ">=5",
|
|
66
|
-
"valibot": "^1.
|
|
66
|
+
"valibot": "^1.4.1",
|
|
67
67
|
"vue": "^3.3.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependenciesMeta": {
|