@formisch/svelte 0.9.0 → 0.10.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 CHANGED
@@ -56,7 +56,7 @@ Every form starts with the `createForm` function. It initializes your form's sto
56
56
  </Form>
57
57
  ```
58
58
 
59
- In addition, Formisch offers several functions (we call them "methods") that can be used to read and manipulate the form state. These include `focus`, `getErrors`, `getAllErrors`, `getInput`, `insert`, `move`, `remove`, `replace`, `reset`, `setErrors`, `setInput`, `submit`, `swap` and `validate`. These methods allow you to control the form programmatically.
59
+ In addition, Formisch offers several functions (we call them "methods") that can be used to read and manipulate the form state. These include `focus`, `getDeepErrorEntries`, `getDeepErrors`, `getDirtyInput`, `getDirtyPaths`, `getErrors`, `getInput`, `handleSubmit`, `insert`, `isDirty`, `isEdited`, `isTouched`, `isValid`, `move`, `pickDirty`, `remove`, `replace`, `reset`, `setErrors`, `setInput`, `submit`, `swap` and `validate`. These methods allow you to control the form programmatically.
60
60
 
61
61
  ## Comparison
62
62
 
@@ -1,6 +1,177 @@
1
1
  import * as v from "valibot";
2
2
  import { untrack } from "svelte";
3
3
 
4
+ //#region src/types/utils/utils.d.ts
5
+ /**
6
+ * Checks if a type is `any`.
7
+ */
8
+ type IsAny<T> = 0 extends 1 & T ? true : false;
9
+ /**
10
+ * Checks if a type is `never`.
11
+ */
12
+ type IsNever<T> = [T] extends [never] ? true : false;
13
+ /**
14
+ * Constructs a type that is maybe a promise.
15
+ */
16
+ type MaybePromise<T> = T | Promise<T>;
17
+ /**
18
+ * Makes all properties deeply optional.
19
+ */
20
+ type DeepPartial<TValue> = TValue extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TValue]?: DeepPartial<TValue[TKey]> | undefined } : TValue | undefined;
21
+ /**
22
+ * Makes all value properties optional.
23
+ *
24
+ * Hint: For dynamic arrays, only plain objects and nested arrays have their
25
+ * values made optional. Primitives and class instances are kept as-is to avoid
26
+ * types like `(string | undefined)[]`.
27
+ */
28
+ 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;
29
+ //#endregion
30
+ //#region src/types/path/path.d.ts
31
+ /**
32
+ * Path key type.
33
+ */
34
+ type PathKey = string | number;
35
+ /**
36
+ * Path type.
37
+ */
38
+ type Path = readonly PathKey[];
39
+ /**
40
+ * Required path type.
41
+ */
42
+ type RequiredPath = readonly [PathKey, ...Path];
43
+ /**
44
+ * Extracts the exact keys of a tuple, array or object. Tuples return their
45
+ * literal numeric indices, dynamic arrays return `number`, objects return
46
+ * their `keyof` keys, and any other input returns `never`.
47
+ */
48
+ 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;
49
+ /**
50
+ * Returns the flat object of all indexable properties of `TValue`. For object
51
+ * unions, properties from every member are merged so that any single property
52
+ * is accessible. For primitives and other non-indexable types, the result is
53
+ * `{}`.
54
+ *
55
+ * Hint: This is necessary to make properties accessible across union members.
56
+ * By default, properties that do not exist in all union options are not
57
+ * accessible and result in "any" when accessed.
58
+ */
59
+ type PropertiesOf<TValue> = { [TKey in ExactKeysOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
60
+ /**
61
+ * Lazily evaluates only the first valid path segment based on the given value.
62
+ */
63
+ 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;
64
+ /**
65
+ * Returns the path if valid, otherwise the first possible valid path based on
66
+ * the given value.
67
+ */
68
+ type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
69
+ /**
70
+ * Detects whether the consuming project is configured with
71
+ * `exactOptionalPropertyTypes: true`.
72
+ *
73
+ * Hint: If `false` the built-in `Required<T>` strips `| undefined` from
74
+ * optional properties, so `Required<{ key?: undefined }>['key']` collapses
75
+ * to `never` — under strict mode the same expression yields `undefined`.
76
+ */
77
+ type IsExactOptionalProps = Required<{
78
+ key?: undefined;
79
+ }>["key"] extends never ? false : true;
80
+ /**
81
+ * Like the built-in `Required<T>`, but preserves `| undefined` in two
82
+ * places where `Required<T>` strips it:
83
+ *
84
+ * 1. Optional property values under `exactOptionalPropertyTypes: false`
85
+ * — without this, input typings for `v.optional`/`v.nullish` schemas
86
+ * narrow incorrectly (issue #15).
87
+ * 2. Array/tuple element types — e.g. `(string | undefined)[]` stays
88
+ * `(string | undefined)[]` instead of becoming `string[]`. Arrays
89
+ * fall through unchanged because they only have a numeric index
90
+ * signature and don't structurally extend `Record<PropertyKey,
91
+ * unknown>` (which requires string keys).
92
+ */
93
+ type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExactOptionalProps extends true ? Required<TValue> : { [TKey in keyof Required<TValue>]: TValue[TKey] } : TValue;
94
+ /**
95
+ * Extracts the value type at the given path.
96
+ */
97
+ 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;
98
+ /**
99
+ * Checks whether a value is a dynamic array or contains one anywhere in its
100
+ * shape. A fixed-length tuple is not itself a dynamic array, but it counts when
101
+ * it contains one, so paths can still navigate through tuples to reach nested
102
+ * arrays.
103
+ *
104
+ * Hint: The inner conditionals (`TValue extends readonly unknown[]` and
105
+ * `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
106
+ * so the inner expression returns the union of each member's result (e.g.
107
+ * `true | false` when some members contain arrays and others don't).
108
+ * Downstream code uses `IsOrHasArray<T> extends true`, but
109
+ * `boolean extends true` is `false` — so we collapse the result via
110
+ * `true extends ...`, which is `true` whenever at least one union member
111
+ * contributed `true`.
112
+ */
113
+ 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;
114
+ /**
115
+ * Extracts the exact keys of a tuple, array or object that contain arrays.
116
+ */
117
+ 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;
118
+ /**
119
+ * Returns the flat object of indexable properties of `TValue` whose values
120
+ * are or contain arrays. Mirrors `PropertiesOf` but keyed by
121
+ * `ExactKeysOfArrayPath` so the lookup is provably valid for array-path
122
+ * navigation in `LazyArrayPath`.
123
+ */
124
+ type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
125
+ /**
126
+ * Lazily evaluates only the first valid array path segment based on the given value.
127
+ */
128
+ 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;
129
+ /**
130
+ * Returns the path if valid, otherwise the first possible valid array path
131
+ * based on the given value.
132
+ */
133
+ type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
134
+ /**
135
+ * Recursive helper for `DirtyPath` that prepends `TKey` to each deeper path,
136
+ * or falls through to `never` when the child is not an object.
137
+ */
138
+ type DeepDirtyPath<TChild, TKey$1 extends PathKey, TDepth extends 0[]> = TChild extends Record<PropertyKey, unknown> ? readonly [TKey$1, ...DirtyPath<TChild, [...TDepth, 0]>] : never;
139
+ /**
140
+ * Returns the union of all `RequiredPath`s that `getDirtyPaths` can emit
141
+ * for a given input type. Object fields contribute their own path and the
142
+ * paths of their descendants; arrays and tuples are atomic and contribute
143
+ * only their own path, because dirty arrays are returned as complete units.
144
+ *
145
+ * Narrowing is exact for the first 5 levels of nesting; deeper paths fall
146
+ * back to `RequiredPath` to keep the result a complete superset of any
147
+ * path the runtime can address.
148
+ *
149
+ * Hint: Arrays and tuples are atomic because they don't structurally
150
+ * extend `Record<PropertyKey, unknown>` and so fall through to `never`
151
+ * via `DeepDirtyPath` — no explicit array check is needed. `TDepth` is
152
+ * a tuple-length counter capped at 5 to bound TypeScript instantiation
153
+ * cost.
154
+ */
155
+ 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;
156
+ /**
157
+ * Recursive helper for `FieldPath` that prepends `TKey` to each deeper field
158
+ * path, or falls through to `never` when the child is a leaf value.
159
+ */
160
+ 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;
161
+ /**
162
+ * Returns the union of all `RequiredPath`s that address a field within the
163
+ * given input type. Object and array fields contribute their own path and the
164
+ * paths of their descendants; unlike `DirtyPath`, arrays are recursed into so
165
+ * that fields at any depth, including array items, can be addressed. Leaf
166
+ * values contribute only their own path (emitted by their parent).
167
+ *
168
+ * Narrowing is exact for the first 5 levels of nesting; deeper paths fall
169
+ * back to `RequiredPath` to keep the result a complete superset of any path
170
+ * the runtime can address. `TDepth` is a tuple-length counter capped at 5 to
171
+ * bound TypeScript instantiation cost.
172
+ */
173
+ 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;
174
+ //#endregion
4
175
  //#region src/types/schema/schema.d.ts
5
176
  /**
6
177
  * Schema type.
@@ -73,6 +244,10 @@ interface InternalBaseStore {
73
244
  */
74
245
  name: string;
75
246
  /**
247
+ * The path to the field.
248
+ */
249
+ path: Path;
250
+ /**
76
251
  * The schema of the field.
77
252
  */
78
253
  schema: Schema;
@@ -100,6 +275,15 @@ interface InternalBaseStore {
100
275
  */
101
276
  isTouched: Signal<boolean>;
102
277
  /**
278
+ * The edited state of the field.
279
+ *
280
+ * Hint: Unlike `isTouched`, which is also set when a field is focused, this
281
+ * is only set when the field's value is changed. Unlike `isDirty`, it stays
282
+ * `true` even if the value is changed back to its initial value. It is only
283
+ * reset when the field is reset.
284
+ */
285
+ isEdited: Signal<boolean>;
286
+ /**
103
287
  * The dirty state of the field.
104
288
  */
105
289
  isDirty: Signal<boolean>;
@@ -113,6 +297,14 @@ interface InternalArrayStore extends InternalBaseStore {
113
297
  */
114
298
  kind: "array";
115
299
  /**
300
+ * Whether the array schema is wrapped in a nullish schema.
301
+ *
302
+ * Hint: This indicates whether a missing input should be represented as the
303
+ * nullish value (`null`/`undefined`) or as a present but empty array
304
+ * (`true`). It keeps resetting consistent with the initial state.
305
+ */
306
+ isNullish: boolean;
307
+ /**
116
308
  * The children of the array field.
117
309
  */
118
310
  children: InternalFieldStore[];
@@ -165,6 +357,14 @@ interface InternalObjectStore extends InternalBaseStore {
165
357
  */
166
358
  kind: "object";
167
359
  /**
360
+ * Whether the object schema is wrapped in a nullish schema.
361
+ *
362
+ * Hint: This indicates whether a missing input should be represented as the
363
+ * nullish value (`null`/`undefined`) or as a present but empty object
364
+ * (`true`). It keeps resetting consistent with the initial state.
365
+ */
366
+ isNullish: boolean;
367
+ /**
168
368
  * The children of the object field.
169
369
  */
170
370
  children: Record<string, InternalFieldStore>;
@@ -228,32 +428,6 @@ type InternalFieldStore = InternalArrayStore | InternalObjectStore | InternalVal
228
428
  */
229
429
  declare const INTERNAL: "~internal";
230
430
  //#endregion
231
- //#region src/types/utils/utils.d.ts
232
- /**
233
- * Checks if a type is `any`.
234
- */
235
- type IsAny<T> = 0 extends 1 & T ? true : false;
236
- /**
237
- * Checks if a type is `never`.
238
- */
239
- type IsNever<T> = [T] extends [never] ? true : false;
240
- /**
241
- * Constructs a type that is maybe a promise.
242
- */
243
- type MaybePromise<T> = T | Promise<T>;
244
- /**
245
- * Makes all properties deeply optional.
246
- */
247
- type DeepPartial<TValue> = TValue extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TValue]?: DeepPartial<TValue[TKey]> | undefined } : TValue | undefined;
248
- /**
249
- * Makes all value properties optional.
250
- *
251
- * Hint: For dynamic arrays, only plain objects and nested arrays have their
252
- * values made optional. Primitives and class instances are kept as-is to avoid
253
- * types like `(string | undefined)[]`.
254
- */
255
- 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;
256
- //#endregion
257
431
  //#region src/types/form/form.d.ts
258
432
  /**
259
433
  * Validation mode type.
@@ -337,139 +511,13 @@ type SubmitHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>
337
511
  */
338
512
  type SubmitEventHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
339
513
  //#endregion
340
- //#region src/types/path/path.d.ts
341
- /**
342
- * Path key type.
343
- */
344
- type PathKey = string | number;
345
- /**
346
- * Path type.
347
- */
348
- type Path = readonly PathKey[];
349
- /**
350
- * Required path type.
351
- */
352
- type RequiredPath = readonly [PathKey, ...Path];
353
- /**
354
- * Extracts the exact keys of a tuple, array or object. Tuples return their
355
- * literal numeric indices, dynamic arrays return `number`, objects return
356
- * their `keyof` keys, and any other input returns `never`.
357
- */
358
- 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;
359
- /**
360
- * Returns the flat object of all indexable properties of `TValue`. For object
361
- * unions, properties from every member are merged so that any single property
362
- * is accessible. For primitives and other non-indexable types, the result is
363
- * `{}`.
364
- *
365
- * Hint: This is necessary to make properties accessible across union members.
366
- * By default, properties that do not exist in all union options are not
367
- * accessible and result in "any" when accessed.
368
- */
369
- type PropertiesOf<TValue> = { [TKey in ExactKeysOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
370
- /**
371
- * Lazily evaluates only the first valid path segment based on the given value.
372
- */
373
- 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;
374
- /**
375
- * Returns the path if valid, otherwise the first possible valid path based on
376
- * the given value.
377
- */
378
- type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
379
- /**
380
- * Detects whether the consuming project is configured with
381
- * `exactOptionalPropertyTypes: true`.
382
- *
383
- * Hint: If `false` the built-in `Required<T>` strips `| undefined` from
384
- * optional properties, so `Required<{ key?: undefined }>['key']` collapses
385
- * to `never` — under strict mode the same expression yields `undefined`.
386
- */
387
- type IsExactOptionalProps = Required<{
388
- key?: undefined;
389
- }>["key"] extends never ? false : true;
390
- /**
391
- * Like the built-in `Required<T>`, but preserves `| undefined` in two
392
- * places where `Required<T>` strips it:
393
- *
394
- * 1. Optional property values under `exactOptionalPropertyTypes: false`
395
- * — without this, input typings for `v.optional`/`v.nullish` schemas
396
- * narrow incorrectly (issue #15).
397
- * 2. Array/tuple element types — e.g. `(string | undefined)[]` stays
398
- * `(string | undefined)[]` instead of becoming `string[]`. Arrays
399
- * fall through unchanged because they only have a numeric index
400
- * signature and don't structurally extend `Record<PropertyKey,
401
- * unknown>` (which requires string keys).
402
- */
403
- type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExactOptionalProps extends true ? Required<TValue> : { [TKey in keyof Required<TValue>]: TValue[TKey] } : TValue;
404
- /**
405
- * Extracts the value type at the given path.
406
- */
407
- 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;
408
- /**
409
- * Checks whether a value is a dynamic array or contains one anywhere in its
410
- * shape. A fixed-length tuple is not itself a dynamic array, but it counts when
411
- * it contains one, so paths can still navigate through tuples to reach nested
412
- * arrays.
413
- *
414
- * Hint: The inner conditionals (`TValue extends readonly unknown[]` and
415
- * `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
416
- * so the inner expression returns the union of each member's result (e.g.
417
- * `true | false` when some members contain arrays and others don't).
418
- * Downstream code uses `IsOrHasArray<T> extends true`, but
419
- * `boolean extends true` is `false` — so we collapse the result via
420
- * `true extends ...`, which is `true` whenever at least one union member
421
- * contributed `true`.
422
- */
423
- 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;
424
- /**
425
- * Extracts the exact keys of a tuple, array or object that contain arrays.
426
- */
427
- 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;
428
- /**
429
- * Returns the flat object of indexable properties of `TValue` whose values
430
- * are or contain arrays. Mirrors `PropertiesOf` but keyed by
431
- * `ExactKeysOfArrayPath` so the lookup is provably valid for array-path
432
- * navigation in `LazyArrayPath`.
433
- */
434
- type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
435
- /**
436
- * Lazily evaluates only the first valid array path segment based on the given value.
437
- */
438
- 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;
439
- /**
440
- * Returns the path if valid, otherwise the first possible valid array path
441
- * based on the given value.
442
- */
443
- type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
444
- /**
445
- * Recursive helper for `DirtyPath` that prepends `TKey` to each deeper path,
446
- * or falls through to `never` when the child is not an object.
447
- */
448
- type DeepDirtyPath<TChild, TKey$1 extends PathKey, TDepth extends 0[]> = TChild extends Record<PropertyKey, unknown> ? readonly [TKey$1, ...DirtyPath<TChild, [...TDepth, 0]>] : never;
449
- /**
450
- * Returns the union of all `RequiredPath`s that `getDirtyPaths` can emit
451
- * for a given input type. Object fields contribute their own path and the
452
- * paths of their descendants; arrays and tuples are atomic and contribute
453
- * only their own path, because dirty arrays are returned as complete units.
454
- *
455
- * Narrowing is exact for the first 5 levels of nesting; deeper paths fall
456
- * back to `RequiredPath` to keep the result a complete superset of any
457
- * path the runtime can address.
458
- *
459
- * Hint: Arrays and tuples are atomic because they don't structurally
460
- * extend `Record<PropertyKey, unknown>` and so fall through to `never`
461
- * via `DeepDirtyPath` — no explicit array check is needed. `TDepth` is
462
- * a tuple-length counter capped at 5 to bound TypeScript instantiation
463
- * cost.
464
- */
465
- 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;
466
- //#endregion
467
514
  //#region src/array/copyItemState/copyItemState.d.ts
468
515
  /**
469
516
  * Copies the deeply nested state (signal values) from one field store to
470
517
  * another. This includes the `elements`, `errors`, `startInput`, `input`,
471
- * `isTouched`, `isDirty`, and for arrays `startItems` and `items` properties.
472
- * Recursively walks through the field stores and copies all signal values.
518
+ * `isTouched`, `isEdited`, `isDirty`, and for arrays `startItems` and `items`
519
+ * properties. Recursively walks through the field stores and copies all signal
520
+ * values.
473
521
  *
474
522
  * @param fromInternalFieldStore The source field store to copy from.
475
523
  * @param toInternalFieldStore The destination field store to copy to.
@@ -479,10 +527,10 @@ declare function copyItemState(fromInternalFieldStore: InternalFieldStore, toInt
479
527
  //#region src/array/resetItemState/resetItemState.d.ts
480
528
  /**
481
529
  * Resets the state of a field store (signal values) deeply nested. Sets
482
- * `elements` to empty array, `errors` to `null`, `isTouched` and `isDirty` to
483
- * `false`, and `startInput`, `input`, `startItems`, and `items` to the new
484
- * input value. Keeps the `initialInput` and `initialItems` state unchanged for
485
- * form reset functionality.
530
+ * `elements` to empty array, `errors` to `null`, `isTouched`, `isEdited` and
531
+ * `isDirty` to `false`, and `startInput`, `input`, `startItems`, and `items` to
532
+ * the new input value. Keeps the `initialInput` and `initialItems` state
533
+ * unchanged for form reset functionality.
486
534
  *
487
535
  * @param internalFieldStore The field store to reset.
488
536
  * @param input The new input value (can be any type including array or object).
@@ -496,8 +544,8 @@ declare function resetItemState(internalFieldStore: InternalFieldStore, input: u
496
544
  /**
497
545
  * Swaps the deeply nested state (signal values) between two field stores. This
498
546
  * includes the `elements`, `errors`, `startInput`, `input`, `isTouched`,
499
- * `isDirty`, and for arrays `startItems` and `items` properties. Recursively
500
- * walks through the field stores and swaps all signal values.
547
+ * `isEdited`, `isDirty`, and for arrays `startItems` and `items` properties.
548
+ * Recursively walks through the field stores and swaps all signal values.
501
549
  *
502
550
  * @param firstInternalFieldStore The first field store to swap.
503
551
  * @param secondInternalFieldStore The second field store to swap.
@@ -558,7 +606,7 @@ declare function getElementInput(element: FieldElement, internalFieldStore: Inte
558
606
  *
559
607
  * @returns Whether the property is true.
560
608
  */
561
- declare function getFieldBool(internalFieldStore: InternalFieldStore, type: "errors" | "isTouched" | "isDirty"): boolean;
609
+ declare function getFieldBool(internalFieldStore: InternalFieldStore, type: "errors" | "isTouched" | "isEdited" | "isDirty"): boolean;
562
610
  //#endregion
563
611
  //#region src/field/getFieldInput/getFieldInput.d.ts
564
612
  /**
@@ -597,7 +645,7 @@ type FieldSchema = v.ArraySchema<v.BaseSchema<unknown, unknown, v.BaseIssue<unkn
597
645
  * @param path The path to the field in the form.
598
646
  * @param nullish Whether the schema is wrapped in a nullish schema.
599
647
  */
600
- declare function initializeFieldStore(internalFieldStore: Partial<InternalFieldStore>, schema: FieldSchema, initialInput: unknown, path: PathKey[], nullish?: boolean): void;
648
+ declare function initializeFieldStore(internalFieldStore: Partial<InternalFieldStore>, schema: FieldSchema, initialInput: unknown, path: Path, nullish?: boolean): void;
601
649
  //#endregion
602
650
  //#region src/field/setFieldBool/setFieldBool.d.ts
603
651
  /**
@@ -635,12 +683,19 @@ declare function setInitialFieldInput(internalFieldStore: InternalFieldStore, in
635
683
  //#region src/field/walkFieldStore/walkFieldStore.d.ts
636
684
  /**
637
685
  * Walks through the field store and all nested children, calling the callback
638
- * for each field store in depth-first order.
686
+ * for each field store in depth-first order. The callback may return `true` to
687
+ * stop the walk early, in which case `walkFieldStore` returns `true` as well.
688
+ *
689
+ * The walk reads array `items` reactively, so a reactive caller subscribes to
690
+ * structural changes naturally. Imperative callers that must not subscribe
691
+ * (e.g. when invoked inside an effect) should wrap the call in `untrack`.
639
692
  *
640
693
  * @param internalFieldStore The field store to walk.
641
- * @param callback The callback to invoke for each field store.
694
+ * @param callback The callback to invoke for each field store. Return `true` to stop the walk early.
695
+ *
696
+ * @returns Whether the walk was stopped early by the callback.
642
697
  */
643
- declare function walkFieldStore(internalFieldStore: InternalFieldStore, callback: (internalFieldStore: InternalFieldStore) => void): void;
698
+ declare function walkFieldStore(internalFieldStore: InternalFieldStore, callback: (internalFieldStore: InternalFieldStore) => boolean | void): boolean;
644
699
  //#endregion
645
700
  //#region src/form/createFormStore/createFormStore.d.ts
646
701
  /**
@@ -741,4 +796,4 @@ declare function createSignal<T>(initialValue: T): Signal<T>;
741
796
  */
742
797
  declare function batch<T>(fn: () => T): T;
743
798
  //#endregion
744
- export { BaseFormStore, Batch, DeepPartial, DirtyPath, FieldElement, FieldSchema, FormConfig, FormSchema, INTERNAL, InternalArrayStore, InternalBaseStore, InternalFieldStore, InternalFormStore, InternalObjectStore, InternalValueStore, IsAny, IsNever, MaybePromise, PartialValues, Path, PathKey, PathValue, RequiredPath, Schema, Signal, SubmitEventHandler, SubmitHandler, Untrack, ValidArrayPath, ValidPath, ValidateFormInputConfig, ValidationMode, batch, copyItemState, createFormStore, createId, createSignal, decodeFormData, focusFieldElement, framework, getDirtyFieldInput, getElementInput, getFieldBool, getFieldInput, getFieldStore, initializeFieldStore, resetItemState, setFieldBool, setFieldInput, setInitialFieldInput, swapItemState, untrack, validateFormInput, validateIfRequired, walkFieldStore };
799
+ export { BaseFormStore, Batch, DeepPartial, DirtyPath, FieldElement, FieldPath, FieldSchema, FormConfig, FormSchema, INTERNAL, InternalArrayStore, InternalBaseStore, InternalFieldStore, InternalFormStore, InternalObjectStore, InternalValueStore, IsAny, IsNever, MaybePromise, PartialValues, Path, PathKey, PathValue, RequiredPath, Schema, Signal, SubmitEventHandler, SubmitHandler, Untrack, ValidArrayPath, ValidPath, ValidateFormInputConfig, ValidationMode, batch, copyItemState, createFormStore, createId, createSignal, decodeFormData, focusFieldElement, framework, getDirtyFieldInput, getElementInput, getFieldBool, getFieldInput, getFieldStore, initializeFieldStore, resetItemState, setFieldBool, setFieldInput, setInitialFieldInput, swapItemState, untrack, validateFormInput, validateIfRequired, walkFieldStore };