@formisch/svelte 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 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
@@ -59,7 +60,13 @@ In addition, Formisch offers several functions (we call them "methods") that can
59
60
 
60
61
  ## Comparison
61
62
 
62
- 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. The result is a small bundle size and native performance for any UI update. This feature, along with a few others, distinguishes Formisch from other form libraries. My vision for Formisch is to create a framework-agnostic platform similar to [Vite](https://vite.dev/), but for forms.
63
+ 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.
64
+
65
+ For a side-by-side look at how Formisch compares to Superforms and TanStack Form, see the [comparison guide](https://formisch.dev/svelte/guides/comparison/).
66
+
67
+ ## Vision
68
+
69
+ 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.
63
70
 
64
71
  ## Partners
65
72
 
@@ -1,8 +1,12 @@
1
1
  <script
2
2
  lang="ts"
3
- generics="TSchema extends Schema, TFieldPath extends RequiredPath"
3
+ generics="TSchema extends FormSchema, TFieldPath extends RequiredPath"
4
4
  >
5
- import type { RequiredPath, Schema, ValidPath } from '../../core/index.svelte';
5
+ import type {
6
+ RequiredPath,
7
+ FormSchema,
8
+ ValidPath,
9
+ } from '../../core/index.svelte';
6
10
  import type * as v from 'valibot';
7
11
  import { useField } from '../../runes/index';
8
12
  import type { FieldStore, FormStore } from '../../types/index';
@@ -12,7 +16,7 @@
12
16
  * Field component props interface.
13
17
  */
14
18
  export interface FieldProps<
15
- TSchema extends Schema = Schema,
19
+ TSchema extends FormSchema = FormSchema,
16
20
  TFieldPath extends RequiredPath = RequiredPath,
17
21
  > {
18
22
  /**
@@ -1,11 +1,11 @@
1
- import type { RequiredPath, Schema, ValidPath } from '../../core/index.svelte';
1
+ import type { RequiredPath, FormSchema, ValidPath } from '../../core/index.svelte';
2
2
  import type * as v from 'valibot';
3
3
  import type { FieldStore, FormStore } from '../../types/index';
4
4
  import type { Snippet } from 'svelte';
5
5
  /**
6
6
  * Field component props interface.
7
7
  */
8
- export interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
8
+ export interface FieldProps<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
9
9
  /**
10
10
  * The form store to which the field belongs.
11
11
  */
@@ -19,14 +19,14 @@ export interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends
19
19
  */
20
20
  readonly children: Snippet<[FieldStore<TSchema, TFieldPath>]>;
21
21
  }
22
- declare function $$render<TSchema extends Schema, TFieldPath extends RequiredPath>(): {
22
+ declare function $$render<TSchema extends FormSchema, TFieldPath extends RequiredPath>(): {
23
23
  props: FieldProps<TSchema, TFieldPath>;
24
24
  exports: {};
25
25
  bindings: "";
26
26
  slots: {};
27
27
  events: {};
28
28
  };
29
- declare class __sveltets_Render<TSchema extends Schema, TFieldPath extends RequiredPath> {
29
+ declare class __sveltets_Render<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
30
30
  props(): ReturnType<typeof $$render<TSchema, TFieldPath>>['props'];
31
31
  events(): ReturnType<typeof $$render<TSchema, TFieldPath>>['events'];
32
32
  slots(): ReturnType<typeof $$render<TSchema, TFieldPath>>['slots'];
@@ -34,12 +34,12 @@ declare class __sveltets_Render<TSchema extends Schema, TFieldPath extends Requi
34
34
  exports(): {};
35
35
  }
36
36
  interface $$IsomorphicComponent {
37
- new <TSchema extends Schema, TFieldPath extends RequiredPath>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TSchema, TFieldPath>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TSchema, TFieldPath>['props']>, ReturnType<__sveltets_Render<TSchema, TFieldPath>['events']>, ReturnType<__sveltets_Render<TSchema, TFieldPath>['slots']>> & {
37
+ new <TSchema extends FormSchema, TFieldPath extends RequiredPath>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TSchema, TFieldPath>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TSchema, TFieldPath>['props']>, ReturnType<__sveltets_Render<TSchema, TFieldPath>['events']>, ReturnType<__sveltets_Render<TSchema, TFieldPath>['slots']>> & {
38
38
  $$bindings?: ReturnType<__sveltets_Render<TSchema, TFieldPath>['bindings']>;
39
39
  } & ReturnType<__sveltets_Render<TSchema, TFieldPath>['exports']>;
40
- <TSchema extends Schema, TFieldPath extends RequiredPath>(internal: unknown, props: ReturnType<__sveltets_Render<TSchema, TFieldPath>['props']> & {}): ReturnType<__sveltets_Render<TSchema, TFieldPath>['exports']>;
40
+ <TSchema extends FormSchema, TFieldPath extends RequiredPath>(internal: unknown, props: ReturnType<__sveltets_Render<TSchema, TFieldPath>['props']> & {}): ReturnType<__sveltets_Render<TSchema, TFieldPath>['exports']>;
41
41
  z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
42
42
  }
43
43
  declare const Field: $$IsomorphicComponent;
44
- type Field<TSchema extends Schema, TFieldPath extends RequiredPath> = InstanceType<typeof Field<TSchema, TFieldPath>>;
44
+ type Field<TSchema extends FormSchema, TFieldPath extends RequiredPath> = InstanceType<typeof Field<TSchema, TFieldPath>>;
45
45
  export default Field;
@@ -1,10 +1,10 @@
1
1
  <script
2
2
  lang="ts"
3
- generics="TSchema extends Schema, TFieldArrayPath extends RequiredPath"
3
+ generics="TSchema extends FormSchema, TFieldArrayPath extends RequiredPath"
4
4
  >
5
5
  import type {
6
6
  RequiredPath,
7
- Schema,
7
+ FormSchema,
8
8
  ValidArrayPath,
9
9
  } from '../../core/index.svelte';
10
10
  import type * as v from 'valibot';
@@ -16,7 +16,7 @@
16
16
  * Field array component props interface.
17
17
  */
18
18
  export interface FieldArrayProps<
19
- TSchema extends Schema = Schema,
19
+ TSchema extends FormSchema = FormSchema,
20
20
  TFieldArrayPath extends RequiredPath = RequiredPath,
21
21
  > {
22
22
  /**
@@ -1,11 +1,11 @@
1
- import type { RequiredPath, Schema, ValidArrayPath } from '../../core/index.svelte';
1
+ import type { RequiredPath, FormSchema, ValidArrayPath } from '../../core/index.svelte';
2
2
  import type * as v from 'valibot';
3
3
  import type { FieldArrayStore, FormStore } from '../../types/index';
4
4
  import type { Snippet } from 'svelte';
5
5
  /**
6
6
  * Field array component props interface.
7
7
  */
8
- export interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath extends RequiredPath = RequiredPath> {
8
+ export interface FieldArrayProps<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
9
9
  /**
10
10
  * The form store to which the field array belongs.
11
11
  */
@@ -19,14 +19,14 @@ export interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPat
19
19
  */
20
20
  readonly children: Snippet<[FieldArrayStore<TSchema, TFieldArrayPath>]>;
21
21
  }
22
- declare function $$render<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(): {
22
+ declare function $$render<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(): {
23
23
  props: FieldArrayProps<TSchema, TFieldArrayPath>;
24
24
  exports: {};
25
25
  bindings: "";
26
26
  slots: {};
27
27
  events: {};
28
28
  };
29
- declare class __sveltets_Render<TSchema extends Schema, TFieldArrayPath extends RequiredPath> {
29
+ declare class __sveltets_Render<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
30
30
  props(): ReturnType<typeof $$render<TSchema, TFieldArrayPath>>['props'];
31
31
  events(): ReturnType<typeof $$render<TSchema, TFieldArrayPath>>['events'];
32
32
  slots(): ReturnType<typeof $$render<TSchema, TFieldArrayPath>>['slots'];
@@ -34,12 +34,12 @@ declare class __sveltets_Render<TSchema extends Schema, TFieldArrayPath extends
34
34
  exports(): {};
35
35
  }
36
36
  interface $$IsomorphicComponent {
37
- new <TSchema extends Schema, TFieldArrayPath extends RequiredPath>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['props']>, ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['events']>, ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['slots']>> & {
37
+ new <TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['props']>, ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['events']>, ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['slots']>> & {
38
38
  $$bindings?: ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['bindings']>;
39
39
  } & ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['exports']>;
40
- <TSchema extends Schema, TFieldArrayPath extends RequiredPath>(internal: unknown, props: ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['props']> & {}): ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['exports']>;
40
+ <TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(internal: unknown, props: ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['props']> & {}): ReturnType<__sveltets_Render<TSchema, TFieldArrayPath>['exports']>;
41
41
  z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
42
42
  }
43
43
  declare const FieldArray: $$IsomorphicComponent;
44
- type FieldArray<TSchema extends Schema, TFieldArrayPath extends RequiredPath> = InstanceType<typeof FieldArray<TSchema, TFieldArrayPath>>;
44
+ type FieldArray<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> = InstanceType<typeof FieldArray<TSchema, TFieldArrayPath>>;
45
45
  export default FieldArray;
@@ -1,7 +1,7 @@
1
- <script lang="ts" generics="TSchema extends Schema = Schema">
1
+ <script lang="ts" generics="TSchema extends FormSchema = FormSchema">
2
2
  import {
3
3
  INTERNAL,
4
- type Schema,
4
+ type FormSchema,
5
5
  type SubmitEventHandler,
6
6
  } from '../../core/index.svelte';
7
7
  import { handleSubmit } from '../../methods/index.svelte';
@@ -12,7 +12,7 @@
12
12
  /**
13
13
  * Form component props type.
14
14
  */
15
- export type FormProps<TSchema extends Schema = Schema> = Omit<
15
+ export type FormProps<TSchema extends FormSchema = FormSchema> = Omit<
16
16
  HTMLFormAttributes,
17
17
  'on:submit' | 'onsubmit' | 'novalidate'
18
18
  > & {
@@ -1,11 +1,11 @@
1
- import { type Schema, type SubmitEventHandler } from '../../core/index.svelte';
1
+ import { type FormSchema, type SubmitEventHandler } from '../../core/index.svelte';
2
2
  import type { FormStore } from '../../types/index';
3
3
  import type { Snippet } from 'svelte';
4
4
  import type { HTMLFormAttributes } from 'svelte/elements';
5
5
  /**
6
6
  * Form component props type.
7
7
  */
8
- export type FormProps<TSchema extends Schema = Schema> = Omit<HTMLFormAttributes, 'on:submit' | 'onsubmit' | 'novalidate'> & {
8
+ export type FormProps<TSchema extends FormSchema = FormSchema> = Omit<HTMLFormAttributes, 'on:submit' | 'onsubmit' | 'novalidate'> & {
9
9
  /**
10
10
  * The form store instance.
11
11
  */
@@ -19,14 +19,14 @@ export type FormProps<TSchema extends Schema = Schema> = Omit<HTMLFormAttributes
19
19
  */
20
20
  children: Snippet;
21
21
  };
22
- declare function $$render<TSchema extends Schema = Schema>(): {
22
+ declare function $$render<TSchema extends FormSchema = FormSchema>(): {
23
23
  props: FormProps<TSchema>;
24
24
  exports: {};
25
25
  bindings: "";
26
26
  slots: {};
27
27
  events: {};
28
28
  };
29
- declare class __sveltets_Render<TSchema extends Schema = Schema> {
29
+ declare class __sveltets_Render<TSchema extends FormSchema = FormSchema> {
30
30
  props(): ReturnType<typeof $$render<TSchema>>['props'];
31
31
  events(): ReturnType<typeof $$render<TSchema>>['events'];
32
32
  slots(): ReturnType<typeof $$render<TSchema>>['slots'];
@@ -34,12 +34,12 @@ declare class __sveltets_Render<TSchema extends Schema = Schema> {
34
34
  exports(): {};
35
35
  }
36
36
  interface $$IsomorphicComponent {
37
- new <TSchema extends Schema = Schema>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TSchema>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TSchema>['props']>, ReturnType<__sveltets_Render<TSchema>['events']>, ReturnType<__sveltets_Render<TSchema>['slots']>> & {
37
+ new <TSchema extends FormSchema = FormSchema>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TSchema>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TSchema>['props']>, ReturnType<__sveltets_Render<TSchema>['events']>, ReturnType<__sveltets_Render<TSchema>['slots']>> & {
38
38
  $$bindings?: ReturnType<__sveltets_Render<TSchema>['bindings']>;
39
39
  } & ReturnType<__sveltets_Render<TSchema>['exports']>;
40
- <TSchema extends Schema = Schema>(internal: unknown, props: ReturnType<__sveltets_Render<TSchema>['props']> & {}): ReturnType<__sveltets_Render<TSchema>['exports']>;
40
+ <TSchema extends FormSchema = FormSchema>(internal: unknown, props: ReturnType<__sveltets_Render<TSchema>['props']> & {}): ReturnType<__sveltets_Render<TSchema>['exports']>;
41
41
  z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
42
42
  }
43
43
  declare const Form: $$IsomorphicComponent;
44
- type Form<TSchema extends Schema = Schema> = InstanceType<typeof Form<TSchema>>;
44
+ type Form<TSchema extends FormSchema = FormSchema> = InstanceType<typeof Form<TSchema>>;
45
45
  export default Form;
@@ -6,6 +6,31 @@ import { untrack } from "svelte";
6
6
  * Schema type.
7
7
  */
8
8
  type Schema = v.GenericSchema | v.GenericSchemaAsync;
9
+ /**
10
+ * Object schema type.
11
+ */
12
+ 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>;
13
+ /**
14
+ * Object schema async type.
15
+ */
16
+ 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>;
17
+ /**
18
+ * Object root schema type.
19
+ */
20
+ type ObjectRootSchema = ObjectSchema | v.IntersectSchema<ObjectSchema[], v.ErrorMessage<v.IntersectIssue> | undefined> | v.UnionSchema<ObjectSchema[], v.ErrorMessage<v.UnionIssue<v.BaseIssue<unknown>>> | undefined>;
21
+ /**
22
+ * Object root schema async type.
23
+ */
24
+ type ObjectRootSchemaAsync = ObjectSchemaAsync | v.IntersectSchemaAsync<(ObjectSchema | ObjectSchemaAsync)[], v.ErrorMessage<v.IntersectIssue> | undefined> | v.UnionSchemaAsync<(ObjectSchema | ObjectSchemaAsync)[], v.ErrorMessage<v.UnionIssue<v.BaseIssue<unknown>>> | undefined>;
25
+ /**
26
+ * Form schema type.
27
+ *
28
+ * Hint: Forms must have an object root, so only object schemas (sync or async),
29
+ * combinators (intersect, union, variant) whose options resolve to objects, and
30
+ * `lazy` schemas wrapping any of these are allowed at the top level. Use
31
+ * {@link Schema} for nested field schemas.
32
+ */
33
+ type FormSchema = ObjectRootSchema | ObjectRootSchemaAsync | v.LazySchema<ObjectRootSchema> | v.LazySchemaAsync<ObjectRootSchema | ObjectRootSchemaAsync>;
9
34
  //#endregion
10
35
  //#region src/types/signal/signal.d.ts
11
36
  /**
@@ -53,6 +78,13 @@ interface InternalBaseStore {
53
78
  schema: Schema;
54
79
  /**
55
80
  * The initial elements of the field.
81
+ *
82
+ * Hint: This may look unused, but do not remove it. `copyItemState` and
83
+ * `swapItemState` move the `elements` reference between field stores when
84
+ * array items are inserted, moved, removed or swapped, and `reset` restores
85
+ * each field's original element via `elements = initialElements`. Without it,
86
+ * focus and file reset target the wrong element after a reorder followed by a
87
+ * reset.
56
88
  */
57
89
  initialElements: FieldElement[];
58
90
  /**
@@ -230,7 +262,7 @@ type ValidationMode = "initial" | "touch" | "input" | "change" | "blur" | "submi
230
262
  /**
231
263
  * Form config interface.
232
264
  */
233
- interface FormConfig<TSchema extends Schema = Schema> {
265
+ interface FormConfig<TSchema extends FormSchema = FormSchema> {
234
266
  /**
235
267
  * The schema of the form.
236
268
  */
@@ -251,7 +283,7 @@ interface FormConfig<TSchema extends Schema = Schema> {
251
283
  /**
252
284
  * Internal form store interface.
253
285
  */
254
- interface InternalFormStore<TSchema extends Schema = Schema> extends InternalObjectStore {
286
+ interface InternalFormStore<TSchema extends FormSchema = FormSchema> extends InternalObjectStore {
255
287
  /**
256
288
  * The element of the form.
257
289
  */
@@ -288,7 +320,7 @@ interface InternalFormStore<TSchema extends Schema = Schema> extends InternalObj
288
320
  /**
289
321
  * Base form store interface.
290
322
  */
291
- interface BaseFormStore<TSchema extends Schema = Schema> {
323
+ interface BaseFormStore<TSchema extends FormSchema = FormSchema> {
292
324
  /**
293
325
  * The internal form store.
294
326
  *
@@ -299,11 +331,11 @@ interface BaseFormStore<TSchema extends Schema = Schema> {
299
331
  /**
300
332
  * Submit handler type.
301
333
  */
302
- type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>) => MaybePromise<unknown>;
334
+ type SubmitHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>) => MaybePromise<unknown>;
303
335
  /**
304
336
  * Submit event handler type.
305
337
  */
306
- type SubmitEventHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
338
+ type SubmitEventHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
307
339
  //#endregion
308
340
  //#region src/types/path/path.d.ts
309
341
  /**
@@ -374,7 +406,10 @@ type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExa
374
406
  */
375
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;
376
408
  /**
377
- * Checks whether a value is an array or contains one anywhere in its shape.
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.
378
413
  *
379
414
  * Hint: The inner conditionals (`TValue extends readonly unknown[]` and
380
415
  * `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
@@ -385,7 +420,7 @@ type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey,
385
420
  * `true extends ...`, which is `true` whenever at least one union member
386
421
  * contributed `true`.
387
422
  */
388
- 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;
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;
389
424
  /**
390
425
  * Extracts the exact keys of a tuple, array or object that contain arrays.
391
426
  */
@@ -400,12 +435,34 @@ type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: T
400
435
  /**
401
436
  * Lazily evaluates only the first valid array path segment based on the given value.
402
437
  */
403
- 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;
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;
404
439
  /**
405
440
  * Returns the path if valid, otherwise the first possible valid array path
406
441
  * based on the given value.
407
442
  */
408
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;
409
466
  //#endregion
410
467
  //#region src/array/copyItemState/copyItemState.d.ts
411
468
  /**
@@ -428,9 +485,12 @@ declare function copyItemState(fromInternalFieldStore: InternalFieldStore, toInt
428
485
  * form reset functionality.
429
486
  *
430
487
  * @param internalFieldStore The field store to reset.
431
- * @param initialInput The new input value (can be any type including array or object).
488
+ * @param input The new input value (can be any type including array or object).
489
+ * @param keepStart Whether to keep `startInput` and `startItems` as the dirty
490
+ * baseline instead of resetting them to the new input. Used when a field store
491
+ * is reused for an in-place edit so its dirty state is detected correctly.
432
492
  */
433
- declare function resetItemState(internalFieldStore: InternalFieldStore, initialInput: unknown): void;
493
+ declare function resetItemState(internalFieldStore: InternalFieldStore, input: unknown, keepStart?: boolean): void;
434
494
  //#endregion
435
495
  //#region src/array/swapItemState/swapItemState.d.ts
436
496
  /**
@@ -444,6 +504,38 @@ declare function resetItemState(internalFieldStore: InternalFieldStore, initialI
444
504
  */
445
505
  declare function swapItemState(firstInternalFieldStore: InternalFieldStore, secondInternalFieldStore: InternalFieldStore): void;
446
506
  //#endregion
507
+ //#region src/field/focusFieldElement/focusFieldElement.d.ts
508
+ /**
509
+ * Focuses the first focusable element of a field store. The elements are tried
510
+ * in order and the first one that actually receives focus wins, so detached,
511
+ * disabled or hidden elements are skipped. The browser decides focusability,
512
+ * which is read back via the element's root `activeElement` so elements in a
513
+ * shadow root or another document are handled correctly.
514
+ *
515
+ * Hint: A `display: none` or `hidden` element is correctly skipped in real
516
+ * browsers, but jsdom has no layout and focuses it anyway, so that case cannot
517
+ * be covered by unit tests.
518
+ *
519
+ * @param internalFieldStore The field store to focus.
520
+ *
521
+ * @returns Whether an element was focused.
522
+ */
523
+ declare function focusFieldElement(internalFieldStore: InternalFieldStore): boolean;
524
+ //#endregion
525
+ //#region src/field/getDirtyFieldInput/getDirtyFieldInput.d.ts
526
+ /**
527
+ * Returns only the dirty input of the field store. Arrays are treated as
528
+ * atomic and returned in full if any item is dirty, while object keys without
529
+ * a dirty descendant are omitted. Returns `undefined` if no descendant is
530
+ * dirty.
531
+ *
532
+ * @param internalFieldStore The field store to get dirty input from.
533
+ * @param dirtyOnly Whether to only include dirty fields. Defaults to `true`.
534
+ *
535
+ * @returns The dirty input, or `undefined` if no descendant is dirty.
536
+ */
537
+ declare function getDirtyFieldInput(internalFieldStore: InternalFieldStore, dirtyOnly?: boolean): unknown;
538
+ //#endregion
447
539
  //#region src/field/getElementInput/getElementInput.d.ts
448
540
  /**
449
541
  * Returns the current input of the element. Handles special cases for select
@@ -561,7 +653,24 @@ declare function walkFieldStore(internalFieldStore: InternalFieldStore, callback
561
653
  *
562
654
  * @returns The internal form store.
563
655
  */
564
- declare function createFormStore(config: FormConfig, parse: (input: unknown) => Promise<v.SafeParseResult<Schema>>): InternalFormStore;
656
+ declare function createFormStore(config: FormConfig, parse: (input: unknown) => Promise<v.SafeParseResult<FormSchema>>): InternalFormStore;
657
+ //#endregion
658
+ //#region src/form/decodeFormData/decodeFormData.d.ts
659
+ /**
660
+ * Decodes the entries of a form data object into nested form values using the
661
+ * Valibot schema as the source of truth. Information that is lost during the
662
+ * transfer via HTTP, like numbers, booleans, dates and unchecked checkboxes,
663
+ * is restored based on the schema.
664
+ *
665
+ * The keys of the form data are expected to be the stringified field paths that
666
+ * Formisch assigns to its field elements (for example `["todos",0,"label"]`).
667
+ *
668
+ * @param schema The form schema.
669
+ * @param formData The form data object.
670
+ *
671
+ * @returns The decoded form values.
672
+ */
673
+ declare function decodeFormData<TSchema extends FormSchema>(schema: TSchema, formData: FormData): unknown;
565
674
  //#endregion
566
675
  //#region src/form/validateFormInput/validateFormInput.d.ts
567
676
  /**
@@ -601,7 +710,7 @@ declare function validateIfRequired(internalFormStore: InternalFormStore, intern
601
710
  /**
602
711
  * Framework type.
603
712
  */
604
- type Framework = "preact" | "qwik" | "react" | "solid" | "svelte" | "vue";
713
+ type Framework = "angular" | "preact" | "qwik" | "react" | "solid" | "svelte" | "vue";
605
714
  //#endregion
606
715
  //#region src/framework/index.svelte.d.ts
607
716
  /**
@@ -632,4 +741,4 @@ declare function createSignal<T>(initialValue: T): Signal<T>;
632
741
  */
633
742
  declare function batch<T>(fn: () => T): T;
634
743
  //#endregion
635
- export { BaseFormStore, Batch, DeepPartial, FieldElement, FieldSchema, FormConfig, 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, framework, getElementInput, getFieldBool, getFieldInput, getFieldStore, initializeFieldStore, resetItemState, setFieldBool, setFieldInput, setInitialFieldInput, swapItemState, untrack, validateFormInput, validateIfRequired, walkFieldStore };
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 };