@paragrav/rhf-utils 0.0.133 → 0.0.134

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
@@ -4,20 +4,27 @@
4
4
 
5
5
  Integration and utility library for [react-hook-form](https://www.react-hook-form.com/).
6
6
 
7
- If you have multiple forms and would like a more declarative API to manage their behavior (via built-in and custom options), including transformation of backend errors, and debugging logging/errors.
7
+ If you have multiple forms and would like a more declarative API to manage their behavior (via built-in and custom options), including transformation of backend errors, and debugging field errors.
8
8
 
9
9
  ## Features
10
10
 
11
11
  - built with and for [TypeScript](https://www.typescriptlang.org/)
12
- - global and form-specific configuration/options
13
- - with support for extendable options
12
+ - global configuration, such as:
13
+ - injecting your own hooks and UI (`FormChildrenWrapper`)
14
+ - server error transformation (`onSubmitErrorUnknown`)
15
+ - FieldErrors logging/throwing (`RhfUtilsClientConfig.FieldErrors`)
16
+ - extendable options type (`RhfUtilsFormOptions`)
17
+ - form-specific overrides
14
18
  - schema-typed Controller component
15
19
  - schema-typed FormSubmitError class
16
- - safer `FieldValues` type (i.e., `SafeFieldValues`)
17
- - flatter `FieldErrors` structure (i.e., `FlatFieldErrors`)
20
+ - throw in submit handler to add errors to RHF context and fail submit
21
+ - flatter `FieldErrors` structure (`FlatFieldErrors`)
22
+ - grouped into `all`, `fields`, `roots`, and `orphans`
23
+ - `FormErrorMessageByPath` for displaying error message (with `FormNonFieldErrorMarker`)
18
24
  - `zod` support
19
- - includes distinction between `z.input` and `z.output` types for transformations support
20
- - 3.3kB gzip core functionality (excluding [peer dependencies](#peer-dependencies))
25
+ - including `z.input` and `z.output` types for transformations
26
+ - safer `FieldValues` type (`SafeFieldValues`)
27
+ - 3.3kB min+gzip core functionality (excluding [peer dependencies](#peer-dependencies))
21
28
 
22
29
  ## Install
23
30
 
@@ -65,8 +72,8 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
65
72
  formRef, // ref
66
73
  context, // rhf UseFormReturn
67
74
  options, // RhfUtilsFormOptions (with any custom props)
68
- Controller, // strictly-typed rhf controller
69
- FormSubmitError, // strictly-typed error class
75
+ Controller, // rhf controller (SafeFieldValues-typed; no schema at this level)
76
+ FormSubmitError, // error class (SafeFieldValues-typed; no schema at this level)
70
77
  children, // RhfUtilsZodForm's Children instance
71
78
  },
72
79
  ) => {
@@ -147,7 +154,7 @@ Currently, only `zod` is supported.
147
154
  // submit handler
148
155
  onSubmit={async (
149
156
  data, // schema output
150
- context, // UseRhfUtilsFormOnSubmitContext (id, ref, rhf context, utils options, strictly-typed FormSubmitError class)
157
+ context, // UseRhfUtilsFormOnSubmitContext (id, ref, rhf context, utils options, schema-typed FormSubmitError class)
151
158
  event, // SubmitEvent
152
159
  ) => {
153
160
  await loginService(data);
@@ -168,12 +175,12 @@ Currently, only `zod` is supported.
168
175
  formRef, // ref
169
176
  context, // rhf UseFormReturn
170
177
  options, // RhfUtilsFormOptions
171
- Controller, // strictly-typed rhf controller
172
- FormSubmitError, // strictly-typed error class
178
+ Controller, // schema-typed rhf controller
179
+ FormSubmitError, // schema-typed error class
173
180
  }) => (
174
181
  <>
175
182
  <Controller
176
- name="email" // strictly-typed field name
183
+ name="email" // schema-typed field name
177
184
  render={({ field, formState: { isSubmitting } }) => (
178
185
  <label>
179
186
  Email
@@ -235,9 +242,9 @@ function Children({...}: RhfUtilsUseFormChildrenZodProps<typeof schema>) { }
235
242
 
236
243
  ## `FormSubmitError`
237
244
 
238
- This is an `Error`-based class you can use to throw a structured error in your submit handler. It is strictly-typed, so it only allows field names from your schema and `root`/`root.{string}` keys.
245
+ This is an `Error`-based class that you can use to throw a structured error in your submit handler. It uses `FormSubmitErrors` (with an "s") type's structure, which is a flat, simplified version of RHF's `FieldErrors`.
239
246
 
240
- It uses `FormSubmitErrors` type's structure, which is a flat, simplified version of RHF's `FieldErrors`.
247
+ It differs from `FlatFieldError` only in that it is narrower. Namely, it is schema-typed, so it allows field names from your schema and `root.${string}` keys. And only `type` (optional) and `message` props for error.
241
248
 
242
249
  Example:
243
250
 
@@ -5,8 +5,8 @@ import c from "./FormErrorMessage.mjs";
5
5
  const f = ({ path: o, Component: s }) => {
6
6
  const { errors: t } = g(), r = i(t, o, void 0), m = s ?? c;
7
7
  return r != null && r.message ? /* @__PURE__ */ n(a, { children: [
8
- /* @__PURE__ */ e(F, { path: o }),
9
- /* @__PURE__ */ e(m, { message: r.message })
8
+ /* @__PURE__ */ e(m, { message: r.message }),
9
+ /* @__PURE__ */ e(F, { path: o })
10
10
  ] }) : null;
11
11
  }, E = f;
12
12
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"FormErrorMessageByPath.mjs","sources":["../../../../src/errors/message/FormErrorMessageByPath.tsx"],"sourcesContent":["import type { FieldError } from 'react-hook-form';\nimport { get, useFormState } from 'react-hook-form';\n\nimport FormNonFieldErrorMarker from '../nonfield/FormNonFieldErrorMarker';\n\nimport FormErrorMessage from './FormErrorMessage';\n\ntype Props = {\n /** Field name as flat path. (e.g., \"address.street\") */\n path: string;\n /** Optional component to use to display message. (Defaults to {@link FormErrorMessage}) */\n Component?: React.FC<{ message: string }>;\n};\n\nconst FormErrorMessageByPath: React.FC<Props> = ({ path, Component }) => {\n const { errors } = useFormState();\n\n const error = get(errors, path, undefined) as FieldError | undefined;\n\n const _Component = Component ?? FormErrorMessage;\n\n if (!error?.message) return null;\n\n return (\n <>\n {/* marker (only required for non-root non-field errors) */}\n <FormNonFieldErrorMarker path={path} />\n\n {/* error message */}\n <_Component message={error.message} />\n </>\n );\n};\n\nexport default FormErrorMessageByPath;\n"],"names":["FormErrorMessageByPath","path","Component","errors","useFormState","error","get","_Component","FormErrorMessage","jsxs","Fragment","jsx","FormNonFieldErrorMarker","FormErrorMessageByPath$1"],"mappings":";;;;AAcA,MAAMA,IAA0C,CAAC,EAAE,MAAAC,GAAM,WAAAC,QAAgB;AACjE,QAAA,EAAE,QAAAC,MAAWC,KAEbC,IAAQC,EAAIH,GAAQF,GAAM,MAAS,GAEnCM,IAAaL,KAAaM;AAE5B,SAACH,KAAA,QAAAA,EAAO,UAKR,gBAAAI,EAAAC,GAAA,EAAA,UAAA;AAAA,IAAA,gBAAAC,EAACC,KAAwB,MAAAX,GAAY;AAAA,IAGpC,gBAAAU,EAAAJ,GAAA,EAAW,SAASF,EAAM,QAAS,CAAA;AAAA,EACtC,EAAA,CAAA,IAT0B;AAW9B,GAEAQ,IAAeb;"}
1
+ {"version":3,"file":"FormErrorMessageByPath.mjs","sources":["../../../../src/errors/message/FormErrorMessageByPath.tsx"],"sourcesContent":["import type { FieldError } from 'react-hook-form';\nimport { get, useFormState } from 'react-hook-form';\n\nimport FormNonFieldErrorMarker from '../nonfield/FormNonFieldErrorMarker';\n\nimport FormErrorMessage from './FormErrorMessage';\n\ntype Props = {\n /** Field name as flat path. (e.g., \"address.street\") */\n path: string;\n /** Optional component to use to display message. (Defaults to {@link FormErrorMessage}) */\n Component?: React.FC<{ message: string }>;\n};\n\nconst FormErrorMessageByPath: React.FC<Props> = ({ path, Component }) => {\n const { errors } = useFormState();\n\n const error = get(errors, path, undefined) as FieldError | undefined;\n\n const _Component = Component ?? FormErrorMessage;\n\n if (!error?.message) return null;\n\n return (\n <>\n {/* error message */}\n <_Component message={error.message} />\n\n {/* marker (only required for non-root non-field errors) */}\n <FormNonFieldErrorMarker path={path} />\n </>\n );\n};\n\nexport default FormErrorMessageByPath;\n"],"names":["FormErrorMessageByPath","path","Component","errors","useFormState","error","get","_Component","FormErrorMessage","jsxs","Fragment","jsx","FormNonFieldErrorMarker","FormErrorMessageByPath$1"],"mappings":";;;;AAcA,MAAMA,IAA0C,CAAC,EAAE,MAAAC,GAAM,WAAAC,QAAgB;AACjE,QAAA,EAAE,QAAAC,MAAWC,KAEbC,IAAQC,EAAIH,GAAQF,GAAM,MAAS,GAEnCM,IAAaL,KAAaM;AAE5B,SAACH,KAAA,QAAAA,EAAO,UAKR,gBAAAI,EAAAC,GAAA,EAAA,UAAA;AAAA,IAAC,gBAAAC,EAAAJ,GAAA,EAAW,SAASF,EAAM,QAAS,CAAA;AAAA,IAGpC,gBAAAM,EAACC,KAAwB,MAAAX,GAAY;AAAA,EACvC,EAAA,CAAA,IAT0B;AAW9B,GAEAY,IAAeb;"}
@@ -1,87 +1,87 @@
1
- import { jsx as h, jsxs as T } from "react/jsx-runtime";
1
+ import { jsx as c, jsxs as j } from "react/jsx-runtime";
2
2
  import "react";
3
- import { useFormContext as j } from "react-hook-form";
3
+ import { useFormContext as W } from "react-hook-form";
4
4
  import w from "../client/config/useRhfUtilsClientConfigContext.mjs";
5
5
  import E from "../devtool/LazyDevTool.mjs";
6
- import { FormSubmitError as s } from "../submit/error/FormSubmitError.mjs";
6
+ import { FormSubmitError as d } from "../submit/error/FormSubmitError.mjs";
7
7
  import S from "../submit/error/setCtxErrorsByFormSubmitErrors.mjs";
8
8
  import U from "../utils/PassthroughChildren.mjs";
9
- import W from "./_Controller.mjs";
10
- function A({
11
- formId: p,
12
- formRef: m,
9
+ import _ from "./_Controller.mjs";
10
+ function G({
11
+ formId: m,
12
+ formRef: p,
13
13
  //
14
14
  onSubmit: a,
15
- onSubmitError: d,
16
- onSubmitInvalid: i,
15
+ onSubmitError: s,
16
+ onSubmitInvalid: x,
17
17
  Children: l,
18
18
  //
19
19
  form: F,
20
20
  utils: r
21
21
  }) {
22
- const e = j(), t = w(), y = async (o) => {
22
+ const e = W(), t = w(), y = async (o) => {
23
23
  r != null && r.stopSubmitPropagation && o.stopPropagation();
24
24
  try {
25
- await e.handleSubmit(f, i)(o);
25
+ await e.handleSubmit(f, x)(o);
26
26
  } catch (n) {
27
- b(n, o);
27
+ P(n, o);
28
28
  }
29
29
  }, f = (o, n) => a == null ? void 0 : a(
30
30
  o,
31
31
  {
32
- formId: p,
33
- formRef: m,
32
+ formId: m,
33
+ formRef: p,
34
34
  context: e,
35
35
  utils: r,
36
- FormSubmitError: s
36
+ FormSubmitError: d
37
37
  },
38
38
  n
39
- ), b = (o, n) => {
40
- var x;
41
- const C = o instanceof s ? (
39
+ ), P = (o, n) => {
40
+ var i;
41
+ const C = o instanceof d ? (
42
42
  // consumer can manually throw FormSubmitError (e.g., manual validation)
43
43
  o.errors
44
44
  ) : (
45
45
  // if error is not FormSubmitError, consumer can provide global handler
46
- (x = t == null ? void 0 : t.onSubmitErrorUnknown) == null ? void 0 : x.call(t, o)
46
+ (i = t == null ? void 0 : t.onSubmitErrorUnknown) == null ? void 0 : i.call(t, o)
47
47
  );
48
- C && S(e, C), d == null || d(
48
+ C && S(e, C), s == null || s(
49
49
  o,
50
50
  {
51
- formId: p,
52
- formRef: m,
51
+ formId: m,
52
+ formRef: p,
53
53
  context: e,
54
54
  utils: r
55
55
  },
56
56
  n
57
57
  );
58
- }, c = {
59
- formId: p,
60
- formRef: m,
58
+ }, h = {
59
+ formId: m,
60
+ formRef: p,
61
61
  context: e,
62
62
  utils: r,
63
- Controller: W,
64
- FormSubmitError: s
65
- }, v = (t == null ? void 0 : t.FormComponent) ?? "form", P = (t == null ? void 0 : t.FormChildrenWrapper) ?? U;
66
- return /* @__PURE__ */ h(
63
+ Controller: _,
64
+ FormSubmitError: d
65
+ }, b = h, v = (t == null ? void 0 : t.FormComponent) ?? "form", T = (t == null ? void 0 : t.FormChildrenWrapper) ?? U;
66
+ return /* @__PURE__ */ c(
67
67
  v,
68
68
  {
69
69
  ...F,
70
- ref: m,
70
+ ref: p,
71
71
  onSubmit: (o) => void y(o),
72
- children: /* @__PURE__ */ T(P, { ...c, children: [
73
- (r == null ? void 0 : r.devTool) && /* @__PURE__ */ h(
72
+ children: /* @__PURE__ */ j(T, { ...b, children: [
73
+ (r == null ? void 0 : r.devTool) && /* @__PURE__ */ c(
74
74
  E,
75
75
  {
76
76
  props: typeof r.devTool == "object" ? r.devTool : void 0
77
77
  }
78
78
  ),
79
- /* @__PURE__ */ h(l, { ...c })
79
+ /* @__PURE__ */ c(l, { ...h })
80
80
  ] })
81
81
  }
82
82
  );
83
83
  }
84
84
  export {
85
- A as default
85
+ G as default
86
86
  };
87
87
  //# sourceMappingURL=Form.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Form.mjs","sources":["../../../src/form/Form.tsx"],"sourcesContent":["import React from 'react';\nimport type { UseFormHandleSubmit } from 'react-hook-form';\nimport { useFormContext } from 'react-hook-form';\n\nimport useRhfUtilsClientConfigMaybeContext from '@/client/config/useRhfUtilsClientConfigContext';\n\nimport LazyDevTool from '@/devtool/LazyDevTool';\n\nimport { FormSubmitError } from '@/submit/error/FormSubmitError';\nimport setCtxErrorsByFormSubmitErrors from '@/submit/error/setCtxErrorsByFormSubmitErrors';\n\nimport PassthroughChildren from '@/utils/PassthroughChildren';\n\nimport _Controller from './_Controller';\nimport type { SafeFieldValues } from './SafeFieldValues';\nimport type { UseRhfUtilsFormChildrenProps } from './UseRhfUtilsFormChildrenProps';\nimport type {\n UseRhfUtilsFormOnSubmitContext,\n UseRhfUtilsFormOnSubmitErrorContext,\n} from './UseRhfUtilsFormOnSubmitContext';\nimport type { UseRhfUtilsFormProps } from './UseRhfUtilsFormProps';\n\nexport type FormChildrenSlots = 'top' | 'bottom';\n\nexport type FormProps<\n TFieldValues extends SafeFieldValues,\n TTransformedValues extends SafeFieldValues,\n> = {\n formId: string;\n formRef: React.RefObject<HTMLFormElement>;\n} & Pick<\n UseRhfUtilsFormProps<TFieldValues, TTransformedValues>,\n | 'onSubmit'\n | 'onSubmitError'\n | 'onSubmitInvalid'\n //\n | 'Children'\n //\n | 'form'\n | 'utils'\n>;\n\nfunction _Form<\n TFieldValues extends SafeFieldValues,\n TTransformedValues extends SafeFieldValues,\n>({\n formId,\n formRef,\n //\n onSubmit,\n onSubmitError,\n onSubmitInvalid,\n Children,\n //\n form,\n utils,\n}: FormProps<TFieldValues, TTransformedValues>) {\n const rhfContext = useFormContext<\n TFieldValues,\n unknown,\n TTransformedValues\n >();\n\n const config = useRhfUtilsClientConfigMaybeContext();\n\n // handlers\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n // cannot stop propagation in handleSubmitValid, b/c it receives a different event object\n if (utils?.stopSubmitPropagation) event.stopPropagation();\n\n try {\n await rhfContext.handleSubmit(handleSubmitValid, onSubmitInvalid)(event);\n } catch (error) {\n handleSubmitError(error, event);\n }\n };\n\n const handleSubmitValid = ((\n data: TTransformedValues,\n event?: React.BaseSyntheticEvent,\n ) => {\n return onSubmit?.(\n data,\n {\n formId,\n formRef,\n context: rhfContext,\n utils,\n FormSubmitError: FormSubmitError<TFieldValues>,\n } satisfies UseRhfUtilsFormOnSubmitContext<\n TFieldValues,\n TTransformedValues\n >,\n event as React.BaseSyntheticEvent<SubmitEvent>, // `as` required due to conditional generic\n );\n }) as Parameters<UseFormHandleSubmit<TFieldValues, TTransformedValues>>[0];\n\n const handleSubmitError = (\n error: unknown,\n event: React.BaseSyntheticEvent,\n ) => {\n // get `FormSubmitErrors`, if possible\n const formSubmitErrors =\n error instanceof FormSubmitError\n ? // consumer can manually throw FormSubmitError (e.g., manual validation)\n (error as FormSubmitError).errors // `as` to avoid `<any>`\n : // if error is not FormSubmitError, consumer can provide global handler\n config?.onSubmitErrorUnknown?.(error);\n\n if (formSubmitErrors)\n setCtxErrorsByFormSubmitErrors(rhfContext, formSubmitErrors);\n\n onSubmitError?.(\n error,\n {\n formId,\n formRef,\n context: rhfContext,\n utils,\n } satisfies UseRhfUtilsFormOnSubmitErrorContext<\n TFieldValues,\n TTransformedValues\n >,\n event as React.BaseSyntheticEvent<SubmitEvent>, // `as` required due to conditional generic\n );\n };\n\n const childrenProps: UseRhfUtilsFormChildrenProps<\n TFieldValues,\n TTransformedValues\n > = {\n formId,\n formRef,\n context: rhfContext,\n utils,\n Controller: _Controller<TFieldValues>,\n FormSubmitError: FormSubmitError<TFieldValues>,\n };\n\n const FormComponent = config?.FormComponent ?? 'form';\n\n const FormChildrenWrapper =\n config?.FormChildrenWrapper ?? PassthroughChildren;\n\n return (\n <FormComponent\n {...form}\n ref={formRef}\n onSubmit={(e) => void handleSubmit(e)}\n >\n <FormChildrenWrapper {...childrenProps}>\n {utils?.devTool && (\n <LazyDevTool\n props={\n typeof utils.devTool === 'object' ? utils.devTool : undefined\n }\n />\n )}\n\n <Children {...childrenProps} />\n </FormChildrenWrapper>\n </FormComponent>\n );\n}\n\nexport default _Form;\n"],"names":["_Form","formId","formRef","onSubmit","onSubmitError","onSubmitInvalid","Children","form","utils","rhfContext","useFormContext","config","useRhfUtilsClientConfigMaybeContext","handleSubmit","event","handleSubmitValid","error","handleSubmitError","data","FormSubmitError","formSubmitErrors","_a","setCtxErrorsByFormSubmitErrors","childrenProps","_Controller","FormComponent","FormChildrenWrapper","PassthroughChildren","jsx","e","jsxs","LazyDevTool"],"mappings":";;;;;;;;;AA0CA,SAASA,EAGP;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA;AAAA,EAEA,UAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,UAAAC;AAAA;AAAA,EAEA,MAAAC;AAAA,EACA,OAAAC;AACF,GAAgD;AAC9C,QAAMC,IAAaC,KAMbC,IAASC,KAITC,IAAe,OAAOC,MAA4C;AAElE,IAAAN,KAAA,QAAAA,EAAO,yBAAuBM,EAAM,gBAAgB;AAEpD,QAAA;AACF,YAAML,EAAW,aAAaM,GAAmBV,CAAe,EAAES,CAAK;AAAA,aAChEE,GAAO;AACd,MAAAC,EAAkBD,GAAOF,CAAK;AAAA,IAChC;AAAA,EAAA,GAGIC,IAAqB,CACzBG,GACAJ,MAEOX,KAAA,gBAAAA;AAAA,IACLe;AAAA,IACA;AAAA,MACE,QAAAjB;AAAA,MACA,SAAAC;AAAA,MACA,SAASO;AAAA,MACT,OAAAD;AAAA,MACA,iBAAAW;AAAA,IACF;AAAA,IAIAL;AAAA,KAIEG,IAAoB,CACxBD,GACAF,MACG;;AAEH,UAAMM,IACJJ,aAAiBG;AAAA;AAAA,MAEZH,EAA0B;AAAA;AAAA;AAAA,OAE3BK,IAAAV,KAAA,gBAAAA,EAAQ,yBAAR,gBAAAU,EAAA,KAAAV,GAA+BK;AAAA;AAEjC,IAAAI,KACFE,EAA+Bb,GAAYW,CAAgB,GAE7DhB,KAAA,QAAAA;AAAA,MACEY;AAAA,MACA;AAAA,QACE,QAAAf;AAAA,QACA,SAAAC;AAAA,QACA,SAASO;AAAA,QACT,OAAAD;AAAA,MACF;AAAA,MAIAM;AAAA;AAAA,EACF,GAGIS,IAGF;AAAA,IACF,QAAAtB;AAAA,IACA,SAAAC;AAAA,IACA,SAASO;AAAA,IACT,OAAAD;AAAA,IACA,YAAYgB;AAAA,IACZ,iBAAAL;AAAA,EAAA,GAGIM,KAAgBd,KAAA,gBAAAA,EAAQ,kBAAiB,QAEzCe,KACJf,KAAA,gBAAAA,EAAQ,wBAAuBgB;AAG/B,SAAA,gBAAAC;AAAA,IAACH;AAAA,IAAA;AAAA,MACE,GAAGlB;AAAA,MACJ,KAAKL;AAAA,MACL,UAAU,CAAC2B,MAAM,KAAKhB,EAAagB,CAAC;AAAA,MAEpC,UAAA,gBAAAC,EAACJ,GAAqB,EAAA,GAAGH,GACtB,UAAA;AAAA,SAAAf,KAAA,gBAAAA,EAAO,YACN,gBAAAoB;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,OACE,OAAOvB,EAAM,WAAY,WAAWA,EAAM,UAAU;AAAA,UAAA;AAAA,QAExD;AAAA,QAGF,gBAAAoB,EAACtB,GAAU,EAAA,GAAGiB,GAAe;AAAA,MAAA,GAC/B;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"Form.mjs","sources":["../../../src/form/Form.tsx"],"sourcesContent":["import React from 'react';\nimport type { UseFormHandleSubmit } from 'react-hook-form';\nimport { useFormContext } from 'react-hook-form';\n\nimport type { RhfUtilsFormChildrenWrapperProps } from '@/client/config/RhfUtilsClientConfig';\nimport useRhfUtilsClientConfigMaybeContext from '@/client/config/useRhfUtilsClientConfigContext';\n\nimport LazyDevTool from '@/devtool/LazyDevTool';\n\nimport { FormSubmitError } from '@/submit/error/FormSubmitError';\nimport setCtxErrorsByFormSubmitErrors from '@/submit/error/setCtxErrorsByFormSubmitErrors';\n\nimport PassthroughChildren from '@/utils/PassthroughChildren';\n\nimport _Controller from './_Controller';\nimport type { SafeFieldValues } from './SafeFieldValues';\nimport type { UseRhfUtilsFormChildrenProps } from './UseRhfUtilsFormChildrenProps';\nimport type {\n UseRhfUtilsFormOnSubmitContext,\n UseRhfUtilsFormOnSubmitErrorContext,\n} from './UseRhfUtilsFormOnSubmitContext';\nimport type { UseRhfUtilsFormProps } from './UseRhfUtilsFormProps';\n\nexport type FormChildrenSlots = 'top' | 'bottom';\n\nexport type FormProps<\n TFieldValues extends SafeFieldValues,\n TTransformedValues extends SafeFieldValues,\n> = {\n formId: string;\n formRef: React.RefObject<HTMLFormElement>;\n} & Pick<\n UseRhfUtilsFormProps<TFieldValues, TTransformedValues>,\n | 'onSubmit'\n | 'onSubmitError'\n | 'onSubmitInvalid'\n //\n | 'Children'\n //\n | 'form'\n | 'utils'\n>;\n\nfunction _Form<\n TFieldValues extends SafeFieldValues,\n TTransformedValues extends SafeFieldValues,\n>({\n formId,\n formRef,\n //\n onSubmit,\n onSubmitError,\n onSubmitInvalid,\n Children,\n //\n form,\n utils,\n}: FormProps<TFieldValues, TTransformedValues>) {\n const rhfContext = useFormContext<\n TFieldValues,\n unknown,\n TTransformedValues\n >();\n\n const config = useRhfUtilsClientConfigMaybeContext();\n\n // handlers\n\n const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {\n // cannot stop propagation in handleSubmitValid, b/c it receives a different event object\n if (utils?.stopSubmitPropagation) event.stopPropagation();\n\n try {\n await rhfContext.handleSubmit(handleSubmitValid, onSubmitInvalid)(event);\n } catch (error) {\n handleSubmitError(error, event);\n }\n };\n\n const handleSubmitValid = ((\n data: TTransformedValues,\n event?: React.BaseSyntheticEvent,\n ) => {\n return onSubmit?.(\n data,\n {\n formId,\n formRef,\n context: rhfContext,\n utils,\n FormSubmitError: FormSubmitError<TFieldValues>,\n } satisfies UseRhfUtilsFormOnSubmitContext<\n TFieldValues,\n TTransformedValues\n >,\n event as React.BaseSyntheticEvent<SubmitEvent>, // `as` required due to conditional generic\n );\n }) as Parameters<UseFormHandleSubmit<TFieldValues, TTransformedValues>>[0];\n\n const handleSubmitError = (\n error: unknown,\n event: React.BaseSyntheticEvent,\n ) => {\n // get `FormSubmitErrors`, if possible\n const formSubmitErrors =\n error instanceof FormSubmitError\n ? // consumer can manually throw FormSubmitError (e.g., manual validation)\n (error as FormSubmitError).errors // `as` to avoid `<any>`\n : // if error is not FormSubmitError, consumer can provide global handler\n config?.onSubmitErrorUnknown?.(error);\n\n if (formSubmitErrors)\n setCtxErrorsByFormSubmitErrors(rhfContext, formSubmitErrors);\n\n onSubmitError?.(\n error,\n {\n formId,\n formRef,\n context: rhfContext,\n utils,\n } satisfies UseRhfUtilsFormOnSubmitErrorContext<\n TFieldValues,\n TTransformedValues\n >,\n event as React.BaseSyntheticEvent<SubmitEvent>, // `as` required due to conditional generic\n );\n };\n\n const childrenProps: UseRhfUtilsFormChildrenProps<\n TFieldValues,\n TTransformedValues\n > = {\n formId,\n formRef,\n context: rhfContext,\n utils,\n Controller: _Controller<TFieldValues>,\n FormSubmitError: FormSubmitError<TFieldValues>,\n };\n\n // children wrapper is not specific to schema (not possible)\n const childrenWrapperProps =\n childrenProps as RhfUtilsFormChildrenWrapperProps;\n\n const FormComponent = config?.FormComponent ?? 'form';\n\n const FormChildrenWrapper =\n config?.FormChildrenWrapper ?? PassthroughChildren;\n\n return (\n <FormComponent\n {...form}\n ref={formRef}\n onSubmit={(e) => void handleSubmit(e)}\n >\n <FormChildrenWrapper {...childrenWrapperProps}>\n {utils?.devTool && (\n <LazyDevTool\n props={\n typeof utils.devTool === 'object' ? utils.devTool : undefined\n }\n />\n )}\n\n <Children {...childrenProps} />\n </FormChildrenWrapper>\n </FormComponent>\n );\n}\n\nexport default _Form;\n"],"names":["_Form","formId","formRef","onSubmit","onSubmitError","onSubmitInvalid","Children","form","utils","rhfContext","useFormContext","config","useRhfUtilsClientConfigMaybeContext","handleSubmit","event","handleSubmitValid","error","handleSubmitError","data","FormSubmitError","formSubmitErrors","_a","setCtxErrorsByFormSubmitErrors","childrenProps","_Controller","childrenWrapperProps","FormComponent","FormChildrenWrapper","PassthroughChildren","jsx","e","jsxs","LazyDevTool"],"mappings":";;;;;;;;;AA2CA,SAASA,EAGP;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA;AAAA,EAEA,UAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,UAAAC;AAAA;AAAA,EAEA,MAAAC;AAAA,EACA,OAAAC;AACF,GAAgD;AAC9C,QAAMC,IAAaC,KAMbC,IAASC,KAITC,IAAe,OAAOC,MAA4C;AAElE,IAAAN,KAAA,QAAAA,EAAO,yBAAuBM,EAAM,gBAAgB;AAEpD,QAAA;AACF,YAAML,EAAW,aAAaM,GAAmBV,CAAe,EAAES,CAAK;AAAA,aAChEE,GAAO;AACd,MAAAC,EAAkBD,GAAOF,CAAK;AAAA,IAChC;AAAA,EAAA,GAGIC,IAAqB,CACzBG,GACAJ,MAEOX,KAAA,gBAAAA;AAAA,IACLe;AAAA,IACA;AAAA,MACE,QAAAjB;AAAA,MACA,SAAAC;AAAA,MACA,SAASO;AAAA,MACT,OAAAD;AAAA,MACA,iBAAAW;AAAA,IACF;AAAA,IAIAL;AAAA,KAIEG,IAAoB,CACxBD,GACAF,MACG;;AAEH,UAAMM,IACJJ,aAAiBG;AAAA;AAAA,MAEZH,EAA0B;AAAA;AAAA;AAAA,OAE3BK,IAAAV,KAAA,gBAAAA,EAAQ,yBAAR,gBAAAU,EAAA,KAAAV,GAA+BK;AAAA;AAEjC,IAAAI,KACFE,EAA+Bb,GAAYW,CAAgB,GAE7DhB,KAAA,QAAAA;AAAA,MACEY;AAAA,MACA;AAAA,QACE,QAAAf;AAAA,QACA,SAAAC;AAAA,QACA,SAASO;AAAA,QACT,OAAAD;AAAA,MACF;AAAA,MAIAM;AAAA;AAAA,EACF,GAGIS,IAGF;AAAA,IACF,QAAAtB;AAAA,IACA,SAAAC;AAAA,IACA,SAASO;AAAA,IACT,OAAAD;AAAA,IACA,YAAYgB;AAAA,IACZ,iBAAAL;AAAA,EAAA,GAIIM,IACJF,GAEIG,KAAgBf,KAAA,gBAAAA,EAAQ,kBAAiB,QAEzCgB,KACJhB,KAAA,gBAAAA,EAAQ,wBAAuBiB;AAG/B,SAAA,gBAAAC;AAAA,IAACH;AAAA,IAAA;AAAA,MACE,GAAGnB;AAAA,MACJ,KAAKL;AAAA,MACL,UAAU,CAAC4B,MAAM,KAAKjB,EAAaiB,CAAC;AAAA,MAEpC,UAAA,gBAAAC,EAACJ,GAAqB,EAAA,GAAGF,GACtB,UAAA;AAAA,SAAAjB,KAAA,gBAAAA,EAAO,YACN,gBAAAqB;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,OACE,OAAOxB,EAAM,WAAY,WAAWA,EAAM,UAAU;AAAA,UAAA;AAAA,QAExD;AAAA,QAGF,gBAAAqB,EAACvB,GAAU,EAAA,GAAGiB,GAAe;AAAA,MAAA,GAC/B;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -1,7 +1,6 @@
1
1
  import { UseFormProps } from 'react-hook-form';
2
2
  import { FlatFieldErrorsOutputConfig } from '../../errors/flat/context/FlatFieldErrorsOutputConfig';
3
3
  import { RhfUtilsFormOptions } from '../../form/RhfUtilsFormOptions';
4
- import { SafeFieldValues } from '../../form/SafeFieldValues';
5
4
  import { UseRhfUtilsFormChildrenProps } from '../../form/UseRhfUtilsFormChildrenProps';
6
5
  import { FormSubmitErrors } from '../../submit/error/FormSubmitErrors';
7
6
 
@@ -41,11 +40,13 @@ export type RhfUtilsClientConfig = {
41
40
  /**
42
41
  * Wrap all form bodies with your own hooks, components, etc.
43
42
  *
43
+ * (NOTE: not schema-typed as not possible at this level)
44
+ *
44
45
  * Use cases:
45
46
  * - custom hooks/behaviors based on `options`
46
47
  * - shared header, footer
47
48
  */
48
- FormChildrenWrapper?: <TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>(props: React.PropsWithChildren<UseRhfUtilsFormChildrenProps<TFieldValues, TTransformedValues>>) => React.ReactNode;
49
+ FormChildrenWrapper?: (props: RhfUtilsFormChildrenWrapperProps) => React.ReactNode;
49
50
  /**
50
51
  * Global submit error handler when/if submit handler throws an error other than {@link FormSubmitError}.
51
52
  *
@@ -64,3 +65,7 @@ export type RhfUtilsClientConfig = {
64
65
  output?: FlatFieldErrorsOutputConfig;
65
66
  };
66
67
  };
68
+ /**
69
+ * Non-schema-typed version of `UseRhfUtilsFormChildrenProps` for global config.
70
+ */
71
+ export type RhfUtilsFormChildrenWrapperProps = React.PropsWithChildren<UseRhfUtilsFormChildrenProps>;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@paragrav/rhf-utils",
3
3
  "author": "paragrav.dev",
4
4
  "license": "MIT",
5
- "version": "0.0.133",
5
+ "version": "0.0.134",
6
6
  "description": "Integration utilities for react-hook-form.",
7
7
  "type": "module",
8
8
  "sideEffects": false,