@paragrav/rhf-utils 0.60.0 → 0.62.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 +57 -96
- package/dist/dts/_exports/relay.d.ts +7 -8
- package/dist/dts/_exports/types.d.ts +1 -0
- package/dist/dts/client/config/RhfUtilsClientConfigType.d.ts +8 -4
- package/dist/dts/errors/flat/getFlatFieldErrors.d.ts +5 -1
- package/dist/dts/form/RhfUtilsFormComponentPropsType.d.ts +2 -6
- package/dist/dts/form/UseRhfUtilsFormChildrenPropsType.d.ts +2 -2
- package/dist/dts/form/context/utils/LastSubmitStateType.d.ts +1 -0
- package/dist/dts/form/context/utils/{RhfUtilsContextPropsType.d.ts → RhfUtilsContextType.d.ts} +3 -2
- package/dist/dts/form/context/utils/useRhfUtilsContext.d.ts +4 -4
- package/dist/dts/form/defaults/form/useRhfUtilsFormResolvedFormProps.d.ts +10 -10
- package/dist/dts/form/providers/RhfUtilsFormProviders.d.ts +1 -1
- package/dist/dts/form/providers/RhfUtilsFormProvidersPropsType.d.ts +2 -0
- package/dist/dts/form/relay/FormRelayOptions.d.ts +16 -0
- package/dist/dts/form/{state/relay/FormStateRelayContextProvider.d.ts → relay/context/FormRelayContextProvider.d.ts} +1 -1
- package/dist/dts/form/relay/context/useFormRelayContext.d.ts +12 -0
- package/dist/dts/form/relay/context/utils.d.ts +4 -0
- package/dist/dts/form/relay/get/FormRelayGroupType.d.ts +16 -0
- package/dist/dts/form/relay/get/grouper/context/hooks.d.ts +8 -0
- package/dist/dts/form/relay/get/grouper/context/index.d.ts +5 -0
- package/dist/dts/form/relay/get/grouper/context/provider.d.ts +9 -0
- package/dist/dts/form/relay/get/grouper/useFirstFormStateGroup.d.ts +9 -0
- package/dist/dts/form/relay/get/useFormRelay.d.ts +13 -0
- package/dist/dts/form/relay/set/FormRelaySetter.d.ts +6 -0
- package/dist/dts/form/relay/set/useFormRelaySet.d.ts +2 -0
- package/dist/dts/form/relay/types.d.ts +12 -0
- package/dist/dts/form/with-handlers-and-children/RhfUtilsFormProps.d.ts +5 -1
- package/dist/dts/form/with-handlers-and-children/_useHandleSubmit.d.ts +1 -1
- package/dist/dts/form/with-providers/RhfUtilsFormWithProviders.d.ts +1 -1
- package/dist/dts/submit/UseRhfUtilsFormOnSubmitContextType.d.ts +3 -3
- package/dist/dts/submit/last-error/useLastSubmitErrorContextWith.d.ts +1 -1
- package/dist/esm/FormRelaySetter.mjs +140 -0
- package/dist/esm/index.mjs +203 -202
- package/dist/esm/relay.mjs +71 -209
- package/package.json +17 -17
- package/dist/dts/form/RhfUtilsFormStateWithUtilsType.d.ts +0 -7
- package/dist/dts/form/state/relay/FormStateRelayedAggregatedType.d.ts +0 -10
- package/dist/dts/form/state/relay/FormStateRelayedItemType.d.ts +0 -11
- package/dist/dts/form/state/relay/FormStateRelayedOptionsType.d.ts +0 -20
- package/dist/dts/form/state/relay/FormStateRelayedType.d.ts +0 -3
- package/dist/dts/form/state/relay/pull/hooks.d.ts +0 -31
- package/dist/dts/form/state/relay/push/FormStateRelayPusher.d.ts +0 -4
- package/dist/dts/form/state/relay/push/useFormStateRelayPusher.d.ts +0 -3
- package/dist/dts/form/state/relay/useFormStateRelayContext.d.ts +0 -20
- package/dist/dts/form/state/relay/utils.d.ts +0 -4
- package/dist/esm/getFlatFieldErrors.mjs +0 -55
package/README.md
CHANGED
|
@@ -9,11 +9,11 @@ Integration and utility library for [react-hook-form](https://www.react-hook-for
|
|
|
9
9
|
- TypeScript-first
|
|
10
10
|
- global configuration (🔗 [`RhfUtilsClientConfig`](#config) section)
|
|
11
11
|
- RHF (`UseFormProps`) and utilities (`RhfUtilsFormOptions`) options defaults
|
|
12
|
-
- inject your own hooks and UI (`
|
|
12
|
+
- inject your own hooks and UI (`FormChildren`)
|
|
13
13
|
- server error transformation (`onSubmitErrorUnknown`) ✨
|
|
14
14
|
- handle cancel prompt (`useCanFormBeCancelled`) ✨
|
|
15
15
|
- RHF `FormState.errors` logging/throwing (`RhfUtilsClientConfig.fieldErrors`) ✨
|
|
16
|
-
- form-level configuration (🔗 [`RhfUtilsZodForm`](#form) section)
|
|
16
|
+
- form-level configuration (🔗 [`RhfUtilsZodForm`](#form-with-providers) section)
|
|
17
17
|
- RHF and utilities options overrides
|
|
18
18
|
- extendable utilities options type (`RhfUtilsFormOptions`)
|
|
19
19
|
- throw error (`FormSubmitError`) in submit handler to add errors to RHF context and fail submit
|
|
@@ -21,7 +21,7 @@ Integration and utility library for [react-hook-form](https://www.react-hook-for
|
|
|
21
21
|
- context injection for children (`RhfUtilsZodForm.Children`), including:
|
|
22
22
|
- formId, formRef, RHF context, utilities options
|
|
23
23
|
- schema-typed Controller component and FormSubmitError class
|
|
24
|
-
- form state relay (🔗 [`
|
|
24
|
+
- form state relay (🔗 [`FormRelayContextProvider`](#form-state-relay) section) ✨
|
|
25
25
|
- access specific form's state from outside that form/provider
|
|
26
26
|
- assign forms into groups and watch collectively
|
|
27
27
|
- simpler/flatter `FieldErrors` structure (🔗 [`FlatFieldErrors`](#flatfielderrors) section)
|
|
@@ -44,7 +44,7 @@ yarn add @paragrav/rhf-utils # yarn
|
|
|
44
44
|
- 🔗 [Config](#config) (`RhfUtilsClientConfig`): define your global config (optional)
|
|
45
45
|
- 🔗 [Provider](#config-provider) (`RhfUtilsClientConfigProvider`): add to your global stack
|
|
46
46
|
- 🔗 [Form With Providers](#form-with-providers) (`RhfUtilsZodFormWithProviders`): use as form component
|
|
47
|
-
- 🔗 [Form State Relay](#form-state-relay) (`
|
|
47
|
+
- 🔗 [Form State Relay](#form-state-relay) (`FormRelayContextProvider`): relay form state
|
|
48
48
|
|
|
49
49
|
## Config
|
|
50
50
|
|
|
@@ -72,14 +72,15 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
|
|
|
72
72
|
},
|
|
73
73
|
|
|
74
74
|
// optional form component to use (defaults to primitive HTML form)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
FormComponent: Form.Root,
|
|
76
|
+
|
|
77
|
+
// inject your own hooks and components
|
|
78
|
+
// into all RhfUtilsZodForm instances
|
|
79
|
+
FormChildren: (
|
|
78
80
|
// RhfUtilsFormComponentProps
|
|
79
81
|
{
|
|
80
|
-
formProps, // computed form props
|
|
81
82
|
formId, // unique id string
|
|
82
|
-
formRef, // ref
|
|
83
|
+
formRef, // form element ref
|
|
83
84
|
context, // rhf UseFormReturn (without proxy `formState`)
|
|
84
85
|
options, // RhfUtilsFormOptions (with any custom props)
|
|
85
86
|
Controller, // rhf controller (SafeFieldValues-typed; no schema at this level)
|
|
@@ -96,13 +97,13 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
|
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
return (
|
|
99
|
-
|
|
100
|
+
<>
|
|
100
101
|
{/* RhfUtilsZodForm.Children "outlet" (see "Component Hierarchy" section) */}
|
|
101
102
|
{children}
|
|
102
103
|
|
|
103
104
|
{/* root errors list */}
|
|
104
105
|
<RootErrorsList />
|
|
105
|
-
|
|
106
|
+
</>
|
|
106
107
|
);
|
|
107
108
|
},
|
|
108
109
|
|
|
@@ -179,17 +180,18 @@ Currently, only `zod` schemas are supported.
|
|
|
179
180
|
// cancel handler (passed to `Children` below)
|
|
180
181
|
// execution routed through `RhfUtilsClientConfig.useCanFormBeCancelled`, if provided
|
|
181
182
|
onCancel={handleCancel}
|
|
182
|
-
//
|
|
183
|
+
// SUBMIT HANDLERS
|
|
184
|
+
// invariants
|
|
183
185
|
onBeforeSubmitInvariants={async (
|
|
184
186
|
{ input, output, api }, // schema input (form values), output; api data (via getApiData)
|
|
185
187
|
context, // UseRhfUtilsFormOnSubmitContext (id, ref, rhf context (without proxy formState), utils options, schema-typed FormSubmitError class)
|
|
186
188
|
event, // SubmitEvent
|
|
187
189
|
) => [
|
|
188
|
-
|
|
189
|
-
'passwordConfirm', // type safe
|
|
190
|
-
'Passwords must match.',
|
|
191
|
-
data.password === data.passwordConfirm,
|
|
192
|
-
|
|
190
|
+
{
|
|
191
|
+
field: 'passwordConfirm', // type safe
|
|
192
|
+
message: 'Passwords must match.',
|
|
193
|
+
valid: data.password === data.passwordConfirm,
|
|
194
|
+
},
|
|
193
195
|
]}
|
|
194
196
|
onBeforeSubmit={({ input, output, api }, context, event) => {
|
|
195
197
|
if (!isValid(input.email))
|
|
@@ -326,7 +328,7 @@ Sometimes you need to control the nesting of the Form element. For example, to a
|
|
|
326
328
|
</aside>
|
|
327
329
|
```
|
|
328
330
|
|
|
329
|
-
|
|
331
|
+
To access forms' state outside its respective context, including in aggregate across more than one form, see [Form State Relay](#form-state-relay) section.
|
|
330
332
|
|
|
331
333
|
## `FormSubmitError`
|
|
332
334
|
|
|
@@ -382,7 +384,9 @@ type RhfUtilsFormOptions = {
|
|
|
382
384
|
};
|
|
383
385
|
```
|
|
384
386
|
|
|
385
|
-
If you need access to options deeper in your component structure, use `useRhfUtilsContext` to receive `RhfUtilsContext` object, which includes `formId`, `formRef`, and `
|
|
387
|
+
If you need access to options deeper in your component structure, use `useRhfUtilsContext` to receive `RhfUtilsContext` object, which includes `formId`, `formRef`, `options`, and `lastSubmitStateRef`.
|
|
388
|
+
|
|
389
|
+
`lastSubmitStateRef` (a ref with possible value of `null | 'submitting' | 'success' | 'error'`) conveys current submit state via ref -- i.e., without needing to wait for next render cycle. If your form navigates away via `onSubmitSuccess`, RHF's `useFormContext` still shows form as `isDirty` and `isSubmitting`, which makes it difficult to distinguish from a user-initiated navigation before form is submitted successfully.
|
|
386
390
|
|
|
387
391
|
Use `useRhfUtilsContextRequestSubmit` hook to get `requestSubmit` function for current form ref in context. This is useful when you need to trigger form submission programatically.
|
|
388
392
|
|
|
@@ -396,7 +400,7 @@ import '@paragrav/rhf-utils';
|
|
|
396
400
|
declare module '@paragrav/rhf-utils' {
|
|
397
401
|
export interface Register {
|
|
398
402
|
RhfUtilsFormOptions: {
|
|
399
|
-
/** Custom props for your custom options/hooks/behaviors. */
|
|
403
|
+
/** Custom props for your custom options/hooks/behaviors per form instance. */
|
|
400
404
|
enableMyPrompter?: boolean;
|
|
401
405
|
enableMyOptionalFormHook?: boolean;
|
|
402
406
|
configMyOptionalFormHook?: MyCustomFormHookConfig;
|
|
@@ -405,99 +409,56 @@ declare module '@paragrav/rhf-utils' {
|
|
|
405
409
|
}
|
|
406
410
|
```
|
|
407
411
|
|
|
408
|
-
## <a id="form-state-relay"
|
|
412
|
+
## <a id="form-state-relay"></a> Form State Relay
|
|
409
413
|
|
|
410
|
-
Sometimes you need to access one or more forms' state outside
|
|
414
|
+
Sometimes you need to access one or more forms' state outside its respective context.
|
|
411
415
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
Use case: display a form's errors (or any other state) outside form and its context.
|
|
415
|
-
|
|
416
|
-
```tsx
|
|
417
|
-
<FormStateRelayContextProvider> // relay provider
|
|
418
|
-
<ReactHookForm.FormProvider> // rhf provider
|
|
419
|
-
<FormStateRelayPusher /> // push form state
|
|
420
|
-
<ReactHookForm.FormProvider>
|
|
421
|
-
|
|
422
|
-
<WatchOutsideFormContext /> // watch form state
|
|
423
|
-
</FormStateRelayContextProvider>;
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
Push can be configured via `FormStateRelayPusher` component or `useFormStateRelayPush` hook with `FormStateRelayPushOptions` options.
|
|
416
|
+
`FormRelayContextProvider` is included by default, but form's state is only relayed with opted-in. Configuration is done per form instance via `relay` prop.
|
|
427
417
|
|
|
428
418
|
```ts
|
|
429
|
-
type
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
```tsx
|
|
438
|
-
function WatchOutsideFormContext() {
|
|
439
|
-
// FormStateWithUtils (either via RHF -- when requested within form context -- or relay when not)
|
|
440
|
-
const formState = useFormStateWithUtilsViaRhfOrRelay();
|
|
441
|
-
}
|
|
419
|
+
type FormRelayOptions = {
|
|
420
|
+
/**
|
|
421
|
+
* Determines what part of RHF's form state is relayed.
|
|
422
|
+
* Also acts to activate RHF proxy values.
|
|
423
|
+
*/
|
|
424
|
+
select: (formState: FormState<SafeFieldValues>) => FormRelayStateSelected;
|
|
442
425
|
|
|
443
|
-
|
|
444
|
-
|
|
426
|
+
/**
|
|
427
|
+
* Arbitrary group name(s) for this form.
|
|
428
|
+
* Think of it like class or category names.
|
|
429
|
+
* (e.g., "parent" or "children")
|
|
430
|
+
*/
|
|
431
|
+
groups?: string[];
|
|
432
|
+
};
|
|
445
433
|
```
|
|
446
434
|
|
|
447
|
-
|
|
435
|
+
There are two main ways to get form state that has been relayed.
|
|
448
436
|
|
|
449
|
-
###
|
|
437
|
+
### Get form relay by id
|
|
450
438
|
|
|
451
|
-
|
|
439
|
+
You can retrieve a singular form's relay state via `useFormRelayId(formId)`. This will return a `FormRelay` object with that form's selected state (`FormRelayStateSelected`), options (`FormRelayOptions`), and utils (`RhfUtilsContext`).
|
|
452
440
|
|
|
453
|
-
|
|
454
|
-
- disable ALL children when parent is "flagged" (i.e., submitting)
|
|
455
|
-
- confirm navigation when ANY mounted form is "flagged" (i.e., dirty)
|
|
441
|
+
### Get form relay by group
|
|
456
442
|
|
|
457
|
-
|
|
458
|
-
function ParentForm() {
|
|
459
|
-
const childrenFormState = useFormStateRelayWatchGroup('children'); // FormStateRelayedAggregated
|
|
460
|
-
|
|
461
|
-
return (
|
|
462
|
-
<ReactHookForm.FormProvider>
|
|
463
|
-
<FormStateRelayPusher formId="parent" /> // pusher
|
|
464
|
-
<input type="submit" disabled={childrenFormState.isDirty} />
|
|
465
|
-
</ReactHookForm.FormProvider>
|
|
466
|
-
);
|
|
467
|
-
}
|
|
443
|
+
When retrieving by group, state is merged into a `FormRelayGroup` object (and no options or utils are provided, as these are form-specific).
|
|
468
444
|
|
|
469
|
-
|
|
470
|
-
const parentFormState = useFormStateRelayWatchId('parent'); // FormStateRelayed
|
|
445
|
+
Use `useFormRelayGroup(callback)` and providing a callback that is is supplied with options (`FormRelayOptions`) and utils (`RhfUtilsContext`) of each form registered to relay, in order for you to determine whether it should be included in this arbitrary "group".
|
|
471
446
|
|
|
472
|
-
|
|
473
|
-
<ReactHookForm.FormProvider>
|
|
474
|
-
<FormStateRelayPusher group="children" /> // pusher
|
|
475
|
-
<input type="submit" disabled={parentFormState.isSubmitting} />
|
|
476
|
-
</ReactHookForm.FormProvider>
|
|
477
|
-
);
|
|
478
|
-
}
|
|
447
|
+
You can also use `FormRelayGrouperContextProvider` if you want to make this group accessible via naive hook.
|
|
479
448
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
isMountedFlagged: boolean; // via RelayedFormOptions['flaggedState']['isMounted']
|
|
489
|
-
};
|
|
449
|
+
```tsx
|
|
450
|
+
<FormRelayGrouperContextProvider
|
|
451
|
+
predicate={({ options, utils }) =>
|
|
452
|
+
!!options?.groups?.includes("parent") // find specific group
|
|
453
|
+
}
|
|
454
|
+
>
|
|
455
|
+
{(state: FormRelayGroup) => ()}
|
|
456
|
+
</FormRelayGrouperContextProvider>
|
|
490
457
|
```
|
|
491
458
|
|
|
492
|
-
|
|
459
|
+
Alternatively, instead render callback, you can use `useFormRelayGrouper`.
|
|
493
460
|
|
|
494
|
-
|
|
495
|
-
<FormStateRelayContextProvider>
|
|
496
|
-
<ParentForm />
|
|
497
|
-
<ChildForm />
|
|
498
|
-
<Child2Form />
|
|
499
|
-
</FormStateRelayContextProvider>
|
|
500
|
-
```
|
|
461
|
+
If you want to build some components to be independent of any one specific context -- i.e., RHF's context, `FormRelayGrouperContext`, or `FormRelayContext` -- you can use `useFirstFormStateGroup` to get `FormRelayGroup` from nearest available context. (If RHF's context is found, its singular state is transformed to `FormRelayGroup`.)
|
|
501
462
|
|
|
502
463
|
## Field Errors
|
|
503
464
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export { useFormStateRelayPusher } from '../form/state/relay/push/useFormStateRelayPusher';
|
|
1
|
+
export { FormRelayContextProvider } from '../form/relay/context/FormRelayContextProvider';
|
|
2
|
+
export type { FormRelayGroup } from '../form/relay/get/FormRelayGroupType';
|
|
3
|
+
export { useFirstFormStateGroup } from '../form/relay/get/grouper/useFirstFormStateGroup';
|
|
4
|
+
export { useFormRelayGroup, useFormRelayId, } from '../form/relay/get/useFormRelay';
|
|
5
|
+
export { FormRelaySetter } from '../form/relay/set/FormRelaySetter';
|
|
6
|
+
export { useFormRelaySet } from '../form/relay/set/useFormRelaySet';
|
|
7
|
+
export type { FormRelay, FormRelayStateSelected } from '../form/relay/types';
|
|
@@ -15,15 +15,19 @@ export type RhfUtilsClientConfig = {
|
|
|
15
15
|
*/
|
|
16
16
|
defaults?: UseRhfUtilsFormGlobalDefaults;
|
|
17
17
|
/**
|
|
18
|
-
* Supply your own `<form>` component.
|
|
18
|
+
* Supply your own `<form>` component.
|
|
19
19
|
*
|
|
20
|
-
* @
|
|
20
|
+
* (By default, a native {@link HTMLFormElement} is used.)
|
|
21
|
+
*/
|
|
22
|
+
FormComponent?: React.FC<React.PropsWithChildren<React.HTMLAttributes<HTMLFormElement>>>;
|
|
23
|
+
/**
|
|
24
|
+
* Inject your own hooks, components, etc., into every form instance.
|
|
21
25
|
*
|
|
22
|
-
*
|
|
26
|
+
* @description
|
|
23
27
|
*
|
|
24
28
|
* (NOTE: context params are not schema-typed as not possible at this level.)
|
|
25
29
|
*/
|
|
26
|
-
|
|
30
|
+
FormChildren?: React.FC<React.PropsWithChildren<RhfUtilsFormComponentProps>>;
|
|
27
31
|
/**
|
|
28
32
|
* A hook that returns a callback that determines whether form can be cancelled at event-time.
|
|
29
33
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FieldError, FieldErrors } from 'react-hook-form';
|
|
2
|
+
import { SafeFieldValues } from '../../form/rhf/SafeFieldValuesType';
|
|
2
3
|
import { FlatFieldErrors } from './types';
|
|
3
4
|
/**
|
|
4
5
|
* Get {@link FlatFieldErrors} from {@link FieldErrors}.
|
|
@@ -28,4 +29,7 @@ export declare const getFlatFieldErrors: (errors: FieldErrors) => FlatFieldError
|
|
|
28
29
|
* iow: dot [?: non-capturing]("type" | "message")[\b word boundary][$ end of string]
|
|
29
30
|
*/
|
|
30
31
|
export declare const regexMaybeFieldErrorLeafNodeSuffix: RegExp;
|
|
31
|
-
export
|
|
32
|
+
export type FieldErrorsSansRef<TFieldValues extends SafeFieldValues = SafeFieldValues> = Record<keyof TFieldValues | 'root', Partial<Pick<FieldError, 'message' | 'type'>> & {
|
|
33
|
+
hasRef: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
export declare const getFlatFieldErrorsSansRef: <TFieldValues extends SafeFieldValues>(errors: FieldErrors<TFieldValues>) => FieldErrorsSansRef<TFieldValues>;
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { UseFormReturn } from 'react-hook-form';
|
|
2
2
|
import { FormSubmitError } from '../submit/error/FormSubmitError';
|
|
3
3
|
import { _Controller } from './_Controller';
|
|
4
|
-
import {
|
|
5
|
-
import { UseRhfUtilsFormInstanceFormProps } from './defaults/form/UseRhfUtilsFormInstanceFormProps';
|
|
4
|
+
import { RhfUtilsContext } from './context/utils/RhfUtilsContextType';
|
|
6
5
|
import { SafeFieldValues } from './rhf/SafeFieldValuesType';
|
|
7
6
|
/**
|
|
8
7
|
* RhfUtilsClientConfig's FormComponent props.
|
|
9
8
|
*/
|
|
10
|
-
export type RhfUtilsFormComponentProps<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues> =
|
|
9
|
+
export type RhfUtilsFormComponentProps<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues> = RhfUtilsContext & {
|
|
11
10
|
rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
|
|
12
|
-
formProps: UseRhfUtilsFormInstanceFormProps & {
|
|
13
|
-
onSubmit: NonNullable<React.PropsWithoutRef<React.JSX.IntrinsicElements['form']>['onSubmit']>;
|
|
14
|
-
};
|
|
15
11
|
Controller: typeof _Controller<TFieldValues>;
|
|
16
12
|
FormSubmitError: typeof FormSubmitError<TFieldValues>;
|
|
17
13
|
};
|
|
@@ -2,7 +2,7 @@ import { UseFormReturn } from 'react-hook-form';
|
|
|
2
2
|
import { FormSubmitError } from '../submit/error/FormSubmitError';
|
|
3
3
|
import { MaybePromise } from '../utils/types';
|
|
4
4
|
import { _Controller } from './_Controller';
|
|
5
|
-
import {
|
|
5
|
+
import { RhfUtilsContext } from './context/utils/RhfUtilsContextType';
|
|
6
6
|
import { RhfUtilsFormOptions } from './options/RhfUtilsFormOptionsType';
|
|
7
7
|
import { SafeFieldValues } from './rhf/SafeFieldValuesType';
|
|
8
8
|
/**
|
|
@@ -10,7 +10,7 @@ import { SafeFieldValues } from './rhf/SafeFieldValuesType';
|
|
|
10
10
|
*
|
|
11
11
|
* (Consider keeping shape in line with `UseRhfUtilsFormOnSubmitProps` and `UseRhfUtilsFormReturn`.)
|
|
12
12
|
*/
|
|
13
|
-
export type UseRhfUtilsFormChildrenProps<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues, TProps = undefined> =
|
|
13
|
+
export type UseRhfUtilsFormChildrenProps<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues, TProps = undefined> = RhfUtilsContext & {
|
|
14
14
|
rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
|
|
15
15
|
options: RhfUtilsFormOptions;
|
|
16
16
|
Controller: typeof _Controller<TFieldValues>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type LastSubmitState = null | 'submitting' | 'success' | 'error';
|
package/dist/dts/form/context/utils/{RhfUtilsContextPropsType.d.ts → RhfUtilsContextType.d.ts}
RENAMED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
|
+
import { LastSubmitState } from './LastSubmitStateType';
|
|
2
3
|
import { RhfUtilsContextProviderProps } from './RhfUtilsContextProvider';
|
|
3
|
-
export type
|
|
4
|
+
export type RhfUtilsContext = RhfUtilsContextProviderProps & {
|
|
4
5
|
/**
|
|
5
6
|
* Current form submit state.
|
|
6
7
|
*
|
|
7
8
|
* e.g., can be used to determine whether safe to redirect (navigate) without prompter.
|
|
8
9
|
* Unlike RHF's `isSubmitSuccessful`, is computed/set immediately after `onSubmit` succeeds/fails.
|
|
9
10
|
*/
|
|
10
|
-
lastSubmitStateRef: RefObject<
|
|
11
|
+
lastSubmitStateRef: RefObject<LastSubmitState>;
|
|
11
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare const _RhfUtilsContextProvider: import('react').Provider<
|
|
3
|
-
lastSubmitStateRef: import('react').RefObject<
|
|
4
|
-
}, useRhfUtilsMaybeContext: () =>
|
|
1
|
+
import { RhfUtilsContext } from './RhfUtilsContextType';
|
|
2
|
+
declare const _RhfUtilsContextProvider: import('react').Provider<RhfUtilsContext | undefined>, useRhfUtilsContext: () => import('./RhfUtilsContextProvider').RhfUtilsContextProviderProps & {
|
|
3
|
+
lastSubmitStateRef: import('react').RefObject<import('./LastSubmitStateType').LastSubmitState>;
|
|
4
|
+
}, useRhfUtilsMaybeContext: () => RhfUtilsContext | undefined;
|
|
5
5
|
export { _RhfUtilsContextProvider, useRhfUtilsContext, useRhfUtilsMaybeContext, };
|
|
@@ -30,7 +30,7 @@ export declare const useRhfUtilsFormResolvedFormProps: (formProps: UseRhfUtilsFo
|
|
|
30
30
|
inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined | undefined;
|
|
31
31
|
nonce?: string | undefined | undefined;
|
|
32
32
|
tabIndex?: number | undefined | undefined;
|
|
33
|
-
onChange?: import('react').
|
|
33
|
+
onChange?: import('react').ChangeEventHandler<HTMLFormElement, Element> | undefined;
|
|
34
34
|
onBlur?: import('react').FocusEventHandler<HTMLFormElement> | undefined;
|
|
35
35
|
key?: import('react').Key | null | undefined;
|
|
36
36
|
autoComplete?: string | undefined | undefined;
|
|
@@ -139,16 +139,16 @@ export declare const useRhfUtilsFormResolvedFormProps: (formProps: UseRhfUtilsFo
|
|
|
139
139
|
onFocus?: import('react').FocusEventHandler<HTMLFormElement> | undefined;
|
|
140
140
|
onFocusCapture?: import('react').FocusEventHandler<HTMLFormElement> | undefined;
|
|
141
141
|
onBlurCapture?: import('react').FocusEventHandler<HTMLFormElement> | undefined;
|
|
142
|
-
onChangeCapture?: import('react').
|
|
142
|
+
onChangeCapture?: import('react').ChangeEventHandler<HTMLFormElement, Element> | undefined;
|
|
143
143
|
onBeforeInput?: import('react').InputEventHandler<HTMLFormElement> | undefined;
|
|
144
|
-
onBeforeInputCapture?: import('react').
|
|
145
|
-
onInput?: import('react').
|
|
146
|
-
onInputCapture?: import('react').
|
|
147
|
-
onReset?: import('react').
|
|
148
|
-
onResetCapture?: import('react').
|
|
149
|
-
onSubmitCapture?: import('react').
|
|
150
|
-
onInvalid?: import('react').
|
|
151
|
-
onInvalidCapture?: import('react').
|
|
144
|
+
onBeforeInputCapture?: import('react').InputEventHandler<HTMLFormElement> | undefined;
|
|
145
|
+
onInput?: import('react').InputEventHandler<HTMLFormElement> | undefined;
|
|
146
|
+
onInputCapture?: import('react').InputEventHandler<HTMLFormElement> | undefined;
|
|
147
|
+
onReset?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
148
|
+
onResetCapture?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
149
|
+
onSubmitCapture?: import('react').SubmitEventHandler<HTMLFormElement> | undefined;
|
|
150
|
+
onInvalid?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
151
|
+
onInvalidCapture?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
152
152
|
onLoad?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
153
153
|
onLoadCapture?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
154
154
|
onError?: import('react').ReactEventHandler<HTMLFormElement> | undefined;
|
|
@@ -2,5 +2,5 @@ import { default as React } from 'react';
|
|
|
2
2
|
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
3
3
|
import { RhfUtilsFormProvidersProps } from './RhfUtilsFormProvidersPropsType';
|
|
4
4
|
type Props<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues> = React.PropsWithChildren<RhfUtilsFormProvidersProps<TFieldValues, TTransformedValues>>;
|
|
5
|
-
export declare function RhfUtilsFormProviders<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>({ formId, rhf, resolver, defaultValues, options, children, }: Props<TFieldValues, TTransformedValues>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare function RhfUtilsFormProviders<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>({ formId, rhf, resolver, defaultValues, options, relay, children, }: Props<TFieldValues, TTransformedValues>): import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Resolver, UseFormProps } from 'react-hook-form';
|
|
2
2
|
import { RhfUtilsFormOptions } from '../options/RhfUtilsFormOptionsType';
|
|
3
|
+
import { FormRelayOptions } from '../relay/FormRelayOptions';
|
|
3
4
|
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
4
5
|
import { RhfUseFormInstanceProps } from '../rhf/UseFormPropsType';
|
|
5
6
|
/**
|
|
@@ -12,4 +13,5 @@ export type RhfUtilsFormProvidersProps<TFieldValues extends SafeFieldValues, TTr
|
|
|
12
13
|
rhf?: RhfUseFormInstanceProps<TFieldValues, TTransformedValues>;
|
|
13
14
|
defaultValues?: UseFormProps<TFieldValues, unknown, TTransformedValues>['defaultValues'];
|
|
14
15
|
options?: RhfUtilsFormOptions;
|
|
16
|
+
relay?: FormRelayOptions;
|
|
15
17
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FormState } from 'react-hook-form';
|
|
2
|
+
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
3
|
+
import { FormRelayStateSelected } from './types';
|
|
4
|
+
export type FormRelayOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Determines what part of RHF's form state is relayed.
|
|
7
|
+
* Also acts to activate RHF proxy values.
|
|
8
|
+
*/
|
|
9
|
+
select: (formState: FormState<SafeFieldValues>) => FormRelayStateSelected;
|
|
10
|
+
/**
|
|
11
|
+
* Arbitrary group name(s) for this form.
|
|
12
|
+
* Think of it like class or category names.
|
|
13
|
+
* (e.g., "parent" or "children")
|
|
14
|
+
*/
|
|
15
|
+
groups?: string[];
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RhfUtilsContext } from '../../context/utils/RhfUtilsContextType';
|
|
2
|
+
import { FormRelayOptions } from '../FormRelayOptions';
|
|
3
|
+
import { FormRelay, FormRelayStateSelected } from '../types';
|
|
4
|
+
export type FormsRelayed = Record<string, // form id
|
|
5
|
+
FormRelay>;
|
|
6
|
+
export type FormRelayContext = {
|
|
7
|
+
add: (state: FormRelayStateSelected, utils: RhfUtilsContext, options: FormRelayOptions) => void;
|
|
8
|
+
update: (id: string, state: FormRelayStateSelected) => void;
|
|
9
|
+
remove: (id: string) => void;
|
|
10
|
+
state: FormsRelayed;
|
|
11
|
+
};
|
|
12
|
+
export declare const _FormRelayContextProvider: import('react').Provider<FormRelayContext | undefined>, useFormRelayContext: () => FormRelayContext;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { FormRelayGroup } from '../get/FormRelayGroupType';
|
|
2
|
+
import { FormRelayStateSelected } from '../types';
|
|
3
|
+
/** Condense list of form states to singular booleans. */
|
|
4
|
+
export declare const getFormRelayedAggregatedByRelayedItem: (formStates: FormRelayStateSelected[]) => FormRelayGroup;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FormState } from 'react-hook-form';
|
|
2
|
+
import { SafeFieldValues } from '../../rhf/SafeFieldValuesType';
|
|
3
|
+
export type FormRelayGroup = Partial<Omit<FormState<SafeFieldValues>, 'defaultValues' | 'dirtyFields' | 'touchedFields' | 'validatingFields' | 'errors' | 'submitErrors'> & {
|
|
4
|
+
hasErrors: boolean;
|
|
5
|
+
hasDirtyFields: boolean;
|
|
6
|
+
hasTouchedFields: boolean;
|
|
7
|
+
hasValidatingFields: boolean;
|
|
8
|
+
/** Sum of all submit counts. */
|
|
9
|
+
submitCount: number;
|
|
10
|
+
/**
|
|
11
|
+
* Consider form flagged when mounted.
|
|
12
|
+
*
|
|
13
|
+
* (To use, return via `FormRelayOptions`'s `select`'s return's `FormRelayStateSelected`'s `isMounted` property.)
|
|
14
|
+
*/
|
|
15
|
+
isMounted: boolean;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const useFormRelayGrouper: () => Partial<Omit<import('react-hook-form').FormState<import('../../../../rhf/SafeFieldValuesType').SafeFieldValues>, "defaultValues" | "errors" | "dirtyFields" | "touchedFields" | "validatingFields" | "submitErrors"> & {
|
|
2
|
+
hasErrors: boolean;
|
|
3
|
+
hasDirtyFields: boolean;
|
|
4
|
+
hasTouchedFields: boolean;
|
|
5
|
+
hasValidatingFields: boolean;
|
|
6
|
+
submitCount: number;
|
|
7
|
+
isMounted: boolean;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { FormRelayGroup } from '../../FormRelayGroupType';
|
|
2
|
+
export type FormRelayGrouperContext = {
|
|
3
|
+
state: FormRelayGroup;
|
|
4
|
+
};
|
|
5
|
+
export declare const _FormRelayGrouperContextProvider: import('react').Provider<FormRelayGrouperContext | undefined>, _useFormRelayGrouperContext: () => FormRelayGrouperContext, _useFormRelayGrouperMaybeContext: () => FormRelayGrouperContext | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FormRelayGroup } from '../../FormRelayGroupType';
|
|
3
|
+
import { FormRelayGroupCriteria } from '../../useFormRelay';
|
|
4
|
+
type Props = {
|
|
5
|
+
criteria: FormRelayGroupCriteria;
|
|
6
|
+
children: ((state: FormRelayGroup) => React.ReactNode) | React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
export declare const FormRelayGrouperContextProvider: React.FC<Props>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FormRelayGroup } from '../FormRelayGroupType';
|
|
2
|
+
/**
|
|
3
|
+
* Use this when you don't (want to) know whether component is wrapped
|
|
4
|
+
* with RHF context, `FormRelayGrouperContext`, or `FormRelayContext`.
|
|
5
|
+
* Will return `FormRelayGroup`, regardless.
|
|
6
|
+
*
|
|
7
|
+
* Allows you to build naive components that are not tied to one specific context.
|
|
8
|
+
*/
|
|
9
|
+
export declare const useFirstFormStateGroup: () => FormRelayGroup;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RhfUtilsFormOptions } from '../../options/RhfUtilsFormOptionsType';
|
|
2
|
+
import { FormRelayOptions } from '../FormRelayOptions';
|
|
3
|
+
import { FormRelayGroup } from './FormRelayGroupType';
|
|
4
|
+
export declare const useFormRelayId: (formId: string) => import('../types').FormRelay | undefined;
|
|
5
|
+
export type FormRelayGroupCriteria = {
|
|
6
|
+
groups: string[];
|
|
7
|
+
} | {
|
|
8
|
+
predicate: (context: {
|
|
9
|
+
groups: FormRelayOptions['groups'];
|
|
10
|
+
options: RhfUtilsFormOptions;
|
|
11
|
+
}) => boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare const useFormRelayGroup: (criteria?: FormRelayGroupCriteria) => FormRelayGroup;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FormState } from 'react-hook-form';
|
|
2
|
+
import { RhfUtilsContext } from '../context/utils/RhfUtilsContextType';
|
|
3
|
+
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
4
|
+
import { FormRelayOptions } from './FormRelayOptions';
|
|
5
|
+
export type FormRelay<TFieldValues extends SafeFieldValues = SafeFieldValues> = {
|
|
6
|
+
state: FormRelayStateSelected<TFieldValues>;
|
|
7
|
+
options: FormRelayOptions;
|
|
8
|
+
utils: RhfUtilsContext;
|
|
9
|
+
};
|
|
10
|
+
export type FormRelayStateSelected<TFieldValues extends SafeFieldValues = SafeFieldValues> = Partial<FormState<TFieldValues> & {
|
|
11
|
+
isMounted: true;
|
|
12
|
+
}>;
|
|
@@ -9,7 +9,11 @@ export type RhfUtilsFormPropsonBeforeSubmitInvariants<TFieldValues extends SafeF
|
|
|
9
9
|
input: TFieldValues;
|
|
10
10
|
output: TTransformedValues;
|
|
11
11
|
api: TApiValues;
|
|
12
|
-
}, context: UseRhfUtilsFormOnSubmitContext<TFieldValues, TTransformedValues, TApiValues>, event: React.BaseSyntheticEvent<SubmitEvent>) => MaybePromise<
|
|
12
|
+
}, context: UseRhfUtilsFormOnSubmitContext<TFieldValues, TTransformedValues, TApiValues>, event: React.BaseSyntheticEvent<SubmitEvent>) => MaybePromise<{
|
|
13
|
+
field: keyof TFieldValues | keyof TApiValues;
|
|
14
|
+
message: string;
|
|
15
|
+
valid: boolean | undefined | null;
|
|
16
|
+
}[]>;
|
|
13
17
|
export type RhfUtilsFormProps<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues, TGetApiValues extends undefined | RhfUtilsFormPropsGetApiValues<TTransformedValues, SafeFieldValues>, TOnSubmitReturnType, TApiValues extends undefined | SafeFieldValues = TGetApiValues extends RhfUtilsFormPropsGetApiValues<TTransformedValues, infer U> ? U : undefined> = {
|
|
14
18
|
getApiData?: TGetApiValues;
|
|
15
19
|
/** Cancellation handler -- channeled through {@link RhfUtilsClientConfig.useCanFormBeCancelled} before propagating to `Children` component. */
|
|
@@ -7,5 +7,5 @@ type Props<TFieldValues extends SafeFieldValues, TTransformedValues extends Safe
|
|
|
7
7
|
onError: (error: unknown, event: React.BaseSyntheticEvent) => void;
|
|
8
8
|
onFinally?: () => MaybePromise<unknown>;
|
|
9
9
|
};
|
|
10
|
-
export declare const useRhfUtilsFormHandleSubmit_Internal: <TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>({ onValid, onInvalid, onError, onFinally, }: Props<TFieldValues, TTransformedValues>) => ((event: React.
|
|
10
|
+
export declare const useRhfUtilsFormHandleSubmit_Internal: <TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues>({ onValid, onInvalid, onError, onFinally, }: Props<TFieldValues, TTransformedValues>) => ((event: React.SubmitEvent<HTMLFormElement>) => void);
|
|
11
11
|
export {};
|