Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

- Add `dirtyFields` field to `formState`
- Add `valueAsNumber` field to the option argument of `register`
- Add new methods to useFormReturn: `clearErrors`, `resetField`, `setError`, `setFocus`, `trigger`, `unregister`
- Expand validation options in `register`: `maxLength`, `minLength`, `max`, `min`, `pattern`
- Add `useFormContext` hook and `FormProvider` module

# v0.0.8

Expand Down
33 changes: 30 additions & 3 deletions doc/transformation.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type fieldDirtyOfInputs = {
}

type rec useFormReturnOfInputs<'setValueAs> = {
clearErrors: variantOfInputs => unit
control: controlOfInputs,
register: (variantOfInputs, ~options: registerOptionsOfInputs<'setValueAs>=?) => JsxDOM.domProps,
handleSubmit: (inputs => unit) => JsxEvent.Form.t => unit,
Expand All @@ -54,11 +55,25 @@ type rec useFormReturnOfInputs<'setValueAs> = {
formState: formStateOfInputs,
getFieldState: (variantOfInputs, formStateOfInputs) => fieldStateOfInputs,
setValue: (variantOfInputs, ReactHookForm.value, ~options: setValueConfigOfInputs=?) => unit,
reset: (~options:defaultValues=?) => unit
}
reset: (~options:defaultValues=?) => unit,
resetField: (variantOfInputs, ~options: defaultValues=?) => unit,
setError: (variantOfInputs, fieldErrorOfInputs, ~options: setErrorConfigOfInputs=?) => unit,
setFocus: variantOfInputs => unit,
trigger: variantOfInputs => unit,
unregister: (variantOfInputs, ~options: registerOptionsOfInputs<'setValueAs>=?) => unit,
}
and controlOfInputs
and variantOfInputs = | @as("example") Example | @as("exampleRequired") ExampleRequired | @as("cart") Cart
and registerOptionsOfInputs<'setValueAs> = {required?: bool, setValueAs?: 'setValueAs, valueAsNumber?: bool}
and registerOptionsOfInputs<'setValueAs> = {
required?: bool,
setValueAs?: 'setValueAs,
valueAsNumber?: bool,
maxLength?: int,
minLength?: int,
max?: float,
min?: float,
pattern?: RegExp.t
}
and formStateOfInputs = {
isDirty: bool,
isValid: bool,
Expand All @@ -80,12 +95,18 @@ and setValueConfigOfInputs = {
shouldDirty: bool,
shouldTouch: bool,
}
and setErrorConfigOfInputs = {
shouldFocus?: bool
}

@module("react-hook-form")
external useFormOfInputs: (
~options: useFormParamsOfInputs<'resolver>=?
) => useFormReturnOfInputs<'setValueAs> = "useForm"

@module("react-hook-form")
external useFormContextOfInputs: unit => useFormReturnOfInputs<'setValueAs> = "useFormContext"

module ControllerOfInputs = {
type controllerRulesOfInputs = {required?: bool}
type controllerFieldsOfInputs = {field: JsxDOM.domProps}
Expand All @@ -99,6 +120,12 @@ module ControllerOfInputs = {
) => React.element = "Controller"
}

module FormProviderOfInputs = {
type props<'setValueAs> = {...useFormReturnOfInputs<'setValueAs>, children: React.element}
@module("react-hook-form")
external make: props<'setValueAs> => React.element = "FormProvider"
}

//useWatch
type useWatchParamsOfInputs = {
name: variantOfInputs,
Expand Down
233 changes: 219 additions & 14 deletions src/ppx/signature.ml
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,39 @@ let map_type_decl
Sig.type_ Recursive
[
(* type useFormReturnOfInputs<'setValueAs> = {
clearErrors: variantOfInputs => unit,
control: controlOfInputs,
register: (variantOfInputs, ~options: registerOptionsOfInputs<'setValueAs>=?) => JsxDOM.domProps,
handleSubmit: (inputs => unit) => JsxEvent.Form.t => unit,
watch: variantOfInputs => valuesOfInputs,
getValues: variantOfInputs => option<valuesOfInputs>,
reset: (~options: defaultValuesOfInputs=?) => unit,
formState: formStateOfInputs,
} *)
getFieldState: (variantOfInputs, formStateOfInputs) => fieldStateOfInputs,
setValue: (variantOfInputs, ReactHookForm.value, ~options: setValueConfigOfInputs=?) => unit,
reset: (~options: defaultValuesOfInputs=?) => unit,
resetField: (variantOfInputs, ~options: defaultValuesOfInputs=?) => unit,
setError: (variantOfInputs, fieldErrorOfInputs, ~options: setErrorConfigOfInputs=?) => unit,
setFocus: variantOfInputs => unit,
trigger: variantOfInputs => unit,
unregister: (variantOfInputs, ~options: registerOptionsOfInputs<'setValueAs>=?) => unit,
} *)
Type.mk
(mkloc ("useFormReturnOf" ^ capitalize record_name) ptype_loc)
~params:[ (Typ.var "setValueAs", (NoVariance, NoInjectivity)) ]
~priv:Public
~kind:
(Ptype_record
[
(* clearErrors: variantOfInputs => unit, *)
Type.field ~mut:Immutable (mknoloc "clearErrors")
(uncurried_core_type_arrow ~arity:1
[
Typ.arrow Nolabel
(Typ.constr
(lid @@ "variantOf" ^ capitalize record_name)
[])
(Typ.constr (lid "unit") []);
]);
(* control: controlOfInputs *)
Type.field ~mut:Immutable (mknoloc "control")
(Typ.constr
Expand Down Expand Up @@ -313,17 +331,6 @@ let map_type_decl
[];
]);
]);
(* reset: (~options: defaultValuesOfInputs=?) => unit, *)
Type.field ~mut:Immutable (mknoloc "reset")
(uncurried_core_type_arrow ~arity:1
[
Typ.arrow (Optional "options")
(Typ.constr ~attrs:[ attr_named_arg ]
(lid @@ "defaultValuesOf"
^ capitalize record_name)
[])
(Typ.constr (lid "unit") []);
]);
(* formState: formStateOfInputs, *)
Type.field ~mut:Immutable (mknoloc "formState")
(Typ.constr
Expand Down Expand Up @@ -368,6 +375,87 @@ let map_type_decl
[])
(Typ.constr (lid "unit") [])));
]);
(* reset: (~options: defaultValuesOfInputs=?) => unit, *)
Type.field ~mut:Immutable (mknoloc "reset")
(uncurried_core_type_arrow ~arity:1
[
Typ.arrow (Optional "options")
(Typ.constr ~attrs:[ attr_named_arg ]
(lid @@ "defaultValuesOf"
^ capitalize record_name)
[])
(Typ.constr (lid "unit") []);
]);
(* resetField: (variantOfInputs, ~options: defaultValuesOfInputs=?) => unit, *)
Type.field ~mut:Immutable (mknoloc "resetField")
(uncurried_core_type_arrow ~arity:2
[
Typ.arrow Nolabel
(Typ.constr
(lid @@ "variantOf" ^ capitalize record_name)
[])
(Typ.arrow (Optional "options")
(Typ.constr ~attrs:[ attr_named_arg ]
(lid @@ "defaultValuesOf"
^ capitalize record_name)
[])
(Typ.constr (lid "unit") []));
]);
(* setError: (variantOfInputs, fieldErrorOfInputs, ~options: setErrorConfigOfInputs=?) => unit, *)
Type.field ~mut:Immutable (mknoloc "setError")
(uncurried_core_type_arrow ~arity:3
[
Typ.arrow Nolabel
(Typ.constr
(lid @@ "variantOf" ^ capitalize record_name)
[])
(Typ.arrow Nolabel
(Typ.constr
(lid @@ "fieldErrorOf"
^ capitalize record_name)
[])
(Typ.arrow (Optional "options")
(Typ.constr
(lid @@ "setErrorConfigOf"
^ capitalize record_name)
[])
(Typ.constr (lid "unit") [])));
]);
(* setFocus: variantOfInputs => unit, *)
Type.field ~mut:Immutable (mknoloc "setFocus")
(uncurried_core_type_arrow ~arity:1
[
Typ.arrow Nolabel
(Typ.constr
(lid @@ "variantOf" ^ capitalize record_name)
[])
(Typ.constr (lid "unit") []);
]);
(* trigger: variantOfInputs => unit, *)
Type.field ~mut:Immutable (mknoloc "trigger")
(uncurried_core_type_arrow ~arity:1
[
Typ.arrow Nolabel
(Typ.constr
(lid @@ "variantOf" ^ capitalize record_name)
[])
(Typ.constr (lid "unit") []);
]);
(* unregister: (variantOfInputs, ~options: registerOptionsOfInputs<'setValueAs>=?) => unit, *)
Type.field ~mut:Immutable (mknoloc "unregister")
(uncurried_core_type_arrow ~arity:2
[
Typ.arrow Nolabel
(Typ.constr
(lid @@ "variantOf" ^ capitalize record_name)
[])
(Typ.arrow (Optional "options")
(Typ.constr ~attrs:[ attr_named_arg ]
(lid @@ "registerOptionsOf"
^ capitalize record_name)
[ Typ.var "setValueAs" ])
(Typ.constr (lid "unit") []));
]);
]);
(* type controlOfInputs *)
Type.mk
Expand All @@ -378,7 +466,16 @@ let map_type_decl
(mkloc ("variantOf" ^ capitalize record_name) ptype_loc)
~priv:Public
~kind:(Ptype_variant (make_const_decls fields ptype_loc));
(* type registerOptionsOfInputs<'setValueAs> = {required?: bool, setValueAs?: 'setValueAs, valueAsNumber?: bool} *)
(* type registerOptionsOfInputs<'setValueAs> = {
required?: bool,
setValueAs?: 'setValueAs,
valueAsNumber?: bool,
maxLength?: int,
minLength?: int,
max?: float,
min?: float,
pattern?: RegExp.t
} *)
Type.mk
(mkloc ("registerOptionsOf" ^ capitalize record_name) ptype_loc)
~params:[ (Typ.var "setValueAs", (NoVariance, NoInjectivity)) ]
Expand All @@ -394,6 +491,21 @@ let map_type_decl
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "valueAsNumber")
(Typ.constr (lid "bool") []);
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "maxLength")
(Typ.constr (lid "int") []);
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "minLength")
(Typ.constr (lid "int") []);
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "max")
(Typ.constr (lid "float") []);
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "min")
(Typ.constr (lid "float") []);
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "pattern")
(Typ.constr (lid "RegExp.t") []);
]);
(* type formStateOfInputs = {
isDirty: bool,
Expand Down Expand Up @@ -512,6 +624,16 @@ let map_type_decl
(mknoloc "shouldTouch")
(Typ.constr (lid "bool") []);
]);
Type.mk
(mkloc ("setErrorConfigOf" ^ capitalize record_name) ptype_loc)
~priv:Public
~kind:
(Ptype_record
[
Type.field ~attrs:[ attr_optional ] ~mut:Immutable
(mknoloc "shouldFocus")
(Typ.constr (lid "bool") []);
]);
]
in

Expand Down Expand Up @@ -542,6 +664,31 @@ let map_type_decl
[ Typ.var "setValueAs" ]);
]))
in
(* @module("react-hook-form")
external useFormContextOfInputs: unit => useFormReturnOfInputs<'setValueAs> = "useFormContext" *)
let primitive_use_form_context =
Sig.value
(Val.mk
~attrs:
[
Attr.mk (mknoloc "module")
(PStr
[
Str.eval
@@ Exp.constant (Const.string "react-hook-form");
]);
]
~prim:[ "useFormContext" ]
(mknoloc @@ "useFormContextOf" ^ capitalize record_name)
(uncurried_core_type_arrow ~arity:0
[
Typ.arrow Nolabel
(Typ.constr (lid "unit") [])
(Typ.constr
(lid @@ "useFormReturnOf" ^ capitalize record_name)
[ Typ.var "setValueAs" ]);
]))
in
(* module ControllerOfInputs = {
type controllerRulesOfInputs = {required?: bool}
type controllerFieldsOfInputs = {field: JsxDOM.domProps}
Expand Down Expand Up @@ -657,6 +804,62 @@ let map_type_decl
]))
in

(* module FormProviderOfInputs = {
type props<'setValueAs> = {...useFormReturnOfInputs<'setValueAs>, children: React.element}
@module("react-hook-form")
external make: props<'setValueAs> => React.element = "FormProvider"
} *)
let module_form_provider =
Sig.module_
(Md.mk
(mknoloc @@ Some ("FormProviderOf" ^ capitalize record_name))
(Mty.signature
[
Sig.type_ Recursive
[
(* type props<'setValueAs> = {...useFormReturnOfInputs<'setValueAs>, children: React.element} *)
Type.mk (mkloc "props" ptype_loc) ~priv:Public
~params:
[
(Typ.var "setValueAs", (NoVariance, NoInjectivity));
]
~kind:
(Ptype_record
[
Type.field ~mut:Immutable (mknoloc "...")
(Typ.constr
(lid @@ "useFormReturnOf"
^ capitalize record_name)
[ Typ.var "setValueAs" ]);
Type.field ~mut:Immutable (mknoloc "children")
(Typ.constr (lid "React.element") []);
]);
];
(* @module("react-hook-form")
external make: props<'setValueAs> => React.element = "FormProvider" *)
Sig.value
(Val.mk
~attrs:
[
Attr.mk (mknoloc "module")
(PStr
[
Str.eval
@@ Exp.constant
(Const.string "react-hook-form");
]);
]
~prim:[ "FormProvider" ] (mknoloc "make")
(uncurried_core_type_arrow ~arity:1
[
Typ.arrow Nolabel
(Typ.constr (lid "props")
[ Typ.var "setValueAs" ])
(Typ.constr (lid "React.element") []);
]));
]))
in

(* type useWatchParamsOfInputs = {
name: variantOfInputs,
control: controlOfInputs=?,
Expand Down Expand Up @@ -928,7 +1131,9 @@ let map_type_decl
type_decls3;
type_decls4;
primitive_use_form;
primitive_use_form_context;
module_controller;
module_form_provider;
type_decls5;
primitive_use_watch;
]
Expand Down
Loading