@paragrav/rhf-utils 0.62.0 → 0.64.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 +8 -6
- package/dist/dts/_exports/form.d.ts +1 -1
- package/dist/dts/client/config/RhfUtilsClientConfigType.d.ts +6 -2
- package/dist/dts/form/{RhfUtilsFormComponentPropsType.d.ts → RhfUtilsFormInjectorProps.d.ts} +6 -2
- package/dist/dts/form/with-handlers-and-children/RhfUtilsFormProps.d.ts +2 -10
- package/dist/dts/form/with-handlers-and-children/RhfUtilsFormPropsOnBeforeSubmitInvariants.d.ts +12 -0
- package/dist/dts/form/with-providers/RhfUtilsFormWithProvidersProps.d.ts +5 -1
- package/dist/dts/submit/error/FormSubmitFieldErrors.d.ts +1 -1
- package/dist/esm/FormRelaySetter.mjs +88 -139
- package/dist/esm/index.mjs +347 -602
- package/dist/esm/relay.mjs +48 -83
- package/dist/esm/trpc.mjs +24 -40
- package/package.json +29 -30
package/README.md
CHANGED
|
@@ -77,20 +77,22 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
|
|
|
77
77
|
// inject your own hooks and components
|
|
78
78
|
// into all RhfUtilsZodForm instances
|
|
79
79
|
FormChildren: (
|
|
80
|
-
//
|
|
80
|
+
// RhfUtilsFormInjectorProps
|
|
81
81
|
{
|
|
82
|
+
Outlet, // Form instance (RhfUtilsZodForm.Children) "outlet"
|
|
83
|
+
|
|
82
84
|
formId, // unique id string
|
|
83
85
|
formRef, // form element ref
|
|
84
86
|
context, // rhf UseFormReturn (without proxy `formState`)
|
|
85
87
|
options, // RhfUtilsFormOptions (with any custom props)
|
|
86
88
|
Controller, // rhf controller (SafeFieldValues-typed; no schema at this level)
|
|
87
89
|
FormSubmitError, // error class (SafeFieldValues-typed; no schema at this level)
|
|
88
|
-
children, // RhfUtilsZodForm's Children instance
|
|
89
90
|
},
|
|
90
91
|
) => {
|
|
92
|
+
// hook injected across all instances
|
|
91
93
|
useMyGlobalFormHook();
|
|
92
94
|
|
|
93
|
-
//
|
|
95
|
+
// hook injected across all instances with per-instance opt-in flag via custom option props
|
|
94
96
|
// (see "Extend RhfUtilsFormOptions" section for more info)
|
|
95
97
|
useMyOptionalFormHook({
|
|
96
98
|
enabled: !!options.enableMyOptionalFormHook,
|
|
@@ -98,8 +100,8 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
|
|
|
98
100
|
|
|
99
101
|
return (
|
|
100
102
|
<>
|
|
101
|
-
{/* RhfUtilsZodForm.Children "outlet" (see "Component Hierarchy" section) */}
|
|
102
|
-
|
|
103
|
+
{/* Form instance (RhfUtilsZodForm.Children) "outlet" (see "Component Hierarchy" section). */}
|
|
104
|
+
<Outlet />
|
|
103
105
|
|
|
104
106
|
{/* root errors list */}
|
|
105
107
|
<RootErrorsList />
|
|
@@ -190,7 +192,7 @@ Currently, only `zod` schemas are supported.
|
|
|
190
192
|
{
|
|
191
193
|
field: 'passwordConfirm', // type safe
|
|
192
194
|
message: 'Passwords must match.',
|
|
193
|
-
|
|
195
|
+
validate: data.password === data.passwordConfirm,
|
|
194
196
|
},
|
|
195
197
|
]}
|
|
196
198
|
onBeforeSubmit={({ input, output, api }, context, event) => {
|
|
@@ -2,6 +2,6 @@ export { useRhfUtilsContext } from '../form/context/utils/useRhfUtilsContext';
|
|
|
2
2
|
export type { RhfUtilsFormOptions } from '../form/options/RhfUtilsFormOptionsType';
|
|
3
3
|
export type { SafeFieldValues } from '../form/rhf/SafeFieldValuesType';
|
|
4
4
|
export type { RHF_UseFormReturnWithoutProxies as UseFormReturnWithoutProxies } from '../form/RHF_UseFormReturnWithoutProxiesType';
|
|
5
|
-
export type {
|
|
5
|
+
export type { RhfUtilsFormInjectorProps } from '../form/RhfUtilsFormInjectorProps';
|
|
6
6
|
export type { UseRhfUtilsFormChildrenProps } from '../form/UseRhfUtilsFormChildrenPropsType';
|
|
7
7
|
export { useFormRequestSubmit } from '../form/utils/useFormRequestSubmit';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FlatFieldErrorsOutputConfig } from '../../errors/flat/context/FlatFieldErrorsOutputConfig';
|
|
2
2
|
import { UseRhfUtilsFormGlobalDefaults } from '../../form/defaults/UseRhfUtilsFormGlobalDefaults';
|
|
3
|
-
import {
|
|
3
|
+
import { RhfUtilsFormInjectorProps } from '../../form/RhfUtilsFormInjectorProps';
|
|
4
4
|
import { FormSubmitFieldErrors } from '../../submit/error/FormSubmitFieldErrors';
|
|
5
5
|
import { UseRhfUtilsFormOnSubmitContext } from '../../submit/UseRhfUtilsFormOnSubmitContextType';
|
|
6
6
|
import { MaybePromise } from '../../utils/types';
|
|
@@ -26,8 +26,12 @@ export type RhfUtilsClientConfig = {
|
|
|
26
26
|
* @description
|
|
27
27
|
*
|
|
28
28
|
* (NOTE: context params are not schema-typed as not possible at this level.)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
*
|
|
32
|
+
* See README.
|
|
29
33
|
*/
|
|
30
|
-
|
|
34
|
+
FormInjector?: React.FC<RhfUtilsFormInjectorProps>;
|
|
31
35
|
/**
|
|
32
36
|
* A hook that returns a callback that determines whether form can be cancelled at event-time.
|
|
33
37
|
*
|
package/dist/dts/form/{RhfUtilsFormComponentPropsType.d.ts → RhfUtilsFormInjectorProps.d.ts}
RENAMED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { UseFormReturn } from 'react-hook-form';
|
|
2
2
|
import { FormSubmitError } from '../submit/error/FormSubmitError';
|
|
3
|
+
import { Merge } from '../utils/types';
|
|
3
4
|
import { _Controller } from './_Controller';
|
|
4
5
|
import { RhfUtilsContext } from './context/utils/RhfUtilsContextType';
|
|
5
6
|
import { SafeFieldValues } from './rhf/SafeFieldValuesType';
|
|
6
7
|
/**
|
|
7
8
|
* RhfUtilsClientConfig's FormComponent props.
|
|
8
9
|
*/
|
|
9
|
-
export type
|
|
10
|
+
export type RhfUtilsFormInjectorProps<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues> = Merge<{
|
|
11
|
+
/** Form instance children (`RhfUtilsZodForm.Children`) to output amid globally-injected code. */
|
|
12
|
+
Outlet: React.FC;
|
|
13
|
+
}, RhfUtilsContext, {
|
|
10
14
|
rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
|
|
11
15
|
Controller: typeof _Controller<TFieldValues>;
|
|
12
16
|
FormSubmitError: typeof FormSubmitError<TFieldValues>;
|
|
13
|
-
}
|
|
17
|
+
}>;
|
|
@@ -4,16 +4,8 @@ import { UseRhfUtilsFormOnSubmitContext, UseRhfUtilsFormOnSubmitErrorContext } f
|
|
|
4
4
|
import { UseRhfUtilsFormInstanceFormProps } from '../defaults/form/UseRhfUtilsFormInstanceFormProps';
|
|
5
5
|
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
6
6
|
import { UseRhfUtilsFormChildrenProps } from '../UseRhfUtilsFormChildrenPropsType';
|
|
7
|
+
import { RhfUtilsFormPropsOnBeforeSubmitInvariants } from './RhfUtilsFormPropsOnBeforeSubmitInvariants';
|
|
7
8
|
export type RhfUtilsFormPropsGetApiValues<TTransformedValues extends SafeFieldValues, TApiValues> = (data: TTransformedValues) => TApiValues;
|
|
8
|
-
export type RhfUtilsFormPropsonBeforeSubmitInvariants<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues, TApiValues extends undefined | SafeFieldValues> = (data: {
|
|
9
|
-
input: TFieldValues;
|
|
10
|
-
output: TTransformedValues;
|
|
11
|
-
api: TApiValues;
|
|
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
|
-
}[]>;
|
|
17
9
|
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> = {
|
|
18
10
|
getApiData?: TGetApiValues;
|
|
19
11
|
/** Cancellation handler -- channeled through {@link RhfUtilsClientConfig.useCanFormBeCancelled} before propagating to `Children` component. */
|
|
@@ -24,7 +16,7 @@ export type RhfUtilsFormProps<TFieldValues extends SafeFieldValues, TTransformed
|
|
|
24
16
|
* List of invariants to run against input/output/api data.
|
|
25
17
|
* For any and all false-y values, a {@link FormSubmitFieldErrors} will be thrown.
|
|
26
18
|
*/
|
|
27
|
-
onBeforeSubmitInvariants?:
|
|
19
|
+
onBeforeSubmitInvariants?: RhfUtilsFormPropsOnBeforeSubmitInvariants<TFieldValues, TTransformedValues, TApiValues>;
|
|
28
20
|
onBeforeSubmit?: (data: {
|
|
29
21
|
input: TFieldValues;
|
|
30
22
|
output: TTransformedValues;
|
package/dist/dts/form/with-handlers-and-children/RhfUtilsFormPropsOnBeforeSubmitInvariants.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { UseRhfUtilsFormOnSubmitContext } from '../../submit/UseRhfUtilsFormOnSubmitContextType';
|
|
2
|
+
import { MaybePromise } from '../../utils/types';
|
|
3
|
+
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
4
|
+
export type RhfUtilsFormPropsOnBeforeSubmitInvariants<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues, TApiValues extends undefined | SafeFieldValues> = (data: {
|
|
5
|
+
input: TFieldValues;
|
|
6
|
+
output: TTransformedValues;
|
|
7
|
+
api: TApiValues;
|
|
8
|
+
}, context: UseRhfUtilsFormOnSubmitContext<TFieldValues, TTransformedValues, TApiValues>, event: React.BaseSyntheticEvent<SubmitEvent>) => MaybePromise<{
|
|
9
|
+
field: keyof TFieldValues | keyof TApiValues;
|
|
10
|
+
message: string;
|
|
11
|
+
validate: boolean | undefined | null;
|
|
12
|
+
}[]>;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { Resolver } from 'react-hook-form';
|
|
2
|
+
import { Merge } from '../../utils/types';
|
|
1
3
|
import { RhfUtilsFormProvidersProps } from '../providers/RhfUtilsFormProvidersPropsType';
|
|
2
4
|
import { SafeFieldValues } from '../rhf/SafeFieldValuesType';
|
|
3
5
|
import { RhfUtilsFormProps, RhfUtilsFormPropsGetApiValues } from '../with-handlers-and-children/RhfUtilsFormProps';
|
|
4
|
-
export type RhfUtilsFormWithProvidersProps<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> =
|
|
6
|
+
export type RhfUtilsFormWithProvidersProps<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> = Merge<RhfUtilsFormProps<TFieldValues, TTransformedValues, TGetApiValues, TOnSubmitReturnType, TApiValues>, RhfUtilsFormProvidersProps<TFieldValues, TTransformedValues>, {
|
|
7
|
+
resolver?: Resolver<TFieldValues, unknown, TTransformedValues>;
|
|
8
|
+
}>;
|
|
@@ -9,6 +9,6 @@ import { SafeFieldValues } from '../../form/rhf/SafeFieldValuesType';
|
|
|
9
9
|
* - simplified `ErrorOption` value.
|
|
10
10
|
*/
|
|
11
11
|
export type FormSubmitFieldErrors<TFieldValues extends SafeFieldValues = SafeFieldValues> = Record<FieldPath<TFieldValues> | `root.${string}`, {
|
|
12
|
-
type?: string;
|
|
13
12
|
message: string;
|
|
13
|
+
type?: string;
|
|
14
14
|
}>;
|
|
@@ -1,140 +1,89 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { get as
|
|
4
|
-
import { flatten as
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import e from "react";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { get as n, useFormState as r } from "react-hook-form";
|
|
4
|
+
import { flatten as i } from "flat";
|
|
5
|
+
//#region src/utils/createContext.ts
|
|
6
|
+
function a() {
|
|
7
|
+
let t = e.createContext(void 0), n = () => e.useContext(t);
|
|
8
|
+
return {
|
|
9
|
+
Provider: t.Provider,
|
|
10
|
+
useMaybe: n,
|
|
11
|
+
useRequired: () => {
|
|
12
|
+
let e = n();
|
|
13
|
+
if (e === void 0) throw Error();
|
|
14
|
+
return e;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
message: t.message,
|
|
90
|
-
hasRef: !!t.ref
|
|
91
|
-
// strip out actual ref, etc. (avoid circular JSON error)
|
|
92
|
-
}
|
|
93
|
-
])
|
|
94
|
-
), O = (e) => {
|
|
95
|
-
if (!e) return;
|
|
96
|
-
const [r] = s.useState(e);
|
|
97
|
-
g(r), h(r);
|
|
98
|
-
}, g = (e) => {
|
|
99
|
-
const r = d(), t = l(), o = y(e);
|
|
100
|
-
s.useEffect(
|
|
101
|
-
() => (t.add(o, r, e), () => {
|
|
102
|
-
t.remove(r.formId);
|
|
103
|
-
}),
|
|
104
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
105
|
-
[]
|
|
106
|
-
);
|
|
107
|
-
}, h = (e) => {
|
|
108
|
-
const r = d(), t = l(), o = y(e);
|
|
109
|
-
s.useEffect(
|
|
110
|
-
// when form state changes, publish to relay context
|
|
111
|
-
() => {
|
|
112
|
-
t.update(r.formId, o);
|
|
113
|
-
},
|
|
114
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
115
|
-
[o]
|
|
116
|
-
);
|
|
117
|
-
}, y = (e) => {
|
|
118
|
-
const r = R(), t = e.select(r), o = JSON.stringify({
|
|
119
|
-
...t,
|
|
120
|
-
errors: t.errors && C(t.errors)
|
|
121
|
-
});
|
|
122
|
-
return s.useMemo(
|
|
123
|
-
// when watch JSON changes, update memo
|
|
124
|
-
() => t,
|
|
125
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
126
|
-
[o]
|
|
127
|
-
);
|
|
128
|
-
}, _ = ({ options: e }) => (O(e), null);
|
|
129
|
-
export {
|
|
130
|
-
k as F,
|
|
131
|
-
I as _,
|
|
132
|
-
_ as a,
|
|
133
|
-
l as b,
|
|
134
|
-
f as c,
|
|
135
|
-
q as d,
|
|
136
|
-
O as e,
|
|
137
|
-
p as g,
|
|
138
|
-
U as i,
|
|
139
|
-
d as u
|
|
140
|
-
};
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/form/relay/context/useFormRelayContext.ts
|
|
20
|
+
var { Provider: o, useRequired: s } = a(), c = ({ children: n }) => {
|
|
21
|
+
let [r, i] = e.useState({});
|
|
22
|
+
return /* @__PURE__ */ t(o, {
|
|
23
|
+
value: {
|
|
24
|
+
add: e.useCallback((e, t, n) => {
|
|
25
|
+
if (r[t.formId]) throw Error("Form id already exists.");
|
|
26
|
+
i((r) => ({
|
|
27
|
+
...r,
|
|
28
|
+
[t.formId]: {
|
|
29
|
+
state: e,
|
|
30
|
+
utils: t,
|
|
31
|
+
options: n
|
|
32
|
+
}
|
|
33
|
+
}));
|
|
34
|
+
}, [r]),
|
|
35
|
+
update: e.useCallback((e, t) => {
|
|
36
|
+
i((n) => {
|
|
37
|
+
let r = n[e];
|
|
38
|
+
if (!r) throw Error("Form id doesn't exist");
|
|
39
|
+
return {
|
|
40
|
+
...n,
|
|
41
|
+
[e]: {
|
|
42
|
+
...r,
|
|
43
|
+
state: t
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}, []),
|
|
48
|
+
remove: e.useCallback((e) => {
|
|
49
|
+
i((t) => Object.fromEntries(Object.entries(t).filter(([t]) => t !== e)));
|
|
50
|
+
}, []),
|
|
51
|
+
state: r
|
|
52
|
+
},
|
|
53
|
+
children: n
|
|
54
|
+
});
|
|
55
|
+
}, { Provider: l, useRequired: u, useMaybe: d } = a(), f = (e) => Object.keys(e).length === 0, p = (e) => i(e), m = (e) => {
|
|
56
|
+
let t = p(e);
|
|
57
|
+
return Object.fromEntries(Object.keys(t).reduce((t, r) => {
|
|
58
|
+
let i = r.replace(h, "");
|
|
59
|
+
if (i === r) return t;
|
|
60
|
+
let a = n(e, i, void 0);
|
|
61
|
+
return a && t.push([i, a]), t;
|
|
62
|
+
}, []));
|
|
63
|
+
}, h = /\.(?:type|message)\b$/, g = (e) => Object.fromEntries(Object.entries(m(e)).map(([e, t]) => [e, {
|
|
64
|
+
type: t.type,
|
|
65
|
+
message: t.message,
|
|
66
|
+
hasRef: !!t.ref
|
|
67
|
+
}])), _ = (t) => {
|
|
68
|
+
if (!t) return;
|
|
69
|
+
let [n] = e.useState(t);
|
|
70
|
+
v(n), y(n);
|
|
71
|
+
}, v = (t) => {
|
|
72
|
+
let n = u(), r = s(), i = b(t);
|
|
73
|
+
e.useEffect(() => (r.add(i, n, t), () => {
|
|
74
|
+
r.remove(n.formId);
|
|
75
|
+
}), []);
|
|
76
|
+
}, y = (t) => {
|
|
77
|
+
let n = u(), r = s(), i = b(t);
|
|
78
|
+
e.useEffect(() => {
|
|
79
|
+
r.update(n.formId, i);
|
|
80
|
+
}, [i]);
|
|
81
|
+
}, b = (t) => {
|
|
82
|
+
let n = r(), i = t.select(n), a = JSON.stringify({
|
|
83
|
+
...i,
|
|
84
|
+
errors: i.errors && g(i.errors)
|
|
85
|
+
});
|
|
86
|
+
return e.useMemo(() => i, [a]);
|
|
87
|
+
}, x = ({ options: e }) => (_(e), null);
|
|
88
|
+
//#endregion
|
|
89
|
+
export { l as a, c, f as i, s as l, _ as n, u as o, m as r, d as s, x as t, a as u };
|