@paragrav/rhf-utils 0.66.0 → 0.67.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/dist/tsdown/FormRelayOptions-mBqiP41Z.d.ts +29 -0
- package/dist/tsdown/FormRelaySetter-BKO0Wodf.js +192 -0
- package/dist/tsdown/RhfUtilsClientConfigType-CeOJzNAc.d.ts +212 -0
- package/dist/tsdown/RhfUtilsContextType-BFmDtONY.d.ts +81 -0
- package/dist/tsdown/index.d.ts +207 -0
- package/dist/tsdown/index.js +745 -0
- package/dist/tsdown/relay.d.ts +56 -0
- package/dist/tsdown/relay.js +71 -0
- package/dist/tsdown/trpc.d.ts +36 -0
- package/dist/tsdown/trpc.js +47 -0
- package/package.json +2 -3
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { a as RhfUtilsFormOptions, i as SafeFieldValues } from "./RhfUtilsContextType-BFmDtONY.js";
|
|
2
|
+
import { n as FormRelay, r as FormRelayStateSelected, t as FormRelayOptions } from "./FormRelayOptions-mBqiP41Z.js";
|
|
3
|
+
import React$1 from "react";
|
|
4
|
+
import { FormState } from "react-hook-form";
|
|
5
|
+
|
|
6
|
+
//#region src/form/relay/context/FormRelayContextProvider.d.ts
|
|
7
|
+
type Props$1 = React$1.PropsWithChildren;
|
|
8
|
+
declare const FormRelayContextProvider: React$1.FC<Props$1>;
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/form/relay/get/FormRelayGroupType.d.ts
|
|
11
|
+
type FormRelayGroup = Partial<Omit<FormState<SafeFieldValues>, 'defaultValues' | 'dirtyFields' | 'touchedFields' | 'validatingFields' | 'errors' | 'submitErrors'> & {
|
|
12
|
+
hasErrors: boolean;
|
|
13
|
+
hasDirtyFields: boolean;
|
|
14
|
+
hasTouchedFields: boolean;
|
|
15
|
+
hasValidatingFields: boolean; /** Sum of all submit counts. */
|
|
16
|
+
submitCount: number;
|
|
17
|
+
/**
|
|
18
|
+
* Consider form flagged when mounted.
|
|
19
|
+
*
|
|
20
|
+
* (To use, return via `FormRelayOptions`'s `select`'s return's `FormRelayStateSelected`'s `isMounted` property.)
|
|
21
|
+
*/
|
|
22
|
+
isMounted: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/form/relay/get/grouper/useFirstFormStateGroup.d.ts
|
|
26
|
+
/**
|
|
27
|
+
* Use this when you don't (want to) know whether component is wrapped
|
|
28
|
+
* with RHF context, `FormRelayGrouperContext`, or `FormRelayContext`.
|
|
29
|
+
* Will return `FormRelayGroup`, regardless.
|
|
30
|
+
*
|
|
31
|
+
* Allows you to build naive components that are not tied to one specific context.
|
|
32
|
+
*/
|
|
33
|
+
declare const useFirstFormStateGroup: () => FormRelayGroup;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/form/relay/get/useFormRelay.d.ts
|
|
36
|
+
declare const useFormRelayId: (formId: string) => FormRelay | undefined;
|
|
37
|
+
type FormRelayGroupCriteria = {
|
|
38
|
+
groups: string[];
|
|
39
|
+
} | {
|
|
40
|
+
predicate: (context: {
|
|
41
|
+
groups: FormRelayOptions['groups'];
|
|
42
|
+
options: RhfUtilsFormOptions;
|
|
43
|
+
}) => boolean;
|
|
44
|
+
};
|
|
45
|
+
declare const useFormRelayGroup: (criteria?: FormRelayGroupCriteria) => FormRelayGroup;
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/form/relay/set/FormRelaySetter.d.ts
|
|
48
|
+
type Props = {
|
|
49
|
+
options?: FormRelayOptions;
|
|
50
|
+
};
|
|
51
|
+
declare const FormRelaySetter: React.FC<Props>;
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/form/relay/set/useFormRelaySet.d.ts
|
|
54
|
+
declare const useFormRelaySet: (options?: FormRelayOptions) => void;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { type FormRelay, FormRelayContextProvider, type FormRelayGroup, FormRelaySetter, type FormRelayStateSelected, useFirstFormStateGroup, useFormRelayGroup, useFormRelayId, useFormRelaySet };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { c as FormRelayContextProvider, i as isEmptyObject, l as useFormRelayContext, n as useFormRelaySet, s as useRhfUtilsMaybeContext, t as FormRelaySetter, u as createContext } from "./FormRelaySetter-BKO0Wodf.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useFormState } from "react-hook-form";
|
|
4
|
+
//#region src/form/relay/context/utils.ts
|
|
5
|
+
/** Condense list of form states to singular booleans. */
|
|
6
|
+
const getFormRelayedAggregatedByRelayedItem = (formStates) => formStates.reduce((acc, curr) => ({
|
|
7
|
+
isDirty: acc.isDirty || curr.isDirty,
|
|
8
|
+
isSubmitting: acc.isSubmitting || curr.isSubmitting,
|
|
9
|
+
isLoading: acc.isLoading || curr.isLoading,
|
|
10
|
+
isSubmitted: acc.isSubmitted || curr.isSubmitted,
|
|
11
|
+
isSubmitSuccessful: acc.isSubmitSuccessful || curr.isSubmitSuccessful,
|
|
12
|
+
isValidating: acc.isValidating || curr.isValidating,
|
|
13
|
+
isValid: acc.isValid || curr.isValid,
|
|
14
|
+
isReady: acc.isReady || curr.isReady,
|
|
15
|
+
disabled: acc.disabled || curr.disabled,
|
|
16
|
+
hasErrors: acc.hasErrors || curr.errors && !isEmptyObject(curr.errors),
|
|
17
|
+
hasDirtyFields: acc.hasDirtyFields || curr.dirtyFields && !isEmptyObject(curr.dirtyFields),
|
|
18
|
+
hasTouchedFields: acc.hasTouchedFields || curr.touchedFields && !isEmptyObject(curr.touchedFields),
|
|
19
|
+
hasValidatingFields: acc.hasValidatingFields || curr.validatingFields && !isEmptyObject(curr.validatingFields),
|
|
20
|
+
submitCount: (acc.submitCount ?? 0) + (curr.submitCount ?? 0),
|
|
21
|
+
isMounted: acc.isMounted || curr.isMounted
|
|
22
|
+
}), {
|
|
23
|
+
isDirty: void 0,
|
|
24
|
+
isSubmitting: void 0,
|
|
25
|
+
isLoading: void 0,
|
|
26
|
+
isSubmitted: void 0,
|
|
27
|
+
isSubmitSuccessful: void 0,
|
|
28
|
+
isValidating: void 0,
|
|
29
|
+
isReady: void 0,
|
|
30
|
+
isValid: void 0,
|
|
31
|
+
disabled: void 0,
|
|
32
|
+
hasErrors: void 0,
|
|
33
|
+
hasDirtyFields: void 0,
|
|
34
|
+
hasTouchedFields: void 0,
|
|
35
|
+
hasValidatingFields: void 0,
|
|
36
|
+
submitCount: void 0,
|
|
37
|
+
isMounted: void 0
|
|
38
|
+
});
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/form/relay/get/useFormRelay.ts
|
|
41
|
+
const useFormRelayId = (formId) => useFormRelayContext().state[formId];
|
|
42
|
+
const useFormRelayGroup = (criteria) => {
|
|
43
|
+
const relayState = useFormRelayContext().state;
|
|
44
|
+
const state = getFormRelayedAggregatedByRelayedItem(getFormRelaysByCriteria(relayState, criteria).map(({ state }) => state));
|
|
45
|
+
const jsonState = JSON.stringify(state);
|
|
46
|
+
return React.useMemo(() => state, [jsonState]);
|
|
47
|
+
};
|
|
48
|
+
const getFormRelaysByCriteria = (relayState, criteria) => Object.values(relayState).filter(({ options, utils }) => !criteria || "groups" in criteria && criteria.groups.filter((group) => options.groups?.includes(group)).length || "predicate" in criteria && criteria.predicate({
|
|
49
|
+
groups: options.groups,
|
|
50
|
+
options: utils.options
|
|
51
|
+
}));
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/form/relay/get/grouper/context/index.ts
|
|
54
|
+
const { Provider: _FormRelayGrouperContextProvider, useRequired: _useFormRelayGrouperContext, useMaybe: _useFormRelayGrouperMaybeContext } = createContext();
|
|
55
|
+
//#endregion
|
|
56
|
+
//#region src/form/relay/get/grouper/useFirstFormStateGroup.ts
|
|
57
|
+
/**
|
|
58
|
+
* Use this when you don't (want to) know whether component is wrapped
|
|
59
|
+
* with RHF context, `FormRelayGrouperContext`, or `FormRelayContext`.
|
|
60
|
+
* Will return `FormRelayGroup`, regardless.
|
|
61
|
+
*
|
|
62
|
+
* Allows you to build naive components that are not tied to one specific context.
|
|
63
|
+
*/
|
|
64
|
+
const useFirstFormStateGroup = () => {
|
|
65
|
+
if (useRhfUtilsMaybeContext()) return getFormRelayedAggregatedByRelayedItem([useFormState()]);
|
|
66
|
+
const maybeRelayCtx = _useFormRelayGrouperMaybeContext();
|
|
67
|
+
if (maybeRelayCtx) return maybeRelayCtx.state;
|
|
68
|
+
return useFormRelayGroup();
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
export { FormRelayContextProvider, FormRelaySetter, useFirstFormStateGroup, useFormRelayGroup, useFormRelayId, useFormRelaySet };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { c as FormSubmitFieldErrors, t as RhfUtilsClientConfig } from "./RhfUtilsClientConfigType-CeOJzNAc.js";
|
|
2
|
+
import { TRPCClientErrorLike } from "@trpc/client";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { AnyTRPCRouter } from "@trpc/server";
|
|
5
|
+
|
|
6
|
+
//#region src/errors/trpc/makeOnSubmitTrpcClientErrorHandler.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* HOF that returns submit error handler for {@link RhfUtilsClientConfig.onSubmitErrorUnknown}.
|
|
9
|
+
*
|
|
10
|
+
* @param onError Fallback for handling non-TRPC errors.
|
|
11
|
+
* @returns FormSubmitError
|
|
12
|
+
*/
|
|
13
|
+
declare const makeOnSubmitTrpcClientErrorHandler: (onNotTrpcClientError: NonNullable<RhfUtilsClientConfig["onSubmitErrorUnknown"]>) => (error: unknown) => FormSubmitFieldErrors | undefined;
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/errors/trpc/trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer.d.ts
|
|
16
|
+
/**
|
|
17
|
+
* Schema that transforms {@link TRPCClientError} to RHF {@link FormSubmitFieldErrors}.
|
|
18
|
+
*/
|
|
19
|
+
declare const trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer: z.ZodEffects<z.ZodEffects<z.ZodPipeline<z.ZodEffects<z.ZodEffects<z.ZodType<TRPCClientErrorLike<AnyTRPCRouter>, z.ZodTypeDef, TRPCClientErrorLike<AnyTRPCRouter>>, string, TRPCClientErrorLike<AnyTRPCRouter>>, unknown, TRPCClientErrorLike<AnyTRPCRouter>>, z.ZodArray<z.ZodObject<{
|
|
20
|
+
code: z.ZodString;
|
|
21
|
+
message: z.ZodString;
|
|
22
|
+
path: z.ZodArray<z.ZodString, "many">;
|
|
23
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
24
|
+
code: z.ZodString;
|
|
25
|
+
message: z.ZodString;
|
|
26
|
+
path: z.ZodArray<z.ZodString, "many">;
|
|
27
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
28
|
+
code: z.ZodString;
|
|
29
|
+
message: z.ZodString;
|
|
30
|
+
path: z.ZodArray<z.ZodString, "many">;
|
|
31
|
+
}, z.ZodTypeAny, "passthrough">>, "many">>, (readonly [string, {
|
|
32
|
+
type: string;
|
|
33
|
+
message: string;
|
|
34
|
+
}])[], TRPCClientErrorLike<AnyTRPCRouter>>, FormSubmitFieldErrors, TRPCClientErrorLike<AnyTRPCRouter>>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { makeOnSubmitTrpcClientErrorHandler, trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { TRPCClientError } from "@trpc/client";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/errors/trpc/trpcClientErrorMessageSchema.ts
|
|
4
|
+
/**
|
|
5
|
+
* Schema for {@link TRPCClientError} message.
|
|
6
|
+
*
|
|
7
|
+
* (Sent from backend as JSON string.)
|
|
8
|
+
*/
|
|
9
|
+
const trpcClientErrorMessageSchema = z.object({
|
|
10
|
+
code: z.string(),
|
|
11
|
+
message: z.string(),
|
|
12
|
+
path: z.array(z.string())
|
|
13
|
+
}).passthrough();
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/errors/trpc/trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer.ts
|
|
16
|
+
/**
|
|
17
|
+
* Schema that transforms {@link TRPCClientError} to RHF {@link FormSubmitFieldErrors}.
|
|
18
|
+
*/
|
|
19
|
+
const trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer = z.custom((error) => error instanceof TRPCClientError).transform((error) => error.message).transform((json) => {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(json);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return [{
|
|
24
|
+
validation: "root",
|
|
25
|
+
code: "server",
|
|
26
|
+
message: json,
|
|
27
|
+
path: ["root"]
|
|
28
|
+
}];
|
|
29
|
+
}
|
|
30
|
+
}).pipe(z.array(trpcClientErrorMessageSchema)).transform((errors) => errors.map((error) => [error.path.join("."), {
|
|
31
|
+
type: error.code,
|
|
32
|
+
message: error.message
|
|
33
|
+
}])).transform((errors) => Object.fromEntries(errors));
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/errors/trpc/makeOnSubmitTrpcClientErrorHandler.ts
|
|
36
|
+
/**
|
|
37
|
+
* HOF that returns submit error handler for {@link RhfUtilsClientConfig.onSubmitErrorUnknown}.
|
|
38
|
+
*
|
|
39
|
+
* @param onError Fallback for handling non-TRPC errors.
|
|
40
|
+
* @returns FormSubmitError
|
|
41
|
+
*/
|
|
42
|
+
const makeOnSubmitTrpcClientErrorHandler = (onNotTrpcClientError) => (error) => {
|
|
43
|
+
if (error instanceof TRPCClientError) return trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer.parse(error);
|
|
44
|
+
return onNotTrpcClientError(error);
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { makeOnSubmitTrpcClientErrorHandler, trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer };
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paragrav/rhf-utils",
|
|
3
3
|
"author": "paragrav.dev",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.67.0",
|
|
5
5
|
"description": "Integration utilities for react-hook-form.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"files": [
|
|
9
|
-
"dist/
|
|
10
|
-
"dist/dts/*"
|
|
9
|
+
"dist/tsdown/*"
|
|
11
10
|
],
|
|
12
11
|
"exports": {
|
|
13
12
|
".": "./dist/tsdown/index.js",
|