@formisch/react 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as v from "valibot";
2
- import { ChangeEventHandler, FocusEventHandler, FormHTMLAttributes, ReactElement } from "react";
2
+ import { ChangeEventHandler, FocusEventHandler, FormEvent, FormHTMLAttributes, ReactElement } from "react";
3
3
 
4
- //#region ../../packages/core/dist/index.vanilla.d.ts
4
+ //#region ../../packages/core/dist/index.react.d.ts
5
5
 
6
6
  //#region src/types/schema.d.ts
7
7
  /**
@@ -184,12 +184,6 @@ interface InternalValueStore extends InternalBaseStore {
184
184
  */
185
185
  type InternalFieldStore = InternalArrayStore | InternalObjectStore | InternalValueStore;
186
186
  //#endregion
187
- //#region src/values.d.ts
188
- /**
189
- * Internal symbol constant.
190
- */
191
- declare const INTERNAL: "~internal";
192
- //#endregion
193
187
  //#region src/types/utils.d.ts
194
188
  /**
195
189
  * Checks if a type is `any`.
@@ -212,6 +206,12 @@ type DeepPartial<TValue> = TValue extends readonly unknown[] ? number extends TV
212
206
  */
213
207
  type PartialValues<TValue> = TValue extends readonly unknown[] ? number extends TValue["length"] ? TValue : { [Key in keyof TValue]: PartialValues<TValue[Key]> } : TValue extends Record<PropertyKey, unknown> ? { [Key in keyof TValue]: PartialValues<TValue[Key]> } : TValue | undefined;
214
208
  //#endregion
209
+ //#region src/values.d.ts
210
+ /**
211
+ * Internal symbol constant.
212
+ */
213
+ declare const INTERNAL: "~internal";
214
+ //#endregion
215
215
  //#region src/types/form.d.ts
216
216
  /**
217
217
  * Validation mode type.
@@ -286,10 +286,16 @@ interface BaseFormStore<TSchema extends Schema = Schema> {
286
286
  */
287
287
  readonly [INTERNAL]: InternalFormStore<TSchema>;
288
288
  }
289
+ //#endregion
290
+ //#region src/types/form.react.d.ts
289
291
  /**
290
292
  * Submit handler type.
291
293
  */
292
- type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
294
+ type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>) => MaybePromise<unknown>;
295
+ /**
296
+ * Submit event handler type.
297
+ */
298
+ type SubmitEventHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: FormEvent<HTMLFormElement>) => MaybePromise<unknown>;
293
299
  //#endregion
294
300
  //#region src/types/path.d.ts
295
301
  /**
@@ -358,9 +364,8 @@ type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArra
358
364
  * @param toInternalFieldStore The destination field store to copy to.
359
365
  */
360
366
  //#endregion
361
- //#region ../../packages/methods/dist/index.vanilla.d.ts
367
+ //#region ../../packages/methods/dist/index.react.d.ts
362
368
  //#region src/focus/focus.d.ts
363
-
364
369
  /**
365
370
  * Focus field config interface.
366
371
  */
@@ -472,7 +477,18 @@ declare function getInput<TSchema extends Schema>(form: BaseFormStore<TSchema>):
472
477
  */
473
478
  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>>;
474
479
  //#endregion
475
- //#region src/handleSubmit/handleSubmit.d.ts
480
+ //#region src/handleSubmit/handleSubmit.react.d.ts
481
+ /**
482
+ * Creates a submit event handler for the form that validates the form input,
483
+ * and calls the provided handler if validation succeeds. This is designed to
484
+ * be used with the form's onsubmit event.
485
+ *
486
+ * @param form The form store to handle submission for.
487
+ * @param handler The submit handler function called with validated output if validation succeeds.
488
+ *
489
+ * @returns A submit event handler function to attach to the form element.
490
+ */
491
+ declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchema>, handler: SubmitHandler<TSchema>): () => Promise<void>;
476
492
  /**
477
493
  * Creates a submit event handler for the form that prevents default browser
478
494
  * submission, validates the form input, and calls the provided handler if
@@ -483,7 +499,7 @@ declare function getInput<TSchema extends Schema, TFieldPath extends RequiredPat
483
499
  *
484
500
  * @returns A submit event handler function to attach to the form element.
485
501
  */
486
- declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchema>, handler: SubmitHandler<TSchema>): (event: SubmitEvent) => Promise<void>;
502
+ declare function handleSubmit<TSchema extends Schema>(form: BaseFormStore<TSchema>, handler: SubmitEventHandler<TSchema>): (event: FormEvent<HTMLFormElement>) => Promise<void>;
487
503
  //#endregion
488
504
  //#region src/insert/insert.d.ts
489
505
  /**
@@ -720,10 +736,12 @@ interface SetFieldInputConfig<TSchema extends Schema, TFieldPath extends Require
720
736
  */
721
737
  readonly input: PathValue<v.InferInput<TSchema>, TFieldPath>;
722
738
  }
739
+ //#endregion
740
+ //#region src/setInput/setInput.react.d.ts
723
741
  /**
724
742
  * Sets the input value of a specific field or the entire form. This updates
725
743
  * the field value(s) and triggers validation if required by the form's
726
- * validation mode.
744
+ * validation mode for both input and change events.
727
745
  *
728
746
  * @param form The form store to set input on.
729
747
  * @param config The set form input configuration specifying the new input values.
@@ -732,7 +750,7 @@ declare function setInput<TSchema extends Schema>(form: BaseFormStore<TSchema>,
732
750
  /**
733
751
  * Sets the input value of a specific field or the entire form. This updates
734
752
  * the field value(s) and triggers validation if required by the form's
735
- * validation mode.
753
+ * validation mode for both input and change events.
736
754
  *
737
755
  * @param form The form store to set input on.
738
756
  * @param config The set input configuration specifying the path and new value.
@@ -856,6 +874,10 @@ interface FieldStore<TSchema extends Schema = Schema, TFieldPath extends Require
856
874
  */
857
875
  readonly isValid: boolean;
858
876
  /**
877
+ * Sets the field input value programmatically.
878
+ */
879
+ readonly onChange: (value: PartialValues<PathValue<v.InferInput<TSchema>, TFieldPath>>) => void;
880
+ /**
859
881
  * The props to spread onto the field element for integration.
860
882
  */
861
883
  readonly props: FieldElementProps;
@@ -1007,7 +1029,7 @@ type FormProps<TSchema extends Schema = Schema> = Omit<FormHTMLAttributes<HTMLFo
1007
1029
  /**
1008
1030
  * The submit handler called when the form is submitted and validation succeeds.
1009
1031
  */
1010
- readonly onSubmit: SubmitHandler<TSchema>;
1032
+ readonly onSubmit: SubmitHandler<TSchema> | SubmitEventHandler<TSchema>;
1011
1033
  };
1012
1034
  /**
1013
1035
  * Form component that manages form submission and applies internal state.
@@ -1070,4 +1092,4 @@ declare function useFieldArray<TSchema extends Schema, TFieldArrayPath extends R
1070
1092
  */
1071
1093
  declare function useForm<TSchema extends Schema>(config: FormConfig<TSchema>): FormStore<TSchema>;
1072
1094
  //#endregion
1073
- export { type DeepPartial, Field, FieldArray, FieldArrayProps, FieldArrayStore, type FieldElement, FieldElementProps, FieldProps, FieldStore, FocusFieldConfig, Form, type FormConfig, FormProps, FormStore, GetFieldErrorsConfig, GetFieldInputConfig, GetFormErrorsConfig, GetFormInputConfig, InsertConfig, MoveConfig, type PartialValues, type PathValue, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, SetFieldInputConfig, SetFormErrorsConfig, SetFormInputConfig, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };
1095
+ export { type DeepPartial, Field, FieldArray, FieldArrayProps, FieldArrayStore, type FieldElement, FieldElementProps, FieldProps, FieldStore, FocusFieldConfig, Form, type FormConfig, FormProps, FormStore, GetFieldErrorsConfig, GetFieldInputConfig, GetFormErrorsConfig, GetFormInputConfig, InsertConfig, MoveConfig, type PartialValues, type PathValue, RemoveConfig, ReplaceConfig, type RequiredPath, ResetFieldConfig, ResetFormConfig, type Schema, SetFieldErrorsConfig, type SetFieldInputConfig, SetFormErrorsConfig, type SetFormInputConfig, type SubmitEventHandler, type SubmitHandler, SwapConfig, UseFieldArrayConfig, UseFieldConfig, type ValidArrayPath, type ValidPath, ValidateFormConfig, type ValidationMode, focus, getAllErrors, getErrors, getInput, handleSubmit, insert, move, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm, validate };
package/dist/index.js CHANGED
@@ -2,11 +2,11 @@ import * as v from "valibot";
2
2
  import { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
5
- //#region ../../packages/core/dist/index.vanilla.js
5
+ //#region ../../packages/core/dist/index.react.js
6
6
  /**
7
7
  * The current framework being used.
8
8
  */
9
- const framework = "vanilla";
9
+ const framework = "react";
10
10
  /**
11
11
  * Creates a unique identifier string.
12
12
  *
@@ -141,7 +141,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
141
141
  initializeFieldStore(internalFieldStore.children[index], schema.item, initialInput[index], path);
142
142
  path.pop();
143
143
  }
144
- } else for (let index = 0; index < schema.items; index++) {
144
+ } else for (let index = 0; index < schema.items.length; index++) {
145
145
  internalFieldStore.children[index] = {};
146
146
  path.push(index);
147
147
  initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
@@ -454,7 +454,7 @@ function setNestedInput(internalFieldStore, input) {
454
454
  }
455
455
  for (let index = 0; index < arrayInput.length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
456
456
  internalFieldStore.input.value = input == null ? input : true;
457
- internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== items.length;
457
+ internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== internalFieldStore.items.value.length;
458
458
  } else if (internalFieldStore.kind === "object") {
459
459
  for (const key in internalFieldStore.children) setNestedInput(internalFieldStore.children[key], input?.[key]);
460
460
  internalFieldStore.input.value = input == null ? input : true;
@@ -619,7 +619,7 @@ function validateIfRequired(internalFormStore, internalFieldStore, validationMod
619
619
  const INTERNAL = "~internal";
620
620
 
621
621
  //#endregion
622
- //#region ../../packages/methods/dist/index.vanilla.js
622
+ //#region ../../packages/methods/dist/index.react.js
623
623
  /**
624
624
  * Focuses the first input element of a field. This is useful for
625
625
  * programmatically setting focus to a specific field, such as after
@@ -659,9 +659,9 @@ function getInput(form, config) {
659
659
  return getFieldInput(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL]);
660
660
  }
661
661
  /* @__NO_SIDE_EFFECTS__ */
662
- function handleSubmit(form, handler) {
662
+ function handleSubmit$1(form, handler) {
663
663
  return async (event) => {
664
- event.preventDefault();
664
+ event?.preventDefault();
665
665
  const internalFormStore = form[INTERNAL];
666
666
  internalFormStore.isSubmitted.value = true;
667
667
  internalFormStore.isSubmitting.value = true;
@@ -675,6 +675,10 @@ function handleSubmit(form, handler) {
675
675
  }
676
676
  };
677
677
  }
678
+ /* @__NO_SIDE_EFFECTS__ */
679
+ function handleSubmit(form, handler) {
680
+ return /* @__PURE__ */ handleSubmit$1(form, handler);
681
+ }
678
682
  /**
679
683
  * Inserts a new item into a field array at the specified index. All items at
680
684
  * or after the insertion point are shifted up by one index.
@@ -814,7 +818,9 @@ function setInput(form, config) {
814
818
  batch(() => {
815
819
  const internalFormStore = form[INTERNAL];
816
820
  setFieldInput(internalFormStore, config.path ?? [], config.input);
817
- validateIfRequired(internalFormStore, config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore, "input");
821
+ const fieldOrFormStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
822
+ validateIfRequired(internalFormStore, fieldOrFormStore, "input");
823
+ validateIfRequired(internalFormStore, fieldOrFormStore, "change");
818
824
  });
819
825
  }
820
826
  /**
@@ -917,6 +923,11 @@ function useField(form, config) {
917
923
  get isValid() {
918
924
  return !getFieldBool(internalFieldStore, "errors");
919
925
  },
926
+ onChange(value) {
927
+ setFieldInput(internalFormStore, config.path, value);
928
+ validateIfRequired(internalFormStore, internalFieldStore, "input");
929
+ validateIfRequired(internalFormStore, internalFieldStore, "change");
930
+ },
920
931
  props: {
921
932
  name: internalFieldStore.name,
922
933
  autoFocus: !!internalFieldStore.errors.value,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formisch/react",
3
3
  "description": "The modular and type-safe form library for React",
4
- "version": "0.2.2",
4
+ "version": "0.4.0",
5
5
  "license": "MIT",
6
6
  "author": "Fabian Hiller",
7
7
  "homepage": "https://formisch.dev",
@@ -33,7 +33,6 @@
33
33
  "access": "public"
34
34
  },
35
35
  "devDependencies": {
36
- "@eslint/js": "^9.39.1",
37
36
  "@types/node": "^24.10.1",
38
37
  "@types/react": "^19.2.5",
39
38
  "@types/react-dom": "^19.2.3",
@@ -46,10 +45,10 @@
46
45
  "react-dom": "^19.2.1",
47
46
  "tsdown": "^0.16.8",
48
47
  "typescript": "~5.9.3",
49
- "typescript-eslint": "^8.46.4",
50
48
  "vite": "^7.2.4",
51
- "@formisch/core": "0.4.5",
52
- "@formisch/methods": "0.5.2"
49
+ "@formisch/core": "0.6.0",
50
+ "@formisch/methods": "0.7.0",
51
+ "@formisch/eslint-config": "0.1.0"
53
52
  },
54
53
  "peerDependencies": {
55
54
  "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",