@paragrav/rhf-utils 0.0.119 → 0.0.120

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
@@ -1,5 +1,9 @@
1
1
  # README
2
2
 
3
+ ## About
4
+
5
+ Integration and utility library for react-hook-form.
6
+
3
7
  ## Install
4
8
 
5
9
  ```sh
@@ -14,16 +18,16 @@ To configure, create a file `config.tsx` with desired configuration settings. Th
14
18
 
15
19
  ```tsx
16
20
  export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
17
- // defaults -- overridable per form instance
21
+ // overridable per form instance
18
22
  defaults: {
19
23
  // globally-relevant subset of RHF's `UseFormProps` options
20
24
  rhf: {
21
- mode: 'onBlur',
25
+ mode: 'onSubmit',
22
26
  },
23
27
 
24
28
  // RhfUtilsFormOptions (see further below)
25
29
  utils: {
26
- // enable dev tool on dev env
30
+ stopSubmitPropagation: true,
27
31
  devTool: import.meta.env.DEV,
28
32
  },
29
33
 
@@ -38,7 +42,8 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
38
42
  FormComponent: Form.Root,
39
43
 
40
44
  // optional wrapper to inject your own hooks and components
41
- // `children` prop is provided by RhfUtilsZodForm's Children prop
45
+ // around all RhfUtilsZodForm instances
46
+ // (see further below for more info)
42
47
  FormChildren: (
43
48
  // UseRhfUtilsFormChildrenProps
44
49
  {
@@ -48,32 +53,32 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
48
53
  options, // RhfUtilsFormOptions
49
54
  Controller, // strictly-typed controller
50
55
  FormSubmitError, // strictly-typed error class
51
- children, // RhfUtilsZodForm.Children
56
+ children, // RhfUtilsZodForm's Children instance
52
57
  },
53
58
  ) => {
54
- // navigation blocker (using custom option)
55
- useFormRouterBlocker(!!options?.prompter);
59
+ // your navigation blocker (using custom option prop -- see "Extend RhfUtilsFormOptions" section)
60
+ useMyFormNavigationPrompt(!!options?.enableMyFormNavigationPrompt);
56
61
 
57
62
  return (
58
63
  <>
59
- {/* specific form children -- e.g., fields, etc. */}
64
+ {/* RhfUtilsZodForm Children outlet */}
60
65
  {children}
61
66
 
62
- {/* global error list */}
63
- <RootErrorsListFromFlatFieldErrorsContext />
67
+ {/* root errors list */}
68
+ <RootErrorsList />
64
69
  </>
65
70
  );
66
71
  },
67
72
 
68
- // non-FormSubmitError throw in onSubmit
69
- // example use case: transform backend error
73
+ // non-FormSubmitError thrown in onSubmit
74
+ // use case: catch backend error and transform data for frontend
70
75
  onSubmitUnknownError: (
71
76
  error, // unknown
72
77
  ) => {
73
78
  // if other error, re-throw to handle in ErrorBoundary
74
79
  if (!(error instanceof MyServerError)) throw error;
75
80
 
76
- // return FormSubmitErrors object to be merged into RHF context errors
81
+ // return FormSubmitErrors object to be merged to RHF context errors
77
82
  return transformServerErrorToFormSubmitErrors(error);
78
83
  },
79
84
 
@@ -107,26 +112,26 @@ Currently, only `zod` is supported.
107
112
 
108
113
  ```tsx
109
114
  <RhfUtilsZodForm
110
- schema={authLoginFormSchema}
115
+ schema={loginFormSchema}
111
116
  defaultValues={{
112
117
  email: '',
113
118
  }}
114
119
  // submit handler
115
120
  onSubmit={async (
116
121
  data, // schema output
117
- context, // UseRhfUtilsFormOnSubmitContext (form id, form ref, context (rhf), utils options, strictly-typed FormSubmitError class)
122
+ context, // UseRhfUtilsFormOnSubmitContext (id, ref, rhf context, utils options, strictly-typed FormSubmitError class)
118
123
  event, // SubmitEvent
119
124
  ) => {
120
125
  await authLoginService(data);
121
- onSuccess();
126
+ props.onSuccess();
122
127
  }}
123
128
  // handle error declaratively (i.e., no throw/catch)
124
129
  onSubmitError={({
125
130
  error, // unknown
126
- context, // UseRhfUtilsFormOnSubmitErrorContext (form id, form ref, context (rhf), utils options)
131
+ context, // UseRhfUtilsFormOnSubmitErrorContext (id, ref, rhf context, utils options)
127
132
  event, // SubmitEvent
128
133
  }) => {
129
- onError(error);
134
+ props.onError(error);
130
135
  }}
131
136
  // fields
132
137
  Children={({
@@ -152,6 +157,19 @@ Currently, only `zod` is supported.
152
157
  <button type="submit">Login</button>
153
158
  </>
154
159
  )}
160
+ // options/overrides
161
+ rhf={{
162
+ mode: 'onBlur',
163
+ }}
164
+ utils={{
165
+ submitOnChange: true,
166
+ resetValuesOnSubmitError: true,
167
+ enableMyFormNavigationPrompt: true, // custom option prop (see "Extend RhfUtilsFormOptions" section)
168
+ }}
169
+ form={{
170
+ // class names are merged together with global defaults
171
+ className: 'my-special-form-class',
172
+ }}
155
173
  />
156
174
  ```
157
175
 
@@ -175,7 +193,7 @@ Example:
175
193
 
176
194
  ```tsx
177
195
  <RhfUtilsZodForm
178
- onSubmit={({ FormSubmitError }) => {
196
+ onSubmit={async ({ FormSubmitError }) => {
179
197
  if (isProblem())
180
198
  throw new FormSubmitError({
181
199
  root: { message: 'There was a problem with the form.' },
@@ -189,7 +207,7 @@ Example:
189
207
 
190
208
  Any non-`FormSubmitError`s thrown from submit handler (e.g., fetch/axios error) can be transformed by `RhfUtilsClientConfig`'s `onSubmitUnknownError` callback. This takes an `unknown` error and can return a `FormSubmitErrors` object, which is merged in RHF's context errors.
191
209
 
192
- Most common use case will be transforming backend errors to frontend shape. (You can use `getOnSubmitTrpcClientErrorHandler` HOF for TRPC backends.)
210
+ Most common use case will be transforming backend errors to frontend shape. (You can use `getOnSubmitTrpcClientErrorHandler` HOF provided by this library for TRPC backends.)
193
211
 
194
212
  ## `RhfUtilsFormOptions`
195
213
 
@@ -209,10 +227,7 @@ type RhfUtilsFormOptions = {
209
227
  /** Reset form after successful submit. */
210
228
  resetFormAfterSubmitSuccessful?: UseResetFormAfterSubmitSuccessfulOptions;
211
229
 
212
- /**
213
- * Control dev tool options.
214
- * (Lazy-loaded when truthy value supplied.)
215
- */
230
+ /** Control dev tool options. (Lazy-loaded when truthy value supplied.) */
216
231
  devTool?: true | Pick<DevtoolUIProps, 'placement' | 'styles'>;
217
232
  };
218
233
  ```
@@ -232,7 +247,7 @@ declare module '@paragrav/rhf-utils' {
232
247
  export interface Register {
233
248
  RhfUtilsFormOptions: {
234
249
  /** Enable user prompt to confirm navigating away from dirty form. */
235
- prompter?: boolean;
250
+ enableMyFormNavigationPrompt?: boolean;
236
251
  };
237
252
  }
238
253
  }
@@ -242,6 +257,8 @@ declare module '@paragrav/rhf-utils' {
242
257
 
243
258
  You can configure via `RhfUtilsClientConfig` (example at the top) when form context errors are outputted -- i.e., via console and/or thrown error.
244
259
 
260
+ Use `useFlatFieldErrorsContext()` hook, which returns an object with errors grouped by `all`, `fields`, `root`, and `orphans`.
261
+
245
262
  ### Orphans
246
263
 
247
264
  The concept of orphan errors is any error that is not being shown to user. An example would be a stray field in a schema that is prohibiting users from successfully submitting a form.
@@ -17,10 +17,11 @@ const v = (e) => (r) => {
17
17
  var o, i, f, l, n, h;
18
18
  return {
19
19
  ...t,
20
+ // merge global config with instance options...
20
21
  rhf: {
22
+ resolver: e(s),
21
23
  ...(o = r.defaults) == null ? void 0 : o.rhf,
22
- ...t.rhf,
23
- resolver: e(s)
24
+ ...t.rhf
24
25
  },
25
26
  utils: {
26
27
  ...(i = r.defaults) == null ? void 0 : i.utils,
@@ -2,10 +2,10 @@ import s from "react";
2
2
  import { useForm as d } from "react-hook-form";
3
3
  import { FormSubmitError as F } from "../submit/error/FormSubmitError.mjs";
4
4
  const v = ({
5
- onSubmit: e,
6
- onSubmitError: f,
7
- onSubmitInvalid: p,
8
- defaultValues: n,
5
+ defaultValues: e,
6
+ onSubmit: f,
7
+ onSubmitError: p,
8
+ onSubmitInvalid: n,
9
9
  Children: c,
10
10
  rhf: i,
11
11
  form: u,
@@ -13,7 +13,7 @@ const v = ({
13
13
  }) => {
14
14
  const r = s.useId(), m = d({
15
15
  ...i,
16
- defaultValues: n
16
+ defaultValues: e
17
17
  }), o = s.useRef(null);
18
18
  return {
19
19
  id: r,
@@ -27,9 +27,9 @@ const v = ({
27
27
  },
28
28
  formProps: {
29
29
  Children: c,
30
- onSubmit: e,
31
- onSubmitError: f,
32
- onSubmitInvalid: p,
30
+ onSubmit: f,
31
+ onSubmitError: p,
32
+ onSubmitInvalid: n,
33
33
  formId: r,
34
34
  formRef: o,
35
35
  form: u,
@@ -14,7 +14,7 @@ export type ObjectSchema<TInputKey extends string, TOutputKey extends string> =
14
14
  [key in TOutputKey]: SafeFieldValues;
15
15
  };
16
16
  export type CreateRhfUtilsClient<TObjectSchema extends ObjectSchema<TObjectSchemaInputKey, TObjectSchemaOutputKey>, TObjectSchemaInputKey extends string, TObjectSchemaOutputKey extends string> = {
17
- useForm: <TSchema extends TObjectSchema, TSchemaInput extends SafeFieldValues = TSchema[TObjectSchemaInputKey], TSchemaOutput extends SafeFieldValues = TSchema[TObjectSchemaOutputKey], UseRhfUtilsFormPropsForm extends UseRhfUtilsFormProps<TSchemaInput, TSchemaOutput> = UseRhfUtilsFormProps<TSchemaInput, TSchemaOutput>>(schema: TSchema, form: Omit<UseRhfUtilsFormPropsForm, 'config'>) => UseRhfUtilsFormReturn<TSchemaInput, TSchemaOutput> & {
17
+ useForm: <TSchema extends TObjectSchema, TSchemaInput extends SafeFieldValues = TSchema[TObjectSchemaInputKey], TSchemaOutput extends SafeFieldValues = TSchema[TObjectSchemaOutputKey], UseRhfUtilsFormPropsForm extends UseRhfUtilsFormProps<TSchemaInput, TSchemaOutput> = UseRhfUtilsFormProps<TSchemaInput, TSchemaOutput>>(schema: TSchema, form: UseRhfUtilsFormPropsForm) => UseRhfUtilsFormReturn<TSchemaInput, TSchemaOutput> & {
18
18
  FormWithProviders: React.FC<React.PropsWithChildren>;
19
19
  };
20
20
  FormWithProviders: <TSchema extends TObjectSchema, TSchemaInput extends SafeFieldValues = TSchema[TObjectSchemaInputKey], TSchemaOutput extends SafeFieldValues = TSchema[TObjectSchemaOutputKey]>(props: {
@@ -4,6 +4,6 @@ import { ZodTypeFieldValues } from '../ZodTypeFieldValues';
4
4
 
5
5
  type Props<TSchema extends ZodTypeFieldValues> = {
6
6
  schema: TSchema;
7
- } & Omit<UseRhfUtilsFormProps<TSchema[typeof zodTypeInput], TSchema[typeof zodTypeOutput]>, 'config'>;
7
+ } & UseRhfUtilsFormProps<TSchema[typeof zodTypeInput], TSchema[typeof zodTypeOutput]>;
8
8
  declare function RhfUtilsZodForm<TSchema extends ZodTypeFieldValues>({ schema, ...props }: Props<TSchema>): import("react/jsx-runtime").JSX.Element;
9
9
  export default RhfUtilsZodForm;
@@ -2,7 +2,7 @@ import { UseRhfUtilsFormProps } from '../../../form/UseRhfUtilsFormProps';
2
2
  import { zodTypeInput, zodTypeOutput } from '../consts';
3
3
  import { ZodTypeFieldValues } from '../ZodTypeFieldValues';
4
4
 
5
- declare const useRhfUtilsZodForm: <TSchema extends ZodTypeFieldValues>(schema: TSchema, form: Omit<UseRhfUtilsFormProps<TSchema[typeof zodTypeInput], TSchema[typeof zodTypeOutput]>, 'config'>) => import('../../../form/UseRhfUtilsFormReturn').UseRhfUtilsFormReturn<TSchema["_input"], TSchema["_output"]> & {
5
+ declare const useRhfUtilsZodForm: <TSchema extends ZodTypeFieldValues>(schema: TSchema, form: UseRhfUtilsFormProps<TSchema[typeof zodTypeInput], TSchema[typeof zodTypeOutput]>) => import('../../../form/UseRhfUtilsFormReturn').UseRhfUtilsFormReturn<TSchema["_input"], TSchema["_output"]> & {
6
6
  FormWithProviders: import('react').FC<{
7
7
  children?: import('react').ReactNode;
8
8
  }>;
@@ -6,12 +6,12 @@ import { UseRhfUtilsFormChildrenProps } from './UseRhfUtilsFormChildrenProps';
6
6
  import { UseRhfUtilsFormOnSubmitContext, UseRhfUtilsFormOnSubmitErrorContext } from './UseRhfUtilsFormOnSubmitContext';
7
7
 
8
8
  export type UseRhfUtilsFormProps<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues> = {
9
+ defaultValues?: UseFormProps<TFieldValues>['defaultValues'];
9
10
  onSubmit?: (values: TTransformedValues, context: UseRhfUtilsFormOnSubmitContext<TFieldValues, TTransformedValues>, event: React.BaseSyntheticEvent<SubmitEvent>) => unknown | Promise<unknown>;
10
11
  /** Submit error handler. (Only for errors not of instance `FormError`, which are handled internally.) */
11
12
  onSubmitError?: (error: unknown, context: UseRhfUtilsFormOnSubmitErrorContext<TFieldValues, TTransformedValues>, event: React.BaseSyntheticEvent<SubmitEvent>) => void;
12
13
  /** Submit handler when form is invalid. */
13
14
  onSubmitInvalid?: SubmitErrorHandler<TFieldValues>;
14
- defaultValues?: UseFormProps<TFieldValues>['defaultValues'];
15
15
  Children: React.FC<UseRhfUtilsFormChildrenProps<TFieldValues, TTransformedValues>>;
16
16
  /** {@link RhfUseFormProps} props for RHF's {@link useForm}. */
17
17
  rhf?: Omit<UseFormProps<TFieldValues>, 'defaultValues'>;
@@ -11,6 +11,6 @@ import { UseRhfUtilsFormReturn } from './UseRhfUtilsFormReturn';
11
11
  * see https://caniuse.com/?search=form%20attribute
12
12
  * @returns Form provider and form.
13
13
  */
14
- declare const useRhfUtilsForm: <TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>({ onSubmit, onSubmitError, onSubmitInvalid, defaultValues, Children, rhf, form, utils, }: UseRhfUtilsFormProps<TFieldValues, TTransformedValues>) => UseRhfUtilsFormReturn<TFieldValues, TTransformedValues>;
14
+ declare const useRhfUtilsForm: <TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>({ defaultValues, onSubmit, onSubmitError, onSubmitInvalid, Children, rhf, form, utils, }: UseRhfUtilsFormProps<TFieldValues, TTransformedValues>) => UseRhfUtilsFormReturn<TFieldValues, TTransformedValues>;
15
15
  export default useRhfUtilsForm;
16
16
  export type UseRhfUtilsForm<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues> = typeof useRhfUtilsForm<TFieldValues, TTransformedValues>;
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.119",
5
+ "version": "0.0.120",
6
6
  "description": "Integration utilities for react-hook-form.",
7
7
  "type": "module",
8
8
  "sideEffects": false,