@formisch/solid 0.9.6 → 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
@@ -59,7 +59,13 @@ In addition, Formisch offers several functions (we call them "methods") that can
59
59
 
60
60
  ## Comparison
61
61
 
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.
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, 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.
63
+
64
+ For a side-by-side look at how Formisch compares to Felte and TanStack Form, see the [comparison guide](https://formisch.dev/solid/guides/comparison/).
65
+
66
+ ## Vision
67
+
68
+ 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
69
 
64
70
  ## Partners
65
71
 
package/dist/dev.js CHANGED
@@ -193,6 +193,43 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
193
193
  });
194
194
  }
195
195
  // @__NO_SIDE_EFFECTS__
196
+ function getFieldBool(internalFieldStore, type) {
197
+ if (internalFieldStore[type].value) return true;
198
+ if (internalFieldStore.kind === "array") {
199
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
200
+ return false;
201
+ }
202
+ if (internalFieldStore.kind == "object") {
203
+ for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
204
+ return false;
205
+ }
206
+ return false;
207
+ }
208
+ // @__NO_SIDE_EFFECTS__
209
+ function getDirtyFieldInput(internalFieldStore, dirtyOnly = true) {
210
+ if (dirtyOnly && !/* @__PURE__ */ getFieldBool(internalFieldStore, "isDirty")) return;
211
+ if (internalFieldStore.kind === "array") {
212
+ if (internalFieldStore.input.value) {
213
+ const value = [];
214
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */ getDirtyFieldInput(internalFieldStore.children[index], false);
215
+ return value;
216
+ }
217
+ return internalFieldStore.input.value;
218
+ }
219
+ if (internalFieldStore.kind === "object") {
220
+ if (internalFieldStore.input.value) {
221
+ const value = {};
222
+ for (const key in internalFieldStore.children) {
223
+ const child = internalFieldStore.children[key];
224
+ if (!dirtyOnly || /* @__PURE__ */ getFieldBool(child, "isDirty")) value[key] = /* @__PURE__ */ getDirtyFieldInput(child, dirtyOnly);
225
+ }
226
+ return value;
227
+ }
228
+ return internalFieldStore.input.value;
229
+ }
230
+ return internalFieldStore.input.value;
231
+ }
232
+ // @__NO_SIDE_EFFECTS__
196
233
  function getFieldInput(internalFieldStore) {
197
234
  if (internalFieldStore.kind === "array") {
198
235
  if (internalFieldStore.input.value) {
@@ -231,19 +268,6 @@ function getElementInput(element, internalFieldStore) {
231
268
  return element.value;
232
269
  }
233
270
  // @__NO_SIDE_EFFECTS__
234
- function getFieldBool(internalFieldStore, type) {
235
- if (internalFieldStore[type].value) return true;
236
- if (internalFieldStore.kind === "array") {
237
- for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
238
- return false;
239
- }
240
- if (internalFieldStore.kind == "object") {
241
- for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
242
- return false;
243
- }
244
- return false;
245
- }
246
- // @__NO_SIDE_EFFECTS__
247
271
  function getFieldStore(internalFormStore, path) {
248
272
  let internalFieldStore = internalFormStore;
249
273
  for (const key of path) internalFieldStore = internalFieldStore.children[key];
@@ -403,6 +427,17 @@ function getAllErrors(form) {
403
427
  return allErrors;
404
428
  }
405
429
  // @__NO_SIDE_EFFECTS__
430
+ function getDirtyInput(form, config) {
431
+ return getDirtyFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
432
+ }
433
+ // @__NO_SIDE_EFFECTS__
434
+ function getDirtyPaths(form, config) {
435
+ config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
436
+ const paths = [];
437
+ config?.path && [...config.path];
438
+ return paths;
439
+ }
440
+ // @__NO_SIDE_EFFECTS__
406
441
  function getErrors(form, config) {
407
442
  return (config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value;
408
443
  }
@@ -481,6 +516,24 @@ function move(form, config) {
481
516
  validateIfRequired(internalFormStore, internalArrayStore, "input");
482
517
  });
483
518
  }
519
+ // @__NO_SIDE_EFFECTS__
520
+ function pickDirty(form, config) {
521
+ if (!getFieldBool(form[INTERNAL], "isDirty")) return;
522
+ const result = /* @__PURE__ */ pickFieldValue(form[INTERNAL], config.from);
523
+ return Object.keys(result).length ? result : void 0;
524
+ }
525
+ // @__NO_SIDE_EFFECTS__
526
+ function pickFieldValue(internalFieldStore, value) {
527
+ if (internalFieldStore.kind === "object" && internalFieldStore.input.value && value && typeof value === "object" && !Array.isArray(value)) {
528
+ const result = {};
529
+ for (const key in internalFieldStore.children) {
530
+ const child = internalFieldStore.children[key];
531
+ if (getFieldBool(child, "isDirty") && key in value) result[key] = /* @__PURE__ */ pickFieldValue(child, value[key]);
532
+ }
533
+ return result;
534
+ }
535
+ return value;
536
+ }
484
537
  function remove(form, config) {
485
538
  const internalFormStore = form[INTERNAL];
486
539
  const internalArrayStore = getFieldStore(internalFormStore, config.path);
@@ -790,4 +843,4 @@ function Form(props) {
790
843
  })();
791
844
  }
792
845
 
793
- export { Field, FieldArray, Form, createForm, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, validate };
846
+ export { Field, FieldArray, Form, createForm, focus, getAllErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, validate };
package/dist/dev.jsx CHANGED
@@ -191,6 +191,43 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
191
191
  });
192
192
  }
193
193
  // @__NO_SIDE_EFFECTS__
194
+ function getFieldBool(internalFieldStore, type) {
195
+ if (internalFieldStore[type].value) return true;
196
+ if (internalFieldStore.kind === "array") {
197
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
198
+ return false;
199
+ }
200
+ if (internalFieldStore.kind == "object") {
201
+ for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
202
+ return false;
203
+ }
204
+ return false;
205
+ }
206
+ // @__NO_SIDE_EFFECTS__
207
+ function getDirtyFieldInput(internalFieldStore, dirtyOnly = true) {
208
+ if (dirtyOnly && !/* @__PURE__ */ getFieldBool(internalFieldStore, "isDirty")) return;
209
+ if (internalFieldStore.kind === "array") {
210
+ if (internalFieldStore.input.value) {
211
+ const value = [];
212
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */ getDirtyFieldInput(internalFieldStore.children[index], false);
213
+ return value;
214
+ }
215
+ return internalFieldStore.input.value;
216
+ }
217
+ if (internalFieldStore.kind === "object") {
218
+ if (internalFieldStore.input.value) {
219
+ const value = {};
220
+ for (const key in internalFieldStore.children) {
221
+ const child = internalFieldStore.children[key];
222
+ if (!dirtyOnly || /* @__PURE__ */ getFieldBool(child, "isDirty")) value[key] = /* @__PURE__ */ getDirtyFieldInput(child, dirtyOnly);
223
+ }
224
+ return value;
225
+ }
226
+ return internalFieldStore.input.value;
227
+ }
228
+ return internalFieldStore.input.value;
229
+ }
230
+ // @__NO_SIDE_EFFECTS__
194
231
  function getFieldInput(internalFieldStore) {
195
232
  if (internalFieldStore.kind === "array") {
196
233
  if (internalFieldStore.input.value) {
@@ -229,19 +266,6 @@ function getElementInput(element, internalFieldStore) {
229
266
  return element.value;
230
267
  }
231
268
  // @__NO_SIDE_EFFECTS__
232
- function getFieldBool(internalFieldStore, type) {
233
- if (internalFieldStore[type].value) return true;
234
- if (internalFieldStore.kind === "array") {
235
- for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
236
- return false;
237
- }
238
- if (internalFieldStore.kind == "object") {
239
- for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
240
- return false;
241
- }
242
- return false;
243
- }
244
- // @__NO_SIDE_EFFECTS__
245
269
  function getFieldStore(internalFormStore, path) {
246
270
  let internalFieldStore = internalFormStore;
247
271
  for (const key of path) internalFieldStore = internalFieldStore.children[key];
@@ -401,6 +425,17 @@ function getAllErrors(form) {
401
425
  return allErrors;
402
426
  }
403
427
  // @__NO_SIDE_EFFECTS__
428
+ function getDirtyInput(form, config) {
429
+ return getDirtyFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
430
+ }
431
+ // @__NO_SIDE_EFFECTS__
432
+ function getDirtyPaths(form, config) {
433
+ config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
434
+ const paths = [];
435
+ config?.path && [...config.path];
436
+ return paths;
437
+ }
438
+ // @__NO_SIDE_EFFECTS__
404
439
  function getErrors(form, config) {
405
440
  return (config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value;
406
441
  }
@@ -479,6 +514,24 @@ function move(form, config) {
479
514
  validateIfRequired(internalFormStore, internalArrayStore, "input");
480
515
  });
481
516
  }
517
+ // @__NO_SIDE_EFFECTS__
518
+ function pickDirty(form, config) {
519
+ if (!getFieldBool(form[INTERNAL], "isDirty")) return;
520
+ const result = /* @__PURE__ */ pickFieldValue(form[INTERNAL], config.from);
521
+ return Object.keys(result).length ? result : void 0;
522
+ }
523
+ // @__NO_SIDE_EFFECTS__
524
+ function pickFieldValue(internalFieldStore, value) {
525
+ if (internalFieldStore.kind === "object" && internalFieldStore.input.value && value && typeof value === "object" && !Array.isArray(value)) {
526
+ const result = {};
527
+ for (const key in internalFieldStore.children) {
528
+ const child = internalFieldStore.children[key];
529
+ if (getFieldBool(child, "isDirty") && key in value) result[key] = /* @__PURE__ */ pickFieldValue(child, value[key]);
530
+ }
531
+ return result;
532
+ }
533
+ return value;
534
+ }
482
535
  function remove(form, config) {
483
536
  const internalFormStore = form[INTERNAL];
484
537
  const internalArrayStore = getFieldStore(internalFormStore, config.path);
@@ -807,11 +860,14 @@ export {
807
860
  createForm,
808
861
  focus,
809
862
  getAllErrors,
863
+ getDirtyInput,
864
+ getDirtyPaths,
810
865
  getErrors,
811
866
  getInput,
812
867
  handleSubmit,
813
868
  insert,
814
869
  move,
870
+ pickDirty,
815
871
  remove,
816
872
  replace,
817
873
  reset,
package/dist/index.d.ts CHANGED
@@ -8,6 +8,31 @@ import { JSX } from "solid-js";
8
8
  * Schema type.
9
9
  */
10
10
  type Schema = v.GenericSchema | v.GenericSchemaAsync;
11
+ /**
12
+ * Object schema type.
13
+ */
14
+ 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>;
15
+ /**
16
+ * Object schema async type.
17
+ */
18
+ 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>;
19
+ /**
20
+ * Object root schema type.
21
+ */
22
+ type ObjectRootSchema = ObjectSchema | v.IntersectSchema<ObjectSchema[], v.ErrorMessage<v.IntersectIssue> | undefined> | v.UnionSchema<ObjectSchema[], v.ErrorMessage<v.UnionIssue<v.BaseIssue<unknown>>> | undefined>;
23
+ /**
24
+ * Object root schema async type.
25
+ */
26
+ type ObjectRootSchemaAsync = ObjectSchemaAsync | v.IntersectSchemaAsync<(ObjectSchema | ObjectSchemaAsync)[], v.ErrorMessage<v.IntersectIssue> | undefined> | v.UnionSchemaAsync<(ObjectSchema | ObjectSchemaAsync)[], v.ErrorMessage<v.UnionIssue<v.BaseIssue<unknown>>> | undefined>;
27
+ /**
28
+ * Form schema type.
29
+ *
30
+ * Hint: Forms must have an object root, so only object schemas (sync or async),
31
+ * combinators (intersect, union, variant) whose options resolve to objects, and
32
+ * `lazy` schemas wrapping any of these are allowed at the top level. Use
33
+ * {@link Schema} for nested field schemas.
34
+ */
35
+ type FormSchema = ObjectRootSchema | ObjectRootSchemaAsync | v.LazySchema<ObjectRootSchema> | v.LazySchemaAsync<ObjectRootSchema | ObjectRootSchemaAsync>;
11
36
  //#endregion
12
37
  //#region src/types/signal/signal.d.ts
13
38
  /**
@@ -224,7 +249,7 @@ type ValidationMode = "initial" | "touch" | "input" | "change" | "blur" | "submi
224
249
  /**
225
250
  * Form config interface.
226
251
  */
227
- interface FormConfig<TSchema extends Schema = Schema> {
252
+ interface FormConfig<TSchema extends FormSchema = FormSchema> {
228
253
  /**
229
254
  * The schema of the form.
230
255
  */
@@ -245,7 +270,7 @@ interface FormConfig<TSchema extends Schema = Schema> {
245
270
  /**
246
271
  * Internal form store interface.
247
272
  */
248
- interface InternalFormStore<TSchema extends Schema = Schema> extends InternalObjectStore {
273
+ interface InternalFormStore<TSchema extends FormSchema = FormSchema> extends InternalObjectStore {
249
274
  /**
250
275
  * The element of the form.
251
276
  */
@@ -282,7 +307,7 @@ interface InternalFormStore<TSchema extends Schema = Schema> extends InternalObj
282
307
  /**
283
308
  * Base form store interface.
284
309
  */
285
- interface BaseFormStore<TSchema extends Schema = Schema> {
310
+ interface BaseFormStore<TSchema extends FormSchema = FormSchema> {
286
311
  /**
287
312
  * The internal form store.
288
313
  *
@@ -293,11 +318,11 @@ interface BaseFormStore<TSchema extends Schema = Schema> {
293
318
  /**
294
319
  * Submit handler type.
295
320
  */
296
- type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>) => MaybePromise<unknown>;
321
+ type SubmitHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>) => MaybePromise<unknown>;
297
322
  /**
298
323
  * Submit event handler type.
299
324
  */
300
- type SubmitEventHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
325
+ type SubmitEventHandler<TSchema extends FormSchema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
301
326
  //#endregion
302
327
  //#region src/types/path/path.d.ts
303
328
  /**
@@ -400,6 +425,28 @@ type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path =
400
425
  * based on the given value.
401
426
  */
402
427
  type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
428
+ /**
429
+ * Recursive helper for `DirtyPath` that prepends `TKey` to each deeper path,
430
+ * or falls through to `never` when the child is not an object.
431
+ */
432
+ type DeepDirtyPath<TChild, TKey$1 extends PathKey, TDepth extends 0[]> = TChild extends Record<PropertyKey, unknown> ? readonly [TKey$1, ...DirtyPath<TChild, [...TDepth, 0]>] : never;
433
+ /**
434
+ * Returns the union of all `RequiredPath`s that `getDirtyPaths` can emit
435
+ * for a given input type. Object fields contribute their own path and the
436
+ * paths of their descendants; arrays and tuples are atomic and contribute
437
+ * only their own path, because dirty arrays are returned as complete units.
438
+ *
439
+ * Narrowing is exact for the first 5 levels of nesting; deeper paths fall
440
+ * back to `RequiredPath` to keep the result a complete superset of any
441
+ * path the runtime can address.
442
+ *
443
+ * Hint: Arrays and tuples are atomic because they don't structurally
444
+ * extend `Record<PropertyKey, unknown>` and so fall through to `never`
445
+ * via `DeepDirtyPath` — no explicit array check is needed. `TDepth` is
446
+ * a tuple-length counter capped at 5 to bound TypeScript instantiation
447
+ * cost.
448
+ */
449
+ 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;
403
450
  //#endregion
404
451
  //#region src/array/copyItemState/copyItemState.d.ts
405
452
  /**
@@ -418,7 +465,7 @@ type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArra
418
465
  /**
419
466
  * Focus field config interface.
420
467
  */
421
- interface FocusFieldConfig<TSchema extends Schema, TFieldPath extends RequiredPath> {
468
+ interface FocusFieldConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
422
469
  /**
423
470
  * The path to the field to focus.
424
471
  */
@@ -432,7 +479,7 @@ interface FocusFieldConfig<TSchema extends Schema, TFieldPath extends RequiredPa
432
479
  * @param form The form store containing the field.
433
480
  * @param config The focus field configuration.
434
481
  */
435
- declare function focus<TSchema extends Schema, TFieldPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: FocusFieldConfig<TSchema, TFieldPath>): void;
482
+ declare function focus<TSchema extends FormSchema, TFieldPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: FocusFieldConfig<TSchema, TFieldPath>): void;
436
483
  //#endregion
437
484
  //#region src/getAllErrors/getAllErrors.d.ts
438
485
  /**
@@ -446,6 +493,93 @@ declare function focus<TSchema extends Schema, TFieldPath extends RequiredPath>(
446
493
  */
447
494
  declare function getAllErrors(form: BaseFormStore): [string, ...string[]] | null;
448
495
  //#endregion
496
+ //#region src/getDirtyInput/getDirtyInput.d.ts
497
+ /**
498
+ * Get form dirty input config interface.
499
+ */
500
+ interface GetFormDirtyInputConfig {
501
+ /**
502
+ * The path to a field. Leave undefined to get the dirty input of the entire
503
+ * form.
504
+ */
505
+ readonly path?: undefined;
506
+ }
507
+ /**
508
+ * Get field dirty input config interface.
509
+ */
510
+ interface GetFieldDirtyInputConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
511
+ /**
512
+ * The path to the field to retrieve the dirty input from.
513
+ */
514
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
515
+ }
516
+ /**
517
+ * Retrieves only the dirty input values of a specific field or the entire
518
+ * form. Arrays are treated as atomic and returned in full if any item is
519
+ * dirty, while object keys without a dirty descendant are omitted. Returns
520
+ * `undefined` if no field in the inspected subtree is dirty.
521
+ *
522
+ * @param form The form store to retrieve dirty input from.
523
+ *
524
+ * @returns The dirty input of the form or specified field, or `undefined`.
525
+ */
526
+ declare function getDirtyInput<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): DeepPartial<v.InferInput<TSchema>> | undefined;
527
+ /**
528
+ * Retrieves only the dirty input values of a specific field or the entire
529
+ * form. Arrays are treated as atomic and returned in full if any item is
530
+ * dirty, while object keys without a dirty descendant are omitted. Returns
531
+ * `undefined` if no field in the inspected subtree is dirty.
532
+ *
533
+ * @param form The form store to retrieve dirty input from.
534
+ * @param config The get dirty input configuration.
535
+ *
536
+ * @returns The dirty input of the form or specified field, or `undefined`.
537
+ */
538
+ declare function getDirtyInput<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldDirtyInputConfig<TSchema, TFieldPath> : GetFormDirtyInputConfig): DeepPartial<TFieldPath extends RequiredPath ? PathValue<v.InferInput<TSchema>, TFieldPath> : v.InferInput<TSchema>> | undefined;
539
+ //#endregion
540
+ //#region src/getDirtyPaths/getDirtyPaths.d.ts
541
+ /**
542
+ * Get form dirty paths config interface.
543
+ */
544
+ interface GetFormDirtyPathsConfig {
545
+ /**
546
+ * The path to a field. Leave undefined to inspect the entire form.
547
+ */
548
+ readonly path?: undefined;
549
+ }
550
+ /**
551
+ * Get field dirty paths config interface.
552
+ */
553
+ interface GetFieldDirtyPathsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
554
+ /**
555
+ * The path to the field to inspect.
556
+ */
557
+ readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
558
+ }
559
+ /**
560
+ * Returns a list of paths to the dirty fields of a specific field or the
561
+ * entire form. Arrays are treated as atomic and contribute only their own
562
+ * path if any item is dirty, while object branches are recursed into. Returns
563
+ * an empty list if no field in the inspected subtree is dirty.
564
+ *
565
+ * @param form The form store to inspect.
566
+ *
567
+ * @returns The list of paths to the dirty fields.
568
+ */
569
+ declare function getDirtyPaths<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): DirtyPath<v.InferInput<TSchema>>[];
570
+ /**
571
+ * Returns a list of paths to the dirty fields of a specific field or the
572
+ * entire form. Arrays are treated as atomic and contribute only their own
573
+ * path if any item is dirty, while object branches are recursed into. Returns
574
+ * an empty list if no field in the inspected subtree is dirty.
575
+ *
576
+ * @param form The form store to inspect.
577
+ * @param config The get dirty paths configuration.
578
+ *
579
+ * @returns The list of paths to the dirty fields.
580
+ */
581
+ declare function getDirtyPaths<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldDirtyPathsConfig<TSchema, TFieldPath> : GetFormDirtyPathsConfig): DirtyPath<v.InferInput<TSchema>>[];
582
+ //#endregion
449
583
  //#region src/getErrors/getErrors.d.ts
450
584
  /**
451
585
  * Get form errors config interface.
@@ -459,7 +593,7 @@ interface GetFormErrorsConfig {
459
593
  /**
460
594
  * Get field errors config interface.
461
595
  */
462
- interface GetFieldErrorsConfig<TSchema extends Schema, TFieldPath extends RequiredPath> {
596
+ interface GetFieldErrorsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
463
597
  /**
464
598
  * The path to the field to retrieve errors from.
465
599
  */
@@ -474,7 +608,7 @@ interface GetFieldErrorsConfig<TSchema extends Schema, TFieldPath extends Requir
474
608
  *
475
609
  * @returns A non-empty array of error messages, or null if no errors exist.
476
610
  */
477
- declare function getErrors<TSchema extends Schema>(form: BaseFormStore<TSchema>): [string, ...string[]] | null;
611
+ declare function getErrors<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): [string, ...string[]] | null;
478
612
  /**
479
613
  * Retrieves error messages from the form. When called without a config,
480
614
  * returns form-level errors. When called with a path, returns errors for
@@ -485,7 +619,7 @@ declare function getErrors<TSchema extends Schema>(form: BaseFormStore<TSchema>)
485
619
  *
486
620
  * @returns A non-empty array of error messages, or null if no errors exist.
487
621
  */
488
- declare function getErrors<TSchema extends Schema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldErrorsConfig<TSchema, TFieldPath> : GetFormErrorsConfig): [string, ...string[]] | null;
622
+ declare function getErrors<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldErrorsConfig<TSchema, TFieldPath> : GetFormErrorsConfig): [string, ...string[]] | null;
489
623
  //#endregion
490
624
  //#region src/getInput/getInput.d.ts
491
625
  /**
@@ -500,7 +634,7 @@ interface GetFormInputConfig {
500
634
  /**
501
635
  * Get field input config interface.
502
636
  */
503
- interface GetFieldInputConfig<TSchema extends Schema, TFieldPath extends RequiredPath> {
637
+ interface GetFieldInputConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
504
638
  /**
505
639
  * The path to the field to retrieve input from.
506
640
  */
@@ -514,7 +648,7 @@ interface GetFieldInputConfig<TSchema extends Schema, TFieldPath extends Require
514
648
  *
515
649
  * @returns The partial input values of the form or the specified field.
516
650
  */
517
- declare function getInput<TSchema extends Schema>(form: BaseFormStore<TSchema>): PartialValues<v.InferInput<TSchema>>;
651
+ declare function getInput<TSchema extends FormSchema>(form: BaseFormStore<TSchema>): PartialValues<v.InferInput<TSchema>>;
518
652
  /**
519
653
  * Retrieves the current input value of a specific field or the entire form.
520
654
  * Returns a partial object as not all fields may have been set.
@@ -524,7 +658,7 @@ declare function getInput<TSchema extends Schema>(form: BaseFormStore<TSchema>):
524
658
  *
525
659
  * @returns The partial input values of the form or the specified field.
526
660
  */
527
- declare function getInput<TSchema extends Schema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldInputConfig<TSchema, TFieldPath> : GetFormInputConfig): PartialValues<TFieldPath extends RequiredPath ? PathValue<v.InferInput<TSchema>, TFieldPath> : v.InferInput<TSchema>>;
661
+ declare function getInput<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? GetFieldInputConfig<TSchema, TFieldPath> : GetFormInputConfig): PartialValues<TFieldPath extends RequiredPath ? PathValue<v.InferInput<TSchema>, TFieldPath> : v.InferInput<TSchema>>;
528
662
  //#endregion
529
663
  //#region src/handleSubmit/handleSubmit.d.ts
530
664
  /**
@@ -537,7 +671,7 @@ declare function getInput<TSchema extends Schema, TFieldPath extends RequiredPat
537
671
  *
538
672
  * @returns A submit event handler function to attach to the form element.
539
673
  */
540
- declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchema>, handler: SubmitHandler<TSchema>): () => Promise<void>;
674
+ declare function handleSubmit<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, handler: SubmitHandler<TSchema>): () => Promise<void>;
541
675
  /**
542
676
  * Creates a submit event handler for the form that prevents default browser
543
677
  * submission, validates the form input, and calls the provided handler if
@@ -548,13 +682,13 @@ declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchem
548
682
  *
549
683
  * @returns A submit event handler function to attach to the form element.
550
684
  */
551
- declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchema>, handler: SubmitEventHandler<TSchema>): (event: SubmitEvent) => Promise<void>;
685
+ declare function handleSubmit<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, handler: SubmitEventHandler<TSchema>): (event: SubmitEvent) => Promise<void>;
552
686
  //#endregion
553
687
  //#region src/insert/insert.d.ts
554
688
  /**
555
689
  * Insert array field config interface.
556
690
  */
557
- interface InsertConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPath> {
691
+ interface InsertConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
558
692
  /**
559
693
  * The path to the field array to insert into.
560
694
  */
@@ -575,13 +709,13 @@ interface InsertConfig<TSchema extends Schema, TFieldArrayPath extends RequiredP
575
709
  * @param form The form store containing the field array.
576
710
  * @param config The insert configuration specifying the path, index, and initial value.
577
711
  */
578
- declare function insert<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: InsertConfig<TSchema, TFieldArrayPath>): void;
712
+ declare function insert<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: InsertConfig<TSchema, TFieldArrayPath>): void;
579
713
  //#endregion
580
714
  //#region src/move/move.d.ts
581
715
  /**
582
716
  * Move array field config interface.
583
717
  */
584
- interface MoveConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPath> {
718
+ interface MoveConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
585
719
  /**
586
720
  * The path to the field array to move an item within.
587
721
  */
@@ -602,13 +736,38 @@ interface MoveConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPat
602
736
  * @param form The form store containing the field array.
603
737
  * @param config The move configuration specifying the path and source/destination indices.
604
738
  */
605
- declare function move<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: MoveConfig<TSchema, TFieldArrayPath>): void;
739
+ declare function move<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: MoveConfig<TSchema, TFieldArrayPath>): void;
740
+ //#endregion
741
+ //#region src/pickDirty/pickDirty.d.ts
742
+ /**
743
+ * Pick dirty config interface.
744
+ */
745
+ interface PickDirtyConfig<TValue extends object> {
746
+ /**
747
+ * The value to filter down to its dirty parts. Must be structurally
748
+ * compatible with the form's schema.
749
+ */
750
+ readonly from: TValue;
751
+ }
752
+ /**
753
+ * Picks only the dirty parts of the given value, using the form's dirty fields
754
+ * as a structural mask. Arrays are treated as atomic and object keys without a
755
+ * dirty descendant are omitted. Returns `undefined` if no field is dirty.
756
+ * Useful for filtering a validated output down to its changed parts before
757
+ * submitting.
758
+ *
759
+ * @param form The form store providing the dirty mask.
760
+ * @param config The pick dirty configuration.
761
+ *
762
+ * @returns The dirty parts of the value, or `undefined`.
763
+ */
764
+ declare function pickDirty<TSchema extends FormSchema, TValue extends object>(form: BaseFormStore<TSchema>, config: PickDirtyConfig<TValue>): DeepPartial<TValue> | undefined;
606
765
  //#endregion
607
766
  //#region src/remove/remove.d.ts
608
767
  /**
609
768
  * Remove array field config interface.
610
769
  */
611
- interface RemoveConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPath> {
770
+ interface RemoveConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
612
771
  /**
613
772
  * The path to the field array to remove an item from.
614
773
  */
@@ -625,13 +784,13 @@ interface RemoveConfig<TSchema extends Schema, TFieldArrayPath extends RequiredP
625
784
  * @param form The form store containing the field array.
626
785
  * @param config The remove configuration specifying the path and index.
627
786
  */
628
- declare function remove<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: RemoveConfig<TSchema, TFieldArrayPath>): void;
787
+ declare function remove<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: RemoveConfig<TSchema, TFieldArrayPath>): void;
629
788
  //#endregion
630
789
  //#region src/replace/replace.d.ts
631
790
  /**
632
791
  * Replace array field config interface.
633
792
  */
634
- interface ReplaceConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPath> {
793
+ interface ReplaceConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
635
794
  /**
636
795
  * The path to the field array to replace an item within.
637
796
  */
@@ -651,7 +810,7 @@ interface ReplaceConfig<TSchema extends Schema, TFieldArrayPath extends Required
651
810
  * @param form The form store containing the field array.
652
811
  * @param config The replace configuration specifying the path, index, and initial input.
653
812
  */
654
- declare function replace<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: ReplaceConfig<TSchema, TFieldArrayPath>): void;
813
+ declare function replace<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: ReplaceConfig<TSchema, TFieldArrayPath>): void;
655
814
  //#endregion
656
815
  //#region src/reset/reset.d.ts
657
816
  /**
@@ -674,7 +833,7 @@ interface ResetBaseConfig {
674
833
  /**
675
834
  * Reset form config interface.
676
835
  */
677
- interface ResetFormConfig<TSchema extends Schema> extends ResetBaseConfig {
836
+ interface ResetFormConfig<TSchema extends FormSchema> extends ResetBaseConfig {
678
837
  /**
679
838
  * The path to a field. Leave undefined to reset the entire form.
680
839
  */
@@ -692,7 +851,7 @@ interface ResetFormConfig<TSchema extends Schema> extends ResetBaseConfig {
692
851
  /**
693
852
  * Reset field config interface.
694
853
  */
695
- interface ResetFieldConfig<TSchema extends Schema, TFieldPath extends RequiredPath> extends ResetBaseConfig {
854
+ interface ResetFieldConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> extends ResetBaseConfig {
696
855
  /**
697
856
  * The path to the field to reset.
698
857
  */
@@ -719,7 +878,7 @@ declare function reset(form: BaseFormStore): void;
719
878
  * @param form The form store to reset.
720
879
  * @param config The reset configuration specifying what to reset and what to keep.
721
880
  */
722
- declare function reset<TSchema extends Schema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? ResetFieldConfig<TSchema, TFieldPath> : ResetFormConfig<TSchema>): void;
881
+ declare function reset<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? ResetFieldConfig<TSchema, TFieldPath> : ResetFormConfig<TSchema>): void;
723
882
  //#endregion
724
883
  //#region src/setErrors/setErrors.d.ts
725
884
  /**
@@ -738,7 +897,7 @@ interface SetFormErrorsConfig {
738
897
  /**
739
898
  * Set field errors config interface.
740
899
  */
741
- interface SetFieldErrorsConfig<TSchema extends Schema, TFieldPath extends RequiredPath> {
900
+ interface SetFieldErrorsConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
742
901
  /**
743
902
  * The path to the field to set errors on.
744
903
  */
@@ -756,13 +915,13 @@ interface SetFieldErrorsConfig<TSchema extends Schema, TFieldPath extends Requir
756
915
  * @param form The form store to set errors on.
757
916
  * @param config The set errors configuration specifying the path and error messages.
758
917
  */
759
- declare function setErrors<TSchema extends Schema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? SetFieldErrorsConfig<TSchema, TFieldPath> : SetFormErrorsConfig): void;
918
+ declare function setErrors<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? SetFieldErrorsConfig<TSchema, TFieldPath> : SetFormErrorsConfig): void;
760
919
  //#endregion
761
920
  //#region src/setInput/setInput.d.ts
762
921
  /**
763
922
  * Set form input config interface.
764
923
  */
765
- interface SetFormInputConfig<TSchema extends Schema> {
924
+ interface SetFormInputConfig<TSchema extends FormSchema> {
766
925
  /**
767
926
  * The path to a field. Leave undefined to set the entire form input.
768
927
  */
@@ -775,7 +934,7 @@ interface SetFormInputConfig<TSchema extends Schema> {
775
934
  /**
776
935
  * Set field input config interface.
777
936
  */
778
- interface SetFieldInputConfig<TSchema extends Schema, TFieldPath extends RequiredPath> {
937
+ interface SetFieldInputConfig<TSchema extends FormSchema, TFieldPath extends RequiredPath> {
779
938
  /**
780
939
  * The path to the field to set input on.
781
940
  */
@@ -793,7 +952,7 @@ interface SetFieldInputConfig<TSchema extends Schema, TFieldPath extends Require
793
952
  * @param form The form store to set input on.
794
953
  * @param config The set form input configuration specifying the new input values.
795
954
  */
796
- declare function setInput<TSchema extends Schema>(form: BaseFormStore<TSchema>, config: SetFormInputConfig<TSchema>): void;
955
+ declare function setInput<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, config: SetFormInputConfig<TSchema>): void;
797
956
  /**
798
957
  * Sets the input value of a specific field or the entire form. This updates
799
958
  * the field value(s) and triggers validation if required by the form's
@@ -802,7 +961,7 @@ declare function setInput<TSchema extends Schema>(form: BaseFormStore<TSchema>,
802
961
  * @param form The form store to set input on.
803
962
  * @param config The set input configuration specifying the path and new value.
804
963
  */
805
- declare function setInput<TSchema extends Schema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? SetFieldInputConfig<TSchema, TFieldPath> : SetFormInputConfig<TSchema>): void;
964
+ declare function setInput<TSchema extends FormSchema, TFieldPath extends RequiredPath | undefined = undefined>(form: BaseFormStore<TSchema>, config: TFieldPath extends RequiredPath ? SetFieldInputConfig<TSchema, TFieldPath> : SetFormInputConfig<TSchema>): void;
806
965
  //#endregion
807
966
  //#region src/submit/submit.d.ts
808
967
  /**
@@ -817,7 +976,7 @@ declare function submit(form: BaseFormStore): void;
817
976
  /**
818
977
  * Swap array field config interface.
819
978
  */
820
- interface SwapConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPath> {
979
+ interface SwapConfig<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath> {
821
980
  /**
822
981
  * The path to the field array to swap items within.
823
982
  */
@@ -837,7 +996,7 @@ interface SwapConfig<TSchema extends Schema, TFieldArrayPath extends RequiredPat
837
996
  * @param form The form store containing the field array.
838
997
  * @param config The swap configuration specifying the path and indices to swap.
839
998
  */
840
- declare function swap<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: SwapConfig<TSchema, TFieldArrayPath>): void;
999
+ declare function swap<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: BaseFormStore<TSchema>, config: SwapConfig<TSchema, TFieldArrayPath>): void;
841
1000
  //#endregion
842
1001
  //#region src/validate/validate.d.ts
843
1002
  /**
@@ -859,7 +1018,7 @@ interface ValidateFormConfig {
859
1018
  *
860
1019
  * @returns A promise resolving to the validation result.
861
1020
  */
862
- declare function validate<TSchema extends Schema>(form: BaseFormStore<TSchema>, config?: ValidateFormConfig): Promise<v.SafeParseResult<TSchema>>;
1021
+ declare function validate<TSchema extends FormSchema>(form: BaseFormStore<TSchema>, config?: ValidateFormConfig): Promise<v.SafeParseResult<TSchema>>;
863
1022
  //#endregion
864
1023
  //#endregion
865
1024
  //#region src/types/field.d.ts
@@ -899,7 +1058,7 @@ interface FieldElementProps {
899
1058
  /**
900
1059
  * Field store interface.
901
1060
  */
902
- interface FieldStore<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
1061
+ interface FieldStore<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
903
1062
  /**
904
1063
  * The path to the field within the form.
905
1064
  */
@@ -936,7 +1095,7 @@ interface FieldStore<TSchema extends Schema = Schema, TFieldPath extends Require
936
1095
  /**
937
1096
  * Field array store interface.
938
1097
  */
939
- interface FieldArrayStore<TSchema extends Schema = Schema, TFieldArrayPath extends RequiredPath = RequiredPath> {
1098
+ interface FieldArrayStore<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
940
1099
  /**
941
1100
  * The path to the array field within the form.
942
1101
  */
@@ -967,7 +1126,7 @@ interface FieldArrayStore<TSchema extends Schema = Schema, TFieldArrayPath exten
967
1126
  /**
968
1127
  * Form store interface.
969
1128
  */
970
- interface FormStore<TSchema extends Schema = Schema> extends BaseFormStore<TSchema> {
1129
+ interface FormStore<TSchema extends FormSchema = FormSchema> extends BaseFormStore<TSchema> {
971
1130
  /**
972
1131
  * Whether the form is currently submitting.
973
1132
  */
@@ -1011,7 +1170,7 @@ type MaybeGetter<TValue> = TValue | (() => TValue);
1011
1170
  /**
1012
1171
  * Field component props interface.
1013
1172
  */
1014
- interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
1173
+ interface FieldProps<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
1015
1174
  /**
1016
1175
  * The form store to which the field belongs.
1017
1176
  */
@@ -1034,13 +1193,13 @@ interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends Require
1034
1193
  *
1035
1194
  * @returns The UI of the field to be rendered.
1036
1195
  */
1037
- declare function Field<TSchema extends Schema, TFieldPath extends RequiredPath>(props: FieldProps<TSchema, TFieldPath>): JSX.Element;
1196
+ declare function Field<TSchema extends FormSchema, TFieldPath extends RequiredPath>(props: FieldProps<TSchema, TFieldPath>): JSX.Element;
1038
1197
  //#endregion
1039
1198
  //#region src/components/FieldArray/FieldArray.d.ts
1040
1199
  /**
1041
1200
  * FieldArray component props interface.
1042
1201
  */
1043
- interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath extends RequiredPath = RequiredPath> {
1202
+ interface FieldArrayProps<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
1044
1203
  /**
1045
1204
  * The form store to which the field array belongs.
1046
1205
  */
@@ -1063,13 +1222,13 @@ interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath exten
1063
1222
  *
1064
1223
  * @returns The UI of the field array to be rendered.
1065
1224
  */
1066
- declare function FieldArray<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(props: FieldArrayProps<TSchema, TFieldArrayPath>): JSX.Element;
1225
+ declare function FieldArray<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(props: FieldArrayProps<TSchema, TFieldArrayPath>): JSX.Element;
1067
1226
  //#endregion
1068
1227
  //#region src/components/Form/Form.d.ts
1069
1228
  /**
1070
1229
  * Form component props type.
1071
1230
  */
1072
- type FormProps<TSchema extends Schema = Schema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "novalidate" | "noValidate"> & {
1231
+ type FormProps<TSchema extends FormSchema = FormSchema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "novalidate" | "noValidate"> & {
1073
1232
  /**
1074
1233
  * The form store instance.
1075
1234
  */
@@ -1091,7 +1250,7 @@ type FormProps<TSchema extends Schema = Schema> = Omit<JSX.FormHTMLAttributes<HT
1091
1250
  *
1092
1251
  * @returns The a native form element.
1093
1252
  */
1094
- declare function Form<TSchema extends Schema>(props: FormProps<TSchema>): JSX.Element;
1253
+ declare function Form<TSchema extends FormSchema>(props: FormProps<TSchema>): JSX.Element;
1095
1254
  //#endregion
1096
1255
  //#region src/primitives/createForm/createForm.d.ts
1097
1256
  /**
@@ -1102,13 +1261,13 @@ declare function Form<TSchema extends Schema>(props: FormProps<TSchema>): JSX.El
1102
1261
  *
1103
1262
  * @returns The form store with reactive properties.
1104
1263
  */
1105
- declare function createForm<TSchema extends Schema>(config: FormConfig<TSchema>): FormStore<TSchema>;
1264
+ declare function createForm<TSchema extends FormSchema>(config: FormConfig<TSchema>): FormStore<TSchema>;
1106
1265
  //#endregion
1107
1266
  //#region src/primitives/useField/useField.d.ts
1108
1267
  /**
1109
1268
  * Use field config interface.
1110
1269
  */
1111
- interface UseFieldConfig<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
1270
+ interface UseFieldConfig<TSchema extends FormSchema = FormSchema, TFieldPath extends RequiredPath = RequiredPath> {
1112
1271
  /**
1113
1272
  * The path to the field within the form schema.
1114
1273
  */
@@ -1122,13 +1281,13 @@ interface UseFieldConfig<TSchema extends Schema = Schema, TFieldPath extends Req
1122
1281
  *
1123
1282
  * @returns The field store with reactive properties and element props.
1124
1283
  */
1125
- declare function useField<TSchema extends Schema, TFieldPath extends RequiredPath>(form: MaybeGetter<FormStore<TSchema>>, config: MaybeGetter<UseFieldConfig<TSchema, TFieldPath>>): FieldStore<TSchema, TFieldPath>;
1284
+ declare function useField<TSchema extends FormSchema, TFieldPath extends RequiredPath>(form: MaybeGetter<FormStore<TSchema>>, config: MaybeGetter<UseFieldConfig<TSchema, TFieldPath>>): FieldStore<TSchema, TFieldPath>;
1126
1285
  //#endregion
1127
1286
  //#region src/primitives/useFieldArray/useFieldArray.d.ts
1128
1287
  /**
1129
1288
  * Use field array config interface.
1130
1289
  */
1131
- interface UseFieldArrayConfig<TSchema extends Schema = Schema, TFieldArrayPath extends RequiredPath = RequiredPath> {
1290
+ interface UseFieldArrayConfig<TSchema extends FormSchema = FormSchema, TFieldArrayPath extends RequiredPath = RequiredPath> {
1132
1291
  /**
1133
1292
  * The path to the field array within the form schema.
1134
1293
  */
@@ -1142,6 +1301,6 @@ interface UseFieldArrayConfig<TSchema extends Schema = Schema, TFieldArrayPath e
1142
1301
  *
1143
1302
  * @returns The field array store with reactive properties for array management.
1144
1303
  */
1145
- declare function useFieldArray<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(form: MaybeGetter<FormStore<TSchema>>, config: MaybeGetter<UseFieldArrayConfig<TSchema, TFieldArrayPath>>): FieldArrayStore<TSchema, TFieldArrayPath>;
1304
+ declare function useFieldArray<TSchema extends FormSchema, TFieldArrayPath extends RequiredPath>(form: MaybeGetter<FormStore<TSchema>>, config: MaybeGetter<UseFieldArrayConfig<TSchema, TFieldArrayPath>>): FieldArrayStore<TSchema, TFieldArrayPath>;
1146
1305
  //#endregion
1147
- export { type DeepPartial, Field, FieldArray, FieldArrayProps, FieldArrayStore, type FieldElement, FieldElementProps, FieldProps, FieldStore, FocusFieldConfig, Form, type FormConfig, FormProps, FormStore, GetFieldErrorsConfig, GetFieldInputConfig, GetFormErrorsConfig, GetFormInputConfig, InsertConfig, MaybeGetter, MoveConfig, type PartialValues, type PathValue, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, SetFieldInputConfig, SetFormErrorsConfig, SetFormInputConfig, type SubmitEventHandler, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, createForm, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, validate };
1306
+ 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, MaybeGetter, MoveConfig, type PartialValues, type PathValue, PickDirtyConfig, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, SetFieldInputConfig, SetFormErrorsConfig, SetFormInputConfig, type SubmitEventHandler, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, createForm, focus, getAllErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, validate };
package/dist/index.js CHANGED
@@ -193,6 +193,43 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
193
193
  });
194
194
  }
195
195
  // @__NO_SIDE_EFFECTS__
196
+ function getFieldBool(internalFieldStore, type) {
197
+ if (internalFieldStore[type].value) return true;
198
+ if (internalFieldStore.kind === "array") {
199
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
200
+ return false;
201
+ }
202
+ if (internalFieldStore.kind == "object") {
203
+ for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
204
+ return false;
205
+ }
206
+ return false;
207
+ }
208
+ // @__NO_SIDE_EFFECTS__
209
+ function getDirtyFieldInput(internalFieldStore, dirtyOnly = true) {
210
+ if (dirtyOnly && !/* @__PURE__ */ getFieldBool(internalFieldStore, "isDirty")) return;
211
+ if (internalFieldStore.kind === "array") {
212
+ if (internalFieldStore.input.value) {
213
+ const value = [];
214
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */ getDirtyFieldInput(internalFieldStore.children[index], false);
215
+ return value;
216
+ }
217
+ return internalFieldStore.input.value;
218
+ }
219
+ if (internalFieldStore.kind === "object") {
220
+ if (internalFieldStore.input.value) {
221
+ const value = {};
222
+ for (const key in internalFieldStore.children) {
223
+ const child = internalFieldStore.children[key];
224
+ if (!dirtyOnly || /* @__PURE__ */ getFieldBool(child, "isDirty")) value[key] = /* @__PURE__ */ getDirtyFieldInput(child, dirtyOnly);
225
+ }
226
+ return value;
227
+ }
228
+ return internalFieldStore.input.value;
229
+ }
230
+ return internalFieldStore.input.value;
231
+ }
232
+ // @__NO_SIDE_EFFECTS__
196
233
  function getFieldInput(internalFieldStore) {
197
234
  if (internalFieldStore.kind === "array") {
198
235
  if (internalFieldStore.input.value) {
@@ -231,19 +268,6 @@ function getElementInput(element, internalFieldStore) {
231
268
  return element.value;
232
269
  }
233
270
  // @__NO_SIDE_EFFECTS__
234
- function getFieldBool(internalFieldStore, type) {
235
- if (internalFieldStore[type].value) return true;
236
- if (internalFieldStore.kind === "array") {
237
- for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
238
- return false;
239
- }
240
- if (internalFieldStore.kind == "object") {
241
- for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
242
- return false;
243
- }
244
- return false;
245
- }
246
- // @__NO_SIDE_EFFECTS__
247
271
  function getFieldStore(internalFormStore, path) {
248
272
  let internalFieldStore = internalFormStore;
249
273
  for (const key of path) internalFieldStore = internalFieldStore.children[key];
@@ -403,6 +427,17 @@ function getAllErrors(form) {
403
427
  return allErrors;
404
428
  }
405
429
  // @__NO_SIDE_EFFECTS__
430
+ function getDirtyInput(form, config) {
431
+ return getDirtyFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
432
+ }
433
+ // @__NO_SIDE_EFFECTS__
434
+ function getDirtyPaths(form, config) {
435
+ config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
436
+ const paths = [];
437
+ config?.path && [...config.path];
438
+ return paths;
439
+ }
440
+ // @__NO_SIDE_EFFECTS__
406
441
  function getErrors(form, config) {
407
442
  return (config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value;
408
443
  }
@@ -481,6 +516,24 @@ function move(form, config) {
481
516
  validateIfRequired(internalFormStore, internalArrayStore, "input");
482
517
  });
483
518
  }
519
+ // @__NO_SIDE_EFFECTS__
520
+ function pickDirty(form, config) {
521
+ if (!getFieldBool(form[INTERNAL], "isDirty")) return;
522
+ const result = /* @__PURE__ */ pickFieldValue(form[INTERNAL], config.from);
523
+ return Object.keys(result).length ? result : void 0;
524
+ }
525
+ // @__NO_SIDE_EFFECTS__
526
+ function pickFieldValue(internalFieldStore, value) {
527
+ if (internalFieldStore.kind === "object" && internalFieldStore.input.value && value && typeof value === "object" && !Array.isArray(value)) {
528
+ const result = {};
529
+ for (const key in internalFieldStore.children) {
530
+ const child = internalFieldStore.children[key];
531
+ if (getFieldBool(child, "isDirty") && key in value) result[key] = /* @__PURE__ */ pickFieldValue(child, value[key]);
532
+ }
533
+ return result;
534
+ }
535
+ return value;
536
+ }
484
537
  function remove(form, config) {
485
538
  const internalFormStore = form[INTERNAL];
486
539
  const internalArrayStore = getFieldStore(internalFormStore, config.path);
@@ -790,4 +843,4 @@ function Form(props) {
790
843
  })();
791
844
  }
792
845
 
793
- export { Field, FieldArray, Form, createForm, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, validate };
846
+ export { Field, FieldArray, Form, createForm, focus, getAllErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, validate };
package/dist/index.jsx CHANGED
@@ -191,6 +191,43 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
191
191
  });
192
192
  }
193
193
  // @__NO_SIDE_EFFECTS__
194
+ function getFieldBool(internalFieldStore, type) {
195
+ if (internalFieldStore[type].value) return true;
196
+ if (internalFieldStore.kind === "array") {
197
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
198
+ return false;
199
+ }
200
+ if (internalFieldStore.kind == "object") {
201
+ for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
202
+ return false;
203
+ }
204
+ return false;
205
+ }
206
+ // @__NO_SIDE_EFFECTS__
207
+ function getDirtyFieldInput(internalFieldStore, dirtyOnly = true) {
208
+ if (dirtyOnly && !/* @__PURE__ */ getFieldBool(internalFieldStore, "isDirty")) return;
209
+ if (internalFieldStore.kind === "array") {
210
+ if (internalFieldStore.input.value) {
211
+ const value = [];
212
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = /* @__PURE__ */ getDirtyFieldInput(internalFieldStore.children[index], false);
213
+ return value;
214
+ }
215
+ return internalFieldStore.input.value;
216
+ }
217
+ if (internalFieldStore.kind === "object") {
218
+ if (internalFieldStore.input.value) {
219
+ const value = {};
220
+ for (const key in internalFieldStore.children) {
221
+ const child = internalFieldStore.children[key];
222
+ if (!dirtyOnly || /* @__PURE__ */ getFieldBool(child, "isDirty")) value[key] = /* @__PURE__ */ getDirtyFieldInput(child, dirtyOnly);
223
+ }
224
+ return value;
225
+ }
226
+ return internalFieldStore.input.value;
227
+ }
228
+ return internalFieldStore.input.value;
229
+ }
230
+ // @__NO_SIDE_EFFECTS__
194
231
  function getFieldInput(internalFieldStore) {
195
232
  if (internalFieldStore.kind === "array") {
196
233
  if (internalFieldStore.input.value) {
@@ -229,19 +266,6 @@ function getElementInput(element, internalFieldStore) {
229
266
  return element.value;
230
267
  }
231
268
  // @__NO_SIDE_EFFECTS__
232
- function getFieldBool(internalFieldStore, type) {
233
- if (internalFieldStore[type].value) return true;
234
- if (internalFieldStore.kind === "array") {
235
- for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
236
- return false;
237
- }
238
- if (internalFieldStore.kind == "object") {
239
- for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
240
- return false;
241
- }
242
- return false;
243
- }
244
- // @__NO_SIDE_EFFECTS__
245
269
  function getFieldStore(internalFormStore, path) {
246
270
  let internalFieldStore = internalFormStore;
247
271
  for (const key of path) internalFieldStore = internalFieldStore.children[key];
@@ -401,6 +425,17 @@ function getAllErrors(form) {
401
425
  return allErrors;
402
426
  }
403
427
  // @__NO_SIDE_EFFECTS__
428
+ function getDirtyInput(form, config) {
429
+ return getDirtyFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
430
+ }
431
+ // @__NO_SIDE_EFFECTS__
432
+ function getDirtyPaths(form, config) {
433
+ config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
434
+ const paths = [];
435
+ config?.path && [...config.path];
436
+ return paths;
437
+ }
438
+ // @__NO_SIDE_EFFECTS__
404
439
  function getErrors(form, config) {
405
440
  return (config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]).errors.value;
406
441
  }
@@ -479,6 +514,24 @@ function move(form, config) {
479
514
  validateIfRequired(internalFormStore, internalArrayStore, "input");
480
515
  });
481
516
  }
517
+ // @__NO_SIDE_EFFECTS__
518
+ function pickDirty(form, config) {
519
+ if (!getFieldBool(form[INTERNAL], "isDirty")) return;
520
+ const result = /* @__PURE__ */ pickFieldValue(form[INTERNAL], config.from);
521
+ return Object.keys(result).length ? result : void 0;
522
+ }
523
+ // @__NO_SIDE_EFFECTS__
524
+ function pickFieldValue(internalFieldStore, value) {
525
+ if (internalFieldStore.kind === "object" && internalFieldStore.input.value && value && typeof value === "object" && !Array.isArray(value)) {
526
+ const result = {};
527
+ for (const key in internalFieldStore.children) {
528
+ const child = internalFieldStore.children[key];
529
+ if (getFieldBool(child, "isDirty") && key in value) result[key] = /* @__PURE__ */ pickFieldValue(child, value[key]);
530
+ }
531
+ return result;
532
+ }
533
+ return value;
534
+ }
482
535
  function remove(form, config) {
483
536
  const internalFormStore = form[INTERNAL];
484
537
  const internalArrayStore = getFieldStore(internalFormStore, config.path);
@@ -807,11 +860,14 @@ export {
807
860
  createForm,
808
861
  focus,
809
862
  getAllErrors,
863
+ getDirtyInput,
864
+ getDirtyPaths,
810
865
  getErrors,
811
866
  getInput,
812
867
  handleSubmit,
813
868
  insert,
814
869
  move,
870
+ pickDirty,
815
871
  remove,
816
872
  replace,
817
873
  reset,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formisch/solid",
3
3
  "description": "The lightweight, schema-first, and fully type-safe form library for SolidJS",
4
- "version": "0.9.6",
4
+ "version": "0.10.0",
5
5
  "license": "MIT",
6
6
  "author": "Fabian Hiller",
7
7
  "homepage": "https://formisch.dev",
@@ -68,14 +68,14 @@
68
68
  "tsup": "^8.5.0",
69
69
  "tsup-preset-solid": "^2.2.0",
70
70
  "typescript": "^5.8.3",
71
- "valibot": "^1.2.0",
71
+ "valibot": "^1.4.1",
72
72
  "vite-plugin-solid": "^2.11.6",
73
73
  "vitest": "3.2.4"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "solid-js": "^1.6.0",
77
77
  "typescript": ">=5",
78
- "valibot": "^1.0.0"
78
+ "valibot": "^1.4.1"
79
79
  },
80
80
  "peerDependenciesMeta": {
81
81
  "typescript": {