@paragrav/rhf-utils 0.61.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.
Files changed (44) hide show
  1. package/README.md +49 -89
  2. package/dist/dts/_exports/relay.d.ts +7 -8
  3. package/dist/dts/errors/flat/getFlatFieldErrors.d.ts +5 -1
  4. package/dist/dts/form/RhfUtilsFormComponentPropsType.d.ts +2 -2
  5. package/dist/dts/form/UseRhfUtilsFormChildrenPropsType.d.ts +2 -2
  6. package/dist/dts/form/context/utils/LastSubmitStateType.d.ts +1 -0
  7. package/dist/dts/form/context/utils/{RhfUtilsContextPropsType.d.ts → RhfUtilsContextType.d.ts} +3 -2
  8. package/dist/dts/form/context/utils/useRhfUtilsContext.d.ts +4 -4
  9. package/dist/dts/form/defaults/form/useRhfUtilsFormResolvedFormProps.d.ts +10 -10
  10. package/dist/dts/form/providers/RhfUtilsFormProviders.d.ts +1 -1
  11. package/dist/dts/form/providers/RhfUtilsFormProvidersPropsType.d.ts +2 -0
  12. package/dist/dts/form/relay/FormRelayOptions.d.ts +16 -0
  13. package/dist/dts/form/{state/relay/FormStateRelayContextProvider.d.ts → relay/context/FormRelayContextProvider.d.ts} +1 -1
  14. package/dist/dts/form/relay/context/useFormRelayContext.d.ts +12 -0
  15. package/dist/dts/form/relay/context/utils.d.ts +4 -0
  16. package/dist/dts/form/relay/get/FormRelayGroupType.d.ts +16 -0
  17. package/dist/dts/form/relay/get/grouper/context/hooks.d.ts +8 -0
  18. package/dist/dts/form/relay/get/grouper/context/index.d.ts +5 -0
  19. package/dist/dts/form/relay/get/grouper/context/provider.d.ts +9 -0
  20. package/dist/dts/form/relay/get/grouper/useFirstFormStateGroup.d.ts +9 -0
  21. package/dist/dts/form/relay/get/useFormRelay.d.ts +13 -0
  22. package/dist/dts/form/relay/set/FormRelaySetter.d.ts +6 -0
  23. package/dist/dts/form/relay/set/useFormRelaySet.d.ts +2 -0
  24. package/dist/dts/form/relay/types.d.ts +12 -0
  25. package/dist/dts/form/with-handlers-and-children/RhfUtilsFormProps.d.ts +5 -1
  26. package/dist/dts/form/with-handlers-and-children/_useHandleSubmit.d.ts +1 -1
  27. package/dist/dts/form/with-providers/RhfUtilsFormWithProviders.d.ts +1 -1
  28. package/dist/dts/submit/UseRhfUtilsFormOnSubmitContextType.d.ts +3 -3
  29. package/dist/dts/submit/last-error/useLastSubmitErrorContextWith.d.ts +1 -1
  30. package/dist/esm/FormRelaySetter.mjs +140 -0
  31. package/dist/esm/index.mjs +226 -220
  32. package/dist/esm/relay.mjs +71 -209
  33. package/package.json +17 -17
  34. package/dist/dts/form/RhfUtilsFormStateWithUtilsType.d.ts +0 -7
  35. package/dist/dts/form/state/relay/FormStateRelayedAggregatedType.d.ts +0 -10
  36. package/dist/dts/form/state/relay/FormStateRelayedItemType.d.ts +0 -11
  37. package/dist/dts/form/state/relay/FormStateRelayedOptionsType.d.ts +0 -20
  38. package/dist/dts/form/state/relay/FormStateRelayedType.d.ts +0 -3
  39. package/dist/dts/form/state/relay/pull/hooks.d.ts +0 -31
  40. package/dist/dts/form/state/relay/push/FormStateRelayPusher.d.ts +0 -4
  41. package/dist/dts/form/state/relay/push/useFormStateRelayPusher.d.ts +0 -3
  42. package/dist/dts/form/state/relay/useFormStateRelayContext.d.ts +0 -20
  43. package/dist/dts/form/state/relay/utils.d.ts +0 -4
  44. 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 (`FormComponent`)
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 (🔗 [`FormStateRelayContextProvider`](#form-state-relay) section) ✨
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) (`FormStateRelayContextProvider`): relay form state
47
+ - 🔗 [Form State Relay](#form-state-relay) (`FormRelayContextProvider`): relay form state
48
48
 
49
49
  ## Config
50
50
 
@@ -180,17 +180,18 @@ Currently, only `zod` schemas are supported.
180
180
  // cancel handler (passed to `Children` below)
181
181
  // execution routed through `RhfUtilsClientConfig.useCanFormBeCancelled`, if provided
182
182
  onCancel={handleCancel}
183
- // submit handlers
183
+ // SUBMIT HANDLERS
184
+ // invariants
184
185
  onBeforeSubmitInvariants={async (
185
186
  { input, output, api }, // schema input (form values), output; api data (via getApiData)
186
187
  context, // UseRhfUtilsFormOnSubmitContext (id, ref, rhf context (without proxy formState), utils options, schema-typed FormSubmitError class)
187
188
  event, // SubmitEvent
188
189
  ) => [
189
- [
190
- 'passwordConfirm', // type safe
191
- 'Passwords must match.',
192
- data.password === data.passwordConfirm,
193
- ],
190
+ {
191
+ field: 'passwordConfirm', // type safe
192
+ message: 'Passwords must match.',
193
+ valid: data.password === data.passwordConfirm,
194
+ },
194
195
  ]}
195
196
  onBeforeSubmit={({ input, output, api }, context, event) => {
196
197
  if (!isValid(input.email))
@@ -327,7 +328,7 @@ Sometimes you need to control the nesting of the Form element. For example, to a
327
328
  </aside>
328
329
  ```
329
330
 
330
- For similar pattern, especially across more than one form, see [Form State Relay](#form-state-relay) section.
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.
331
332
 
332
333
  ## `FormSubmitError`
333
334
 
@@ -383,7 +384,9 @@ type RhfUtilsFormOptions = {
383
384
  };
384
385
  ```
385
386
 
386
- If you need access to options deeper in your component structure, use `useRhfUtilsContext` to receive `RhfUtilsContext` object, which includes `formId`, `formRef`, and `options` settings.
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.
387
390
 
388
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.
389
392
 
@@ -397,7 +400,7 @@ import '@paragrav/rhf-utils';
397
400
  declare module '@paragrav/rhf-utils' {
398
401
  export interface Register {
399
402
  RhfUtilsFormOptions: {
400
- /** Custom props for your custom options/hooks/behaviors. */
403
+ /** Custom props for your custom options/hooks/behaviors per form instance. */
401
404
  enableMyPrompter?: boolean;
402
405
  enableMyOptionalFormHook?: boolean;
403
406
  configMyOptionalFormHook?: MyCustomFormHookConfig;
@@ -406,99 +409,56 @@ declare module '@paragrav/rhf-utils' {
406
409
  }
407
410
  ```
408
411
 
409
- ## <a id="form-state-relay" /> Form State Relay _(~1.2kB min+gzip)_
410
-
411
- Sometimes you need to access one or more forms' state outside the form (and its providers).
412
-
413
- ### Single form state
414
-
415
- Use case: display a form's errors (or any other state) outside form and its context.
416
-
417
- ```tsx
418
- <FormStateRelayContextProvider> // relay provider
419
- <ReactHookForm.FormProvider> // rhf provider
420
- <FormStateRelayPusher /> // push form state
421
- <ReactHookForm.FormProvider>
412
+ ## <a id="form-state-relay"></a> Form State Relay
422
413
 
423
- <WatchOutsideFormContext /> // watch form state
424
- </FormStateRelayContextProvider>;
425
- ```
414
+ Sometimes you need to access one or more forms' state outside its respective context.
426
415
 
427
- 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.
428
417
 
429
418
  ```ts
430
- type FormStateRelayPushOptions = {
431
- group?: string | string[]; // assign group(s) to watch multiple forms in aggregate
432
- flaggedState?: {
433
- isMounted?: true; // flag form when mounted -- e.g., forms that are hidden by default
434
- };
435
- };
436
- ```
437
-
438
- ```tsx
439
- function WatchOutsideFormContext() {
440
- // FormStateWithUtils (either via RHF -- when requested within form context -- or relay when not)
441
- const formState = useFormStateWithUtilsViaRhfOrRelay();
442
- }
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;
443
425
 
444
- // when watching a single form, original RHF FormState with generally-typed SafeFieldValues
445
- type FormStateRelayed = FormState<SafeFieldValues>;
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
+ };
446
433
  ```
447
434
 
448
- The `useFormStateWithUtilsViaRhfOrRelay` hook uses `useFormStateRelayPullOnlyOrThrow` internally. It provides additional naivety when consumer doesn't know which context between RHF or Relay is present. (This is useful when building base components -- e.g., buttons -- which may exist outside of form context.)
435
+ There are two main ways to get form state that has been relayed.
449
436
 
450
- ### Multiple forms
437
+ ### Get form relay by id
451
438
 
452
- Use cases:
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`).
453
440
 
454
- - disable parent form when ANY child is "flagged" (i.e., dirty)
455
- - disable ALL children when parent is "flagged" (i.e., submitting)
456
- - confirm navigation when ANY mounted form is "flagged" (i.e., dirty)
441
+ ### Get form relay by group
457
442
 
458
- ```tsx
459
- function ParentForm() {
460
- const childrenFormState = useFormStateRelayWatchGroup('children'); // FormStateRelayedAggregated
461
-
462
- return (
463
- <ReactHookForm.FormProvider>
464
- <FormStateRelayPusher formId="parent" /> // pusher
465
- <input type="submit" disabled={childrenFormState.isDirty} />
466
- </ReactHookForm.FormProvider>
467
- );
468
- }
443
+ When retrieving by group, state is merged into a `FormRelayGroup` object (and no options or utils are provided, as these are form-specific).
469
444
 
470
- function ChildForm() {
471
- 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".
472
446
 
473
- return (
474
- <ReactHookForm.FormProvider>
475
- <FormStateRelayPusher group="children" /> // pusher
476
- <input type="submit" disabled={parentFormState.isSubmitting} />
477
- </ReactHookForm.FormProvider>
478
- );
479
- }
447
+ You can also use `FormRelayGrouperContextProvider` if you want to make this group accessible via naive hook.
480
448
 
481
- type FormStateRelayedAggregated = FormStateRelayed & {
482
- // object values reduced to booleans for non-empty-ness
483
- dirtyFields: boolean;
484
- touchedFields: boolean;
485
- validatingFields: boolean;
486
- error: boolean;
487
- // composites
488
- isSubmitUnsuccessful: boolean;
489
- isMountedFlagged: boolean; // via RelayedFormOptions['flaggedState']['isMounted']
490
- };
449
+ ```tsx
450
+ <FormRelayGrouperContextProvider
451
+ predicate={({ options, utils }) =>
452
+ !!options?.groups?.includes("parent") // find specific group
453
+ }
454
+ >
455
+ {(state: FormRelayGroup) => ()}
456
+ </FormRelayGrouperContextProvider>
491
457
  ```
492
458
 
493
- You can also aggregate any (i.e., all) forms via `useFormStateRelayPullAny`, which returns `FormStateRelayedAggregated` as well.
459
+ Alternatively, instead render callback, you can use `useFormRelayGrouper`.
494
460
 
495
- ```tsx
496
- <FormStateRelayContextProvider>
497
- <ParentForm />
498
- <ChildForm />
499
- <Child2Form />
500
- </FormStateRelayContextProvider>
501
- ```
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`.)
502
462
 
503
463
  ## Field Errors
504
464
 
@@ -1,8 +1,7 @@
1
- export { FormStateRelayContextProvider } from '../form/state/relay/FormStateRelayContextProvider';
2
- export type { FormStateRelayedAggregated } from '../form/state/relay/FormStateRelayedAggregatedType';
3
- export type { FormStateRelayedItemWithUtils } from '../form/state/relay/FormStateRelayedItemType';
4
- export type { FormStateRelayedOptions } from '../form/state/relay/FormStateRelayedOptionsType';
5
- export type { FormStateRelayed } from '../form/state/relay/FormStateRelayedType';
6
- export { useFormStateRelayPullAny, useFormStateRelayPullById, useFormStateRelayPullGroup, useFormStateRelayPullOnlyOrThrow, useFormStateWithUtilsViaRhfOrRelay, } from '../form/state/relay/pull/hooks';
7
- export { FormStateRelayPusher } from '../form/state/relay/push/FormStateRelayPusher';
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';
@@ -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 declare const getFlatFieldErrorsSansRef: (errors: FieldErrors) => Record<string, Omit<FieldError, "ref">>;
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,12 +1,12 @@
1
1
  import { UseFormReturn } from 'react-hook-form';
2
2
  import { FormSubmitError } from '../submit/error/FormSubmitError';
3
3
  import { _Controller } from './_Controller';
4
- import { RhfUtilsContextProps } from './context/utils/RhfUtilsContextPropsType';
4
+ import { RhfUtilsContext } from './context/utils/RhfUtilsContextType';
5
5
  import { SafeFieldValues } from './rhf/SafeFieldValuesType';
6
6
  /**
7
7
  * RhfUtilsClientConfig's FormComponent props.
8
8
  */
9
- export type RhfUtilsFormComponentProps<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues> = RhfUtilsContextProps & {
9
+ export type RhfUtilsFormComponentProps<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues> = RhfUtilsContext & {
10
10
  rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
11
11
  Controller: typeof _Controller<TFieldValues>;
12
12
  FormSubmitError: typeof FormSubmitError<TFieldValues>;
@@ -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 { RhfUtilsContextProps } from './context/utils/RhfUtilsContextPropsType';
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> = RhfUtilsContextProps & {
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';
@@ -1,11 +1,12 @@
1
1
  import { RefObject } from 'react';
2
+ import { LastSubmitState } from './LastSubmitStateType';
2
3
  import { RhfUtilsContextProviderProps } from './RhfUtilsContextProvider';
3
- export type RhfUtilsContextProps = RhfUtilsContextProviderProps & {
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<null | 'submitting' | 'success' | 'error'>;
11
+ lastSubmitStateRef: RefObject<LastSubmitState>;
11
12
  };
@@ -1,5 +1,5 @@
1
- import { RhfUtilsContextProps } from './RhfUtilsContextPropsType';
2
- declare const _RhfUtilsContextProvider: import('react').Provider<RhfUtilsContextProps | undefined>, useRhfUtilsContext: () => import('./RhfUtilsContextProvider').RhfUtilsContextProviderProps & {
3
- lastSubmitStateRef: import('react').RefObject<null | "submitting" | "success" | "error">;
4
- }, useRhfUtilsMaybeContext: () => RhfUtilsContextProps | undefined;
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').FormEventHandler<HTMLFormElement> | undefined;
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').FormEventHandler<HTMLFormElement> | undefined;
142
+ onChangeCapture?: import('react').ChangeEventHandler<HTMLFormElement, Element> | undefined;
143
143
  onBeforeInput?: import('react').InputEventHandler<HTMLFormElement> | undefined;
144
- onBeforeInputCapture?: import('react').FormEventHandler<HTMLFormElement> | undefined;
145
- onInput?: import('react').FormEventHandler<HTMLFormElement> | undefined;
146
- onInputCapture?: import('react').FormEventHandler<HTMLFormElement> | undefined;
147
- onReset?: import('react').FormEventHandler<HTMLFormElement> | undefined;
148
- onResetCapture?: import('react').FormEventHandler<HTMLFormElement> | undefined;
149
- onSubmitCapture?: import('react').FormEventHandler<HTMLFormElement> | undefined;
150
- onInvalid?: import('react').FormEventHandler<HTMLFormElement> | undefined;
151
- onInvalidCapture?: import('react').FormEventHandler<HTMLFormElement> | undefined;
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
+ };
@@ -1,4 +1,4 @@
1
1
  import { default as React } from 'react';
2
2
  type Props = React.PropsWithChildren;
3
- export declare const FormStateRelayContextProvider: React.FC<Props>;
3
+ export declare const FormRelayContextProvider: React.FC<Props>;
4
4
  export {};
@@ -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,6 @@
1
+ import { FormRelayOptions } from '../FormRelayOptions';
2
+ type Props = {
3
+ options?: FormRelayOptions;
4
+ };
5
+ export declare const FormRelaySetter: React.FC<Props>;
6
+ export {};
@@ -0,0 +1,2 @@
1
+ import { FormRelayOptions } from '../FormRelayOptions';
2
+ export declare const useFormRelaySet: (options?: FormRelayOptions) => void;
@@ -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<[keyof TFieldValues | keyof TApiValues, string, unknown][]>;
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.FormEvent<HTMLFormElement>) => void);
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 {};
@@ -5,4 +5,4 @@ import { RhfUtilsFormWithProvidersProps } from './RhfUtilsFormWithProvidersProps
5
5
  * Form providers (with utils) with immediate descendent {@link RhfUtilsForm}.
6
6
  * (Syntactic sugar for {@link useRhfUtilsForm}. Use this for most applications.)
7
7
  */
8
- export declare function RhfUtilsFormWithProviders<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>({ getApiData, resolver, rhf, defaultValues, options, onCancel, onSubmitInvalid, onBeforeSubmitInvariants, onBeforeSubmit, onSubmit, onSubmitSuccess, onSubmitError, onSubmitFinally, Children, form, formId, className, }: RhfUtilsFormWithProvidersProps<TFieldValues, TTransformedValues, TGetApiValues, TOnSubmitReturnType, TApiValues>): import("react/jsx-runtime").JSX.Element;
8
+ export declare function RhfUtilsFormWithProviders<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>({ getApiData, resolver, rhf, defaultValues, options, relay, onCancel, onSubmitInvalid, onBeforeSubmitInvariants, onBeforeSubmit, onSubmit, onSubmitSuccess, onSubmitError, onSubmitFinally, Children, form, formId, className, }: RhfUtilsFormWithProvidersProps<TFieldValues, TTransformedValues, TGetApiValues, TOnSubmitReturnType, TApiValues>): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { UseFormReturn } from 'react-hook-form';
2
2
  import { FormSubmitError } from './error/FormSubmitError';
3
3
  import { FormSubmitFieldErrors } from './error/FormSubmitFieldErrors';
4
- import { RhfUtilsContextProps } from '../form/context/utils/RhfUtilsContextPropsType';
4
+ import { RhfUtilsContext } from '../form/context/utils/RhfUtilsContextType';
5
5
  import { SafeFieldValues } from '../form/rhf/SafeFieldValuesType';
6
6
  /**
7
7
  * Props for onSubmit other than `data` and `event`.
@@ -9,7 +9,7 @@ import { SafeFieldValues } from '../form/rhf/SafeFieldValuesType';
9
9
  * Consider keeping shape in line with `UseRhfUtilsFormChildrenProps` and `UseRhfUtilsFormReturn`.
10
10
  */
11
11
  export type UseRhfUtilsFormOnSubmitContext<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues, TApiValues extends undefined | SafeFieldValues = undefined> = {
12
- utils: RhfUtilsContextProps;
12
+ utils: RhfUtilsContext;
13
13
  rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
14
14
  FormSubmitError: typeof FormSubmitError<TFieldValues, TApiValues>;
15
15
  };
@@ -17,7 +17,7 @@ export type UseRhfUtilsFormOnSubmitContext<TFieldValues extends SafeFieldValues
17
17
  * Props for onSubmitError other than `error` and `event`.
18
18
  */
19
19
  export type UseRhfUtilsFormOnSubmitErrorContext<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues> = {
20
- utils: RhfUtilsContextProps;
20
+ utils: RhfUtilsContext;
21
21
  rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
22
22
  errors?: FormSubmitFieldErrors;
23
23
  };
@@ -1,2 +1,2 @@
1
1
  import { MaybePromise } from '../../utils/types';
2
- export declare const useLastSubmitErrorContextWith: (handleSubmit: (event: React.FormEvent<HTMLFormElement>) => MaybePromise<unknown>) => (event: React.FormEvent<HTMLFormElement>) => Promise<unknown>;
2
+ export declare const useLastSubmitErrorContextWith: (handleSubmit: (event: React.SubmitEvent<HTMLFormElement>) => MaybePromise<unknown>) => (event: React.SubmitEvent<HTMLFormElement>) => Promise<unknown>;