@formisch/react 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,177 @@ import { ChangeEventHandler, FocusEventHandler, FormEvent, FormHTMLAttributes, R
3
3
 
4
4
  //#region ../../packages/core/dist/index.react.d.ts
5
5
 
6
+ //#region src/types/utils/utils.d.ts
7
+ /**
8
+ * Checks if a type is `any`.
9
+ */
10
+ type IsAny<T> = 0 extends 1 & T ? true : false;
11
+ /**
12
+ * Checks if a type is `never`.
13
+ */
14
+ type IsNever<T> = [T] extends [never] ? true : false;
15
+ /**
16
+ * Constructs a type that is maybe a promise.
17
+ */
18
+ type MaybePromise<T> = T | Promise<T>;
19
+ /**
20
+ * Makes all properties deeply optional.
21
+ */
22
+ type DeepPartial<TValue> = TValue extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TValue]?: DeepPartial<TValue[TKey]> | undefined } : TValue | undefined;
23
+ /**
24
+ * Makes all value properties optional.
25
+ *
26
+ * Hint: For dynamic arrays, only plain objects and nested arrays have their
27
+ * values made optional. Primitives and class instances are kept as-is to avoid
28
+ * types like `(string | undefined)[]`.
29
+ */
30
+ type PartialValues<TValue> = TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? (TItem extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TItem]: PartialValues<TItem[TKey]> } : TItem)[] : { [TKey in keyof TValue]: PartialValues<TValue[TKey]> } : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: PartialValues<TValue[TKey]> } : TValue | undefined;
31
+ //#endregion
32
+ //#region src/types/path/path.d.ts
33
+ /**
34
+ * Path key type.
35
+ */
36
+ type PathKey = string | number;
37
+ /**
38
+ * Path type.
39
+ */
40
+ type Path = readonly PathKey[];
41
+ /**
42
+ * Required path type.
43
+ */
44
+ type RequiredPath = readonly [PathKey, ...Path];
45
+ /**
46
+ * Extracts the exact keys of a tuple, array or object. Tuples return their
47
+ * literal numeric indices, dynamic arrays return `number`, objects return
48
+ * their `keyof` keys, and any other input returns `never`.
49
+ */
50
+ type ExactKeysOf<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly unknown[] ? number extends TValue["length"] ? number : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? TIndex : never }[number] : TValue extends Record<PropertyKey, unknown> ? keyof TValue & PathKey : never;
51
+ /**
52
+ * Returns the flat object of all indexable properties of `TValue`. For object
53
+ * unions, properties from every member are merged so that any single property
54
+ * is accessible. For primitives and other non-indexable types, the result is
55
+ * `{}`.
56
+ *
57
+ * Hint: This is necessary to make properties accessible across union members.
58
+ * By default, properties that do not exist in all union options are not
59
+ * accessible and result in "any" when accessed.
60
+ */
61
+ type PropertiesOf<TValue> = { [TKey in ExactKeysOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
62
+ /**
63
+ * Lazily evaluates only the first valid path segment based on the given value.
64
+ */
65
+ type LazyPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValidPath : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOf<TValue>, ...infer TPathRest extends Path] ? LazyPath<Required<PropertiesOf<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOf<TValue>> extends false ? readonly [...TValidPath, ExactKeysOf<TValue>] : TValidPath;
66
+ /**
67
+ * Returns the path if valid, otherwise the first possible valid path based on
68
+ * the given value.
69
+ */
70
+ type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
71
+ /**
72
+ * Detects whether the consuming project is configured with
73
+ * `exactOptionalPropertyTypes: true`.
74
+ *
75
+ * Hint: If `false` the built-in `Required<T>` strips `| undefined` from
76
+ * optional properties, so `Required<{ key?: undefined }>['key']` collapses
77
+ * to `never` — under strict mode the same expression yields `undefined`.
78
+ */
79
+ type IsExactOptionalProps = Required<{
80
+ key?: undefined;
81
+ }>["key"] extends never ? false : true;
82
+ /**
83
+ * Like the built-in `Required<T>`, but preserves `| undefined` in two
84
+ * places where `Required<T>` strips it:
85
+ *
86
+ * 1. Optional property values under `exactOptionalPropertyTypes: false`
87
+ * — without this, input typings for `v.optional`/`v.nullish` schemas
88
+ * narrow incorrectly (issue #15).
89
+ * 2. Array/tuple element types — e.g. `(string | undefined)[]` stays
90
+ * `(string | undefined)[]` instead of becoming `string[]`. Arrays
91
+ * fall through unchanged because they only have a numeric index
92
+ * signature and don't structurally extend `Record<PropertyKey,
93
+ * unknown>` (which requires string keys).
94
+ */
95
+ type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExactOptionalProps extends true ? Required<TValue> : { [TKey in keyof Required<TValue>]: TValue[TKey] } : TValue;
96
+ /**
97
+ * Extracts the value type at the given path.
98
+ */
99
+ 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;
100
+ /**
101
+ * Checks whether a value is a dynamic array or contains one anywhere in its
102
+ * shape. A fixed-length tuple is not itself a dynamic array, but it counts when
103
+ * it contains one, so paths can still navigate through tuples to reach nested
104
+ * arrays.
105
+ *
106
+ * Hint: The inner conditionals (`TValue extends readonly unknown[]` and
107
+ * `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
108
+ * so the inner expression returns the union of each member's result (e.g.
109
+ * `true | false` when some members contain arrays and others don't).
110
+ * Downstream code uses `IsOrHasArray<T> extends true`, but
111
+ * `boolean extends true` is `false` — so we collapse the result via
112
+ * `true extends ...`, which is `true` whenever at least one union member
113
+ * contributed `true`.
114
+ */
115
+ 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;
116
+ /**
117
+ * Extracts the exact keys of a tuple, array or object that contain arrays.
118
+ */
119
+ type ExactKeysOfArrayPath<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? IsOrHasArray<TItem> extends true ? number : never : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TIndex : never : never }[number] : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TKey : never }[keyof TValue] & PathKey : never;
120
+ /**
121
+ * Returns the flat object of indexable properties of `TValue` whose values
122
+ * are or contain arrays. Mirrors `PropertiesOf` but keyed by
123
+ * `ExactKeysOfArrayPath` so the lookup is provably valid for array-path
124
+ * navigation in `LazyArrayPath`.
125
+ */
126
+ type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
127
+ /**
128
+ * Lazily evaluates only the first valid array path segment based on the given value.
129
+ */
130
+ 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;
131
+ /**
132
+ * Returns the path if valid, otherwise the first possible valid array path
133
+ * based on the given value.
134
+ */
135
+ type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
136
+ /**
137
+ * Recursive helper for `DirtyPath` that prepends `TKey` to each deeper path,
138
+ * or falls through to `never` when the child is not an object.
139
+ */
140
+ type DeepDirtyPath<TChild, TKey$1 extends PathKey, TDepth extends 0[]> = TChild extends Record<PropertyKey, unknown> ? readonly [TKey$1, ...DirtyPath<TChild, [...TDepth, 0]>] : never;
141
+ /**
142
+ * Returns the union of all `RequiredPath`s that `getDirtyPaths` can emit
143
+ * for a given input type. Object fields contribute their own path and the
144
+ * paths of their descendants; arrays and tuples are atomic and contribute
145
+ * only their own path, because dirty arrays are returned as complete units.
146
+ *
147
+ * Narrowing is exact for the first 5 levels of nesting; deeper paths fall
148
+ * back to `RequiredPath` to keep the result a complete superset of any
149
+ * path the runtime can address.
150
+ *
151
+ * Hint: Arrays and tuples are atomic because they don't structurally
152
+ * extend `Record<PropertyKey, unknown>` and so fall through to `never`
153
+ * via `DeepDirtyPath` — no explicit array check is needed. `TDepth` is
154
+ * a tuple-length counter capped at 5 to bound TypeScript instantiation
155
+ * cost.
156
+ */
157
+ 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;
158
+ /**
159
+ * Recursive helper for `FieldPath` that prepends `TKey` to each deeper field
160
+ * path, or falls through to `never` when the child is a leaf value.
161
+ */
162
+ type DeepFieldPath<TChild, TKey$1 extends PathKey, TDepth extends 0[]> = TChild extends readonly unknown[] | Record<PropertyKey, unknown> ? readonly [TKey$1, ...FieldPath<TChild, [...TDepth, 0]>] : never;
163
+ /**
164
+ * Returns the union of all `RequiredPath`s that address a field within the
165
+ * given input type. Object and array fields contribute their own path and the
166
+ * paths of their descendants; unlike `DirtyPath`, arrays are recursed into so
167
+ * that fields at any depth, including array items, can be addressed. Leaf
168
+ * values contribute only their own path (emitted by their parent).
169
+ *
170
+ * Narrowing is exact for the first 5 levels of nesting; deeper paths fall
171
+ * back to `RequiredPath` to keep the result a complete superset of any path
172
+ * the runtime can address. `TDepth` is a tuple-length counter capped at 5 to
173
+ * bound TypeScript instantiation cost.
174
+ */
175
+ type FieldPath<TValue, TDepth extends 0[] = []> = TDepth["length"] extends 5 ? RequiredPath : TValue extends readonly unknown[] | Record<PropertyKey, unknown> ? { [TKey in ExactKeysOf<TValue>]: readonly [TKey] | DeepFieldPath<NonNullable<PropertiesOf<TValue>[TKey]>, TKey, TDepth> }[ExactKeysOf<TValue>] : never;
176
+ //#endregion
6
177
  //#region src/types/schema/schema.d.ts
7
178
  /**
8
179
  * Schema type.
@@ -67,11 +238,22 @@ interface InternalBaseStore {
67
238
  */
68
239
  name: string;
69
240
  /**
241
+ * The path to the field.
242
+ */
243
+ path: Path;
244
+ /**
70
245
  * The schema of the field.
71
246
  */
72
247
  schema: Schema;
73
248
  /**
74
249
  * The initial elements of the field.
250
+ *
251
+ * Hint: This may look unused, but do not remove it. `copyItemState` and
252
+ * `swapItemState` move the `elements` reference between field stores when
253
+ * array items are inserted, moved, removed or swapped, and `reset` restores
254
+ * each field's original element via `elements = initialElements`. Without it,
255
+ * focus and file reset target the wrong element after a reorder followed by a
256
+ * reset.
75
257
  */
76
258
  initialElements: FieldElement[];
77
259
  /**
@@ -87,6 +269,15 @@ interface InternalBaseStore {
87
269
  */
88
270
  isTouched: Signal<boolean>;
89
271
  /**
272
+ * The edited state of the field.
273
+ *
274
+ * Hint: Unlike `isTouched`, which is also set when a field is focused, this
275
+ * is only set when the field's value is changed. Unlike `isDirty`, it stays
276
+ * `true` even if the value is changed back to its initial value. It is only
277
+ * reset when the field is reset.
278
+ */
279
+ isEdited: Signal<boolean>;
280
+ /**
90
281
  * The dirty state of the field.
91
282
  */
92
283
  isDirty: Signal<boolean>;
@@ -100,6 +291,14 @@ interface InternalArrayStore extends InternalBaseStore {
100
291
  */
101
292
  kind: "array";
102
293
  /**
294
+ * Whether the array schema is wrapped in a nullish schema.
295
+ *
296
+ * Hint: This indicates whether a missing input should be represented as the
297
+ * nullish value (`null`/`undefined`) or as a present but empty array
298
+ * (`true`). It keeps resetting consistent with the initial state.
299
+ */
300
+ isNullish: boolean;
301
+ /**
103
302
  * The children of the array field.
104
303
  */
105
304
  children: InternalFieldStore[];
@@ -152,6 +351,14 @@ interface InternalObjectStore extends InternalBaseStore {
152
351
  */
153
352
  kind: "object";
154
353
  /**
354
+ * Whether the object schema is wrapped in a nullish schema.
355
+ *
356
+ * Hint: This indicates whether a missing input should be represented as the
357
+ * nullish value (`null`/`undefined`) or as a present but empty object
358
+ * (`true`). It keeps resetting consistent with the initial state.
359
+ */
360
+ isNullish: boolean;
361
+ /**
155
362
  * The children of the object field.
156
363
  */
157
364
  children: Record<string, InternalFieldStore>;
@@ -209,32 +416,6 @@ interface InternalValueStore extends InternalBaseStore {
209
416
  */
210
417
  type InternalFieldStore = InternalArrayStore | InternalObjectStore | InternalValueStore;
211
418
  //#endregion
212
- //#region src/types/utils/utils.d.ts
213
- /**
214
- * Checks if a type is `any`.
215
- */
216
- type IsAny<T> = 0 extends 1 & T ? true : false;
217
- /**
218
- * Checks if a type is `never`.
219
- */
220
- type IsNever<T> = [T] extends [never] ? true : false;
221
- /**
222
- * Constructs a type that is maybe a promise.
223
- */
224
- type MaybePromise<T> = T | Promise<T>;
225
- /**
226
- * Makes all properties deeply optional.
227
- */
228
- type DeepPartial<TValue> = TValue extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TValue]?: DeepPartial<TValue[TKey]> | undefined } : TValue | undefined;
229
- /**
230
- * Makes all value properties optional.
231
- *
232
- * Hint: For dynamic arrays, only plain objects and nested arrays have their
233
- * values made optional. Primitives and class instances are kept as-is to avoid
234
- * types like `(string | undefined)[]`.
235
- */
236
- type PartialValues<TValue> = TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? (TItem extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TItem]: PartialValues<TItem[TKey]> } : TItem)[] : { [TKey in keyof TValue]: PartialValues<TValue[TKey]> } : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: PartialValues<TValue[TKey]> } : TValue | undefined;
237
- //#endregion
238
419
  //#region src/values.d.ts
239
420
  /**
240
421
  * Internal symbol constant.
@@ -326,173 +507,137 @@ type SubmitHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>
326
507
  */
327
508
  type SubmitEventHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>, event: FormEvent<HTMLFormElement>) => MaybePromise<unknown>;
328
509
  //#endregion
329
- //#region src/types/path/path.d.ts
330
- /**
331
- * Path key type.
332
- */
333
- type PathKey = string | number;
334
- /**
335
- * Path type.
336
- */
337
- type Path = readonly PathKey[];
510
+ //#region src/array/copyItemState/copyItemState.d.ts
338
511
  /**
339
- * Required path type.
512
+ * Copies the deeply nested state (signal values) from one field store to
513
+ * another. This includes the `elements`, `errors`, `startInput`, `input`,
514
+ * `isTouched`, `isEdited`, `isDirty`, and for arrays `startItems` and `items`
515
+ * properties. Recursively walks through the field stores and copies all signal
516
+ * values.
517
+ *
518
+ * @param fromInternalFieldStore The source field store to copy from.
519
+ * @param toInternalFieldStore The destination field store to copy to.
340
520
  */
341
- type RequiredPath = readonly [PathKey, ...Path];
521
+ //#endregion
522
+ //#region ../../packages/methods/dist/index.react.d.ts
523
+ //#region src/focus/focus.d.ts
342
524
  /**
343
- * Extracts the exact keys of a tuple, array or object. Tuples return their
344
- * literal numeric indices, dynamic arrays return `number`, objects return
345
- * their `keyof` keys, and any other input returns `never`.
525
+ * Focus field config interface.
346
526
  */
347
- type ExactKeysOf<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly unknown[] ? number extends TValue["length"] ? number : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? TIndex : never }[number] : TValue extends Record<PropertyKey, unknown> ? keyof TValue & PathKey : never;
527
+ interface FocusFieldConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
528
+ /**
529
+ * The path to the field to focus.
530
+ */
531
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
532
+ }
348
533
  /**
349
- * Returns the flat object of all indexable properties of `TValue`. For object
350
- * unions, properties from every member are merged so that any single property
351
- * is accessible. For primitives and other non-indexable types, the result is
352
- * `{}`.
534
+ * Focuses the first focusable input element of a field. This is useful for
535
+ * programmatically setting focus to a specific field, such as after
536
+ * validation errors or user interactions.
353
537
  *
354
- * Hint: This is necessary to make properties accessible across union members.
355
- * By default, properties that do not exist in all union options are not
356
- * accessible and result in "any" when accessed.
538
+ * @param form The form store containing the field.
539
+ * @param config The focus field configuration.
357
540
  */
358
- type PropertiesOf<TValue> = { [TKey in ExactKeysOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
541
+ declare function focus<TSchema extends FormSchema, TFieldPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: FocusFieldConfig<TSchema, TFieldPath>): void;
542
+ //#endregion
543
+ //#region src/getDeepErrorEntries/getDeepErrorEntries.d.ts
359
544
  /**
360
- * Lazily evaluates only the first valid path segment based on the given value.
545
+ * Deep error entry interface.
361
546
  */
362
- type LazyPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValidPath : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOf<TValue>, ...infer TPathRest extends Path] ? LazyPath<Required<PropertiesOf<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOf<TValue>> extends false ? readonly [...TValidPath, ExactKeysOf<TValue>] : TValidPath;
547
+ interface DeepErrorEntry<TValue = unknown> {
548
+ /**
549
+ * The path to the field with errors, or an empty path for form-level errors.
550
+ */
551
+ readonly path: unknown extends TValue ? Path : readonly [] | FieldPath<TValue>;
552
+ /**
553
+ * The error messages of the field.
554
+ */
555
+ readonly errors: [string, ...string[]];
556
+ }
363
557
  /**
364
- * Returns the path if valid, otherwise the first possible valid path based on
365
- * the given value.
558
+ * Get form deep error entries config interface.
366
559
  */
367
- type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
560
+ interface GetFormDeepErrorEntriesConfig {
561
+ /**
562
+ * The path to a field. Leave undefined to get the entries of the entire form.
563
+ */
564
+ readonly path?: undefined;
565
+ }
368
566
  /**
369
- * Detects whether the consuming project is configured with
370
- * `exactOptionalPropertyTypes: true`.
371
- *
372
- * Hint: If `false` the built-in `Required<T>` strips `| undefined` from
373
- * optional properties, so `Required<{ key?: undefined }>['key']` collapses
374
- * to `never` — under strict mode the same expression yields `undefined`.
567
+ * Get field deep error entries config interface.
375
568
  */
376
- type IsExactOptionalProps = Required<{
377
- key?: undefined;
378
- }>["key"] extends never ? false : true;
569
+ interface GetFieldDeepErrorEntriesConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
570
+ /**
571
+ * The path to the field to retrieve the entries from.
572
+ */
573
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
574
+ }
379
575
  /**
380
- * Like the built-in `Required<T>`, but preserves `| undefined` in two
381
- * places where `Required<T>` strips it:
576
+ * Retrieves the errors of a specific field or the entire form as a list of
577
+ * entries, each pairing the path to a field with its error messages. This is
578
+ * useful for building custom error summaries that link each message back to
579
+ * its field. Form-level errors are included with an empty path.
382
580
  *
383
- * 1. Optional property values under `exactOptionalPropertyTypes: false`
384
- * — without this, input typings for `v.optional`/`v.nullish` schemas
385
- * narrow incorrectly (issue #15).
386
- * 2. Array/tuple element types — e.g. `(string | undefined)[]` stays
387
- * `(string | undefined)[]` instead of becoming `string[]`. Arrays
388
- * fall through unchanged because they only have a numeric index
389
- * signature and don't structurally extend `Record<PropertyKey,
390
- * unknown>` (which requires string keys).
391
- */
392
- type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExactOptionalProps extends true ? Required<TValue> : { [TKey in keyof Required<TValue>]: TValue[TKey] } : TValue;
393
- /**
394
- * Extracts the value type at the given path.
395
- */
396
- 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;
397
- /**
398
- * Checks whether a value is an array or contains one anywhere in its shape.
581
+ * @param form The form store to retrieve error entries from.
399
582
  *
400
- * Hint: The inner conditionals (`TValue extends readonly unknown[]` and
401
- * `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
402
- * so the inner expression returns the union of each member's result (e.g.
403
- * `true | false` when some members contain arrays and others don't).
404
- * Downstream code uses `IsOrHasArray<T> extends true`, but
405
- * `boolean extends true` is `false` — so we collapse the result via
406
- * `true extends ...`, which is `true` whenever at least one union member
407
- * contributed `true`.
408
- */
409
- 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;
410
- /**
411
- * Extracts the exact keys of a tuple, array or object that contain arrays.
583
+ * @returns A list of path and error message entries.
412
584
  */
413
- type ExactKeysOfArrayPath<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? IsOrHasArray<TItem> extends true ? number : never : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TIndex : never : never }[number] : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TKey : never }[keyof TValue] & PathKey : never;
414
- /**
415
- * Returns the flat object of indexable properties of `TValue` whose values
416
- * are or contain arrays. Mirrors `PropertiesOf` but keyed by
417
- * `ExactKeysOfArrayPath` so the lookup is provably valid for array-path
418
- * navigation in `LazyArrayPath`.
419
- */
420
- type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
421
- /**
422
- * Lazily evaluates only the first valid array path segment based on the given value.
423
- */
424
- 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;
585
+ declare function getDeepErrorEntries<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): DeepErrorEntry<v.InferInput<TSchema>>[];
425
586
  /**
426
- * Returns the path if valid, otherwise the first possible valid array path
427
- * based on the given value.
428
- */
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.
587
+ * Retrieves the errors of a specific field or the entire form as a list of
588
+ * entries, each pairing the path to a field with its error messages. This is
589
+ * useful for building custom error summaries that link each message back to
590
+ * its field. Form-level errors are included with an empty path.
440
591
  *
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.
592
+ * @param form The form store to retrieve error entries from.
593
+ * @param config The get deep error entries configuration.
444
594
  *
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.
595
+ * @returns A list of path and error message entries.
450
596
  */
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;
597
+ declare function getDeepErrorEntries<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldDeepErrorEntriesConfig<TSchema, TFieldPath> : GetFormDeepErrorEntriesConfig): DeepErrorEntry<v.InferInput<TSchema>>[];
452
598
  //#endregion
453
- //#region src/array/copyItemState/copyItemState.d.ts
599
+ //#region src/getDeepErrors/getDeepErrors.d.ts
454
600
  /**
455
- * Copies the deeply nested state (signal values) from one field store to
456
- * another. This includes the `elements`, `errors`, `startInput`, `input`,
457
- * `isTouched`, `isDirty`, and for arrays `startItems` and `items` properties.
458
- * Recursively walks through the field stores and copies all signal values.
459
- *
460
- * @param fromInternalFieldStore The source field store to copy from.
461
- * @param toInternalFieldStore The destination field store to copy to.
601
+ * Get form deep errors config interface.
462
602
  */
463
- //#endregion
464
- //#region ../../packages/methods/dist/index.react.d.ts
465
- //#region src/focus/focus.d.ts
603
+ interface GetFormDeepErrorsConfig {
604
+ /**
605
+ * The path to a field. Leave undefined to get the errors of the entire form.
606
+ */
607
+ readonly path?: undefined;
608
+ }
466
609
  /**
467
- * Focus field config interface.
610
+ * Get field deep errors config interface.
468
611
  */
469
- interface FocusFieldConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
612
+ interface GetFieldDeepErrorsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
470
613
  /**
471
- * The path to the field to focus.
614
+ * The path to the field to retrieve the errors from.
472
615
  */
473
616
  readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
474
617
  }
475
618
  /**
476
- * Focuses the first input element of a field. This is useful for
477
- * programmatically setting focus to a specific field, such as after
478
- * validation errors or user interactions.
619
+ * Retrieves all error messages of a specific field or the entire form by
620
+ * walking through the field store and all its descendants. This is useful for
621
+ * displaying a summary of all validation errors within a section or the whole
622
+ * form. Form-level errors are included.
479
623
  *
480
- * @param form The form store containing the field.
481
- * @param config The focus field configuration.
624
+ * @param form The form store to retrieve errors from.
625
+ *
626
+ * @returns A non-empty array of error messages, or null if no errors exist.
482
627
  */
483
- declare function focus<TSchema extends FormSchema, TFieldPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: FocusFieldConfig<TSchema, TFieldPath>): void;
484
- //#endregion
485
- //#region src/getAllErrors/getAllErrors.d.ts
628
+ declare function getDeepErrors<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): [string, ...string[]] | null;
486
629
  /**
487
- * Retrieves all error messages from all fields in the form by walking through
488
- * the entire field store tree. This is useful for displaying a summary of all
489
- * validation errors across the form.
630
+ * Retrieves all error messages of a specific field or the entire form by
631
+ * walking through the field store and all its descendants. This is useful for
632
+ * displaying a summary of all validation errors within a section or the whole
633
+ * form. Form-level errors are included.
490
634
  *
491
635
  * @param form The form store to retrieve errors from.
636
+ * @param config The get deep errors configuration.
492
637
  *
493
638
  * @returns A non-empty array of error messages, or null if no errors exist.
494
639
  */
495
- declare function getAllErrors(form: BaseFormStore): [string, ...string[]] | null;
640
+ declare function getDeepErrors<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldDeepErrorsConfig<TSchema, TFieldPath> : GetFormDeepErrorsConfig): [string, ...string[]] | null;
496
641
  //#endregion
497
642
  //#region src/getDirtyInput/getDirtyInput.d.ts
498
643
  /**
@@ -712,6 +857,172 @@ interface InsertConfig<TSchema extends FormSchema, TFieldArrayPath extends Requi
712
857
  */
713
858
  declare function insert<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: InsertConfig<TSchema, TFieldArrayPath>): void;
714
859
  //#endregion
860
+ //#region src/isDirty/isDirty.d.ts
861
+ /**
862
+ * Is form dirty config interface.
863
+ */
864
+ interface IsFormDirtyConfig {
865
+ /**
866
+ * The path to a field. Leave undefined to check the entire form.
867
+ */
868
+ readonly path?: undefined;
869
+ }
870
+ /**
871
+ * Is field dirty config interface.
872
+ */
873
+ interface IsFieldDirtyConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
874
+ /**
875
+ * The path to the field to check for dirtiness.
876
+ */
877
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
878
+ }
879
+ /**
880
+ * Checks whether a specific field or the entire form is dirty by walking
881
+ * through the field store and all its descendants. A field is dirty when its
882
+ * input differs from its initial value.
883
+ *
884
+ * @param form The form store to check for dirtiness.
885
+ *
886
+ * @returns Whether the field or form is dirty.
887
+ */
888
+ declare function isDirty<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): boolean;
889
+ /**
890
+ * Checks whether a specific field or the entire form is dirty by walking
891
+ * through the field store and all its descendants. A field is dirty when its
892
+ * input differs from its initial value.
893
+ *
894
+ * @param form The form store to check for dirtiness.
895
+ * @param config The is dirty configuration.
896
+ *
897
+ * @returns Whether the field or form is dirty.
898
+ */
899
+ declare function isDirty<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? IsFieldDirtyConfig<TSchema, TFieldPath> : IsFormDirtyConfig): boolean;
900
+ //#endregion
901
+ //#region src/isEdited/isEdited.d.ts
902
+ /**
903
+ * Is form edited config interface.
904
+ */
905
+ interface IsFormEditedConfig {
906
+ /**
907
+ * The path to a field. Leave undefined to check the entire form.
908
+ */
909
+ readonly path?: undefined;
910
+ }
911
+ /**
912
+ * Is field edited config interface.
913
+ */
914
+ interface IsFieldEditedConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
915
+ /**
916
+ * The path to the field to check for being edited.
917
+ */
918
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
919
+ }
920
+ /**
921
+ * Checks whether a specific field or the entire form is edited by walking
922
+ * through the field store and all its descendants. A field is edited once its
923
+ * value has been changed by the user.
924
+ *
925
+ * @param form The form store to check for being edited.
926
+ *
927
+ * @returns Whether the field or form is edited.
928
+ */
929
+ declare function isEdited<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): boolean;
930
+ /**
931
+ * Checks whether a specific field or the entire form is edited by walking
932
+ * through the field store and all its descendants. A field is edited once its
933
+ * value has been changed by the user.
934
+ *
935
+ * @param form The form store to check for being edited.
936
+ * @param config The is edited configuration.
937
+ *
938
+ * @returns Whether the field or form is edited.
939
+ */
940
+ declare function isEdited<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? IsFieldEditedConfig<TSchema, TFieldPath> : IsFormEditedConfig): boolean;
941
+ //#endregion
942
+ //#region src/isTouched/isTouched.d.ts
943
+ /**
944
+ * Is form touched config interface.
945
+ */
946
+ interface IsFormTouchedConfig {
947
+ /**
948
+ * The path to a field. Leave undefined to check the entire form.
949
+ */
950
+ readonly path?: undefined;
951
+ }
952
+ /**
953
+ * Is field touched config interface.
954
+ */
955
+ interface IsFieldTouchedConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
956
+ /**
957
+ * The path to the field to check for being touched.
958
+ */
959
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
960
+ }
961
+ /**
962
+ * Checks whether a specific field or the entire form is touched by walking
963
+ * through the field store and all its descendants. A field is touched once it
964
+ * has received and lost focus.
965
+ *
966
+ * @param form The form store to check for being touched.
967
+ *
968
+ * @returns Whether the field or form is touched.
969
+ */
970
+ declare function isTouched<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): boolean;
971
+ /**
972
+ * Checks whether a specific field or the entire form is touched by walking
973
+ * through the field store and all its descendants. A field is touched once it
974
+ * has received and lost focus.
975
+ *
976
+ * @param form The form store to check for being touched.
977
+ * @param config The is touched configuration.
978
+ *
979
+ * @returns Whether the field or form is touched.
980
+ */
981
+ declare function isTouched<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? IsFieldTouchedConfig<TSchema, TFieldPath> : IsFormTouchedConfig): boolean;
982
+ //#endregion
983
+ //#region src/isValid/isValid.d.ts
984
+ /**
985
+ * Is form valid config interface.
986
+ */
987
+ interface IsFormValidConfig {
988
+ /**
989
+ * The path to a field. Leave undefined to check the entire form.
990
+ */
991
+ readonly path?: undefined;
992
+ }
993
+ /**
994
+ * Is field valid config interface.
995
+ */
996
+ interface IsFieldValidConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
997
+ /**
998
+ * The path to the field to check for validity.
999
+ */
1000
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
1001
+ }
1002
+ /**
1003
+ * Checks whether a specific field or the entire form is valid by walking
1004
+ * through the field store and all its descendants. A field is valid when
1005
+ * neither it nor any of its descendants contains an error. Form-level errors
1006
+ * are included.
1007
+ *
1008
+ * @param form The form store to check for validity.
1009
+ *
1010
+ * @returns Whether the field or form is valid.
1011
+ */
1012
+ declare function isValid<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): boolean;
1013
+ /**
1014
+ * Checks whether a specific field or the entire form is valid by walking
1015
+ * through the field store and all its descendants. A field is valid when
1016
+ * neither it nor any of its descendants contains an error. Form-level errors
1017
+ * are included.
1018
+ *
1019
+ * @param form The form store to check for validity.
1020
+ * @param config The is valid configuration.
1021
+ *
1022
+ * @returns Whether the field or form is valid.
1023
+ */
1024
+ declare function isValid<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? IsFieldValidConfig<TSchema, TFieldPath> : IsFormValidConfig): boolean;
1025
+ //#endregion
715
1026
  //#region src/move/move.d.ts
716
1027
  /**
717
1028
  * Move array field config interface.
@@ -827,6 +1138,10 @@ interface ResetBaseConfig {
827
1138
  */
828
1139
  readonly keepTouched?: boolean | undefined;
829
1140
  /**
1141
+ * Whether to keep the edited state during reset. Defaults to false.
1142
+ */
1143
+ readonly keepEdited?: boolean | undefined;
1144
+ /**
830
1145
  * Whether to keep the error messages during reset. Defaults to false.
831
1146
  */
832
1147
  readonly keepErrors?: boolean | undefined;
@@ -1075,6 +1390,10 @@ interface FieldStore<TSchema extends FormSchema = FormSchema, TFieldPath extends
1075
1390
  */
1076
1391
  readonly isTouched: boolean;
1077
1392
  /**
1393
+ * Whether the field value has been edited.
1394
+ */
1395
+ readonly isEdited: boolean;
1396
+ /**
1078
1397
  * Whether the field input differs from its initial value.
1079
1398
  */
1080
1399
  readonly isDirty: boolean;
@@ -1112,6 +1431,10 @@ interface FieldArrayStore<TSchema extends FormSchema = FormSchema, TFieldArrayPa
1112
1431
  */
1113
1432
  readonly isTouched: boolean;
1114
1433
  /**
1434
+ * Whether the field array value has been edited.
1435
+ */
1436
+ readonly isEdited: boolean;
1437
+ /**
1115
1438
  * Whether the field array input differs from its initial value.
1116
1439
  */
1117
1440
  readonly isDirty: boolean;
@@ -1143,6 +1466,10 @@ interface FormStore<TSchema extends FormSchema = FormSchema> extends BaseFormSto
1143
1466
  */
1144
1467
  readonly isTouched: boolean;
1145
1468
  /**
1469
+ * Whether any field in the form has been edited.
1470
+ */
1471
+ readonly isEdited: boolean;
1472
+ /**
1146
1473
  * Whether any field in the form differs from its initial value.
1147
1474
  */
1148
1475
  readonly isDirty: boolean;
@@ -1154,7 +1481,7 @@ interface FormStore<TSchema extends FormSchema = FormSchema> extends BaseFormSto
1154
1481
  * The current error messages of the form.
1155
1482
  *
1156
1483
  * Hint: This property only contains validation errors at the root level
1157
- * of the form. To get all errors from all fields, use `getAllErrors`.
1484
+ * of the form. To get all errors from all fields, use `getDeepErrors`.
1158
1485
  */
1159
1486
  readonly errors: [string, ...string[]] | null;
1160
1487
  }
@@ -1301,4 +1628,4 @@ declare function useFieldArray<TSchema extends FormSchema, TFieldArrayPath exten
1301
1628
  */
1302
1629
  declare function useForm<TSchema extends FormSchema>(config: FormConfig<TSchema>): FormStore<TSchema>;
1303
1630
  //#endregion
1304
- export { type DeepPartial, Field, FieldArray, FieldArrayProps, FieldArrayStore, type FieldElement, FieldElementProps, FieldProps, FieldStore, FocusFieldConfig, Form, type FormConfig, FormProps, 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, type SetFieldInputConfig, SetFormErrorsConfig, type 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 };
1631
+ export { DeepErrorEntry, type DeepPartial, Field, FieldArray, FieldArrayProps, FieldArrayStore, type FieldElement, FieldElementProps, FieldProps, FieldStore, FocusFieldConfig, Form, type FormConfig, FormProps, type FormSchema, FormStore, GetFieldDeepErrorEntriesConfig, GetFieldDeepErrorsConfig, GetFieldDirtyInputConfig, GetFieldDirtyPathsConfig, GetFieldErrorsConfig, GetFieldInputConfig, GetFormDeepErrorEntriesConfig, GetFormDeepErrorsConfig, GetFormDirtyInputConfig, GetFormDirtyPathsConfig, GetFormErrorsConfig, GetFormInputConfig, InsertConfig, IsFieldDirtyConfig, IsFieldEditedConfig, IsFieldTouchedConfig, IsFieldValidConfig, IsFormDirtyConfig, IsFormEditedConfig, IsFormTouchedConfig, IsFormValidConfig, MoveConfig, type PartialValues, type PathValue, PickDirtyConfig, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, type SetFieldInputConfig, SetFormErrorsConfig, type SetFormInputConfig, type SubmitEventHandler, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, focus, getDeepErrorEntries, getDeepErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, isDirty, isEdited, isTouched, isValid, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };