react-form-action 2.6.0 β 2.8.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 +26 -19
- package/dist/client.d.mts +20 -5
- package/dist/client.mjs +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ import { formAction } from "react-form-action";
|
|
|
49
49
|
import { z } from "zod";
|
|
50
50
|
|
|
51
51
|
export const subscribeAction = formAction
|
|
52
|
-
.input(z.object({ email: z.
|
|
52
|
+
.input(z.object({ email: z.email() }))
|
|
53
53
|
.run(async ({ input }) => {
|
|
54
54
|
return input.email;
|
|
55
55
|
});
|
|
@@ -138,7 +138,7 @@ const i18nMiddleware = async () => {
|
|
|
138
138
|
const authAction = formAction
|
|
139
139
|
.use(i18nMiddleware)
|
|
140
140
|
.use(async ({ ctx: { t } }) =>
|
|
141
|
-
console.log("π context enhanced by previous middlewares π", t)
|
|
141
|
+
console.log("π context enhanced by previous middlewares π", t),
|
|
142
142
|
)
|
|
143
143
|
.error(async ({ error }) => {
|
|
144
144
|
if (error instanceof DbError) {
|
|
@@ -151,7 +151,7 @@ const authAction = formAction
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
export const signIn = authAction
|
|
154
|
-
.input(z.object({ email: z.
|
|
154
|
+
.input(z.object({ email: z.email() }))
|
|
155
155
|
// π extend the previous input (only without refinements and transforms)
|
|
156
156
|
.input(z.object({ password: z.string() }))
|
|
157
157
|
.run(async ({ ctx: { t }, input: { email, password } }) => {
|
|
@@ -166,14 +166,14 @@ export const signUp = authAction
|
|
|
166
166
|
.input(
|
|
167
167
|
z
|
|
168
168
|
.object({
|
|
169
|
-
email: z.
|
|
169
|
+
email: z.email(),
|
|
170
170
|
password: z.string(),
|
|
171
171
|
confirm: z.string(),
|
|
172
172
|
})
|
|
173
173
|
.refine((data) => data.password === data.confirm, {
|
|
174
174
|
message: "Passwords don't match",
|
|
175
175
|
path: ["confirm"],
|
|
176
|
-
})
|
|
176
|
+
}),
|
|
177
177
|
) // if using refinement, only one input call is permited, as schema with ZodEffects is not extendable.
|
|
178
178
|
.run(async ({ ctx: { t }, input: { email, password } }) => {
|
|
179
179
|
// π passwords match!
|
|
@@ -193,35 +193,42 @@ export const signUp = authAction
|
|
|
193
193
|
The `formAction` builder supports action arguments binding:
|
|
194
194
|
|
|
195
195
|
```ts
|
|
196
|
-
// app/update-user/[userId]/action.tsx
|
|
196
|
+
// app/[locale]/update-user/[userId]/action.tsx
|
|
197
197
|
import { formAction } from "react-form-action";
|
|
198
198
|
|
|
199
199
|
export const updateUser = formAction
|
|
200
|
-
.args([z.string().uuid()])
|
|
200
|
+
.args([z.string().uuid(), z.enum("fr", "en")])
|
|
201
201
|
.run(async ({ args: [userId] }) => {
|
|
202
202
|
return userId;
|
|
203
203
|
// ^? string
|
|
204
|
+
})
|
|
205
|
+
.error(({ args: [_, locale] }) => {
|
|
206
|
+
return locale === "fr"
|
|
207
|
+
? "Γchec de la mise Γ jour de l'utilisateur"
|
|
208
|
+
: "Failed to update user";
|
|
204
209
|
});
|
|
205
210
|
```
|
|
206
211
|
|
|
207
212
|
```tsx
|
|
208
|
-
// app/update-user/[userId]/page.tsx
|
|
213
|
+
// app/[locale]/update-user/[userId]/page.tsx
|
|
209
214
|
import { Action } from "react-form-action/client";
|
|
210
215
|
|
|
216
|
+
import { locale as localeParam } from "next/root-params";
|
|
211
217
|
import { updateUser } from "./action";
|
|
212
218
|
import { UpdateUserForm } from "./form";
|
|
213
219
|
|
|
214
220
|
export default function Page({
|
|
215
221
|
params,
|
|
216
|
-
}: {
|
|
217
|
-
|
|
218
|
-
}) {
|
|
222
|
+
}: PageProps<"/[locale]/update-user/[userId]">) {
|
|
223
|
+
const locale = await localeParam();
|
|
219
224
|
const { userId } = await params;
|
|
220
225
|
|
|
221
|
-
const action = updateUser.bind(null, userId);
|
|
222
|
-
|
|
223
226
|
return (
|
|
224
|
-
<Action
|
|
227
|
+
<Action
|
|
228
|
+
action={updateUser}
|
|
229
|
+
args={[userId, await localeParam()]}
|
|
230
|
+
initialData=""
|
|
231
|
+
>
|
|
225
232
|
<SubscribeForm />
|
|
226
233
|
</Action>
|
|
227
234
|
);
|
|
@@ -291,7 +298,7 @@ export const updateUser = createFormAction<
|
|
|
291
298
|
|
|
292
299
|
return failure({ message: "Failed to update user." });
|
|
293
300
|
}
|
|
294
|
-
}
|
|
301
|
+
},
|
|
295
302
|
);
|
|
296
303
|
```
|
|
297
304
|
|
|
@@ -301,7 +308,7 @@ The action creator supports arguments binding:
|
|
|
301
308
|
export const updateUser = createFormAction(
|
|
302
309
|
(
|
|
303
310
|
{ success, failure, invalid },
|
|
304
|
-
userId: string /* Here you can specify multiple arguments
|
|
311
|
+
userId: string /* Here you can specify multiple arguments */,
|
|
305
312
|
) =>
|
|
306
313
|
async (prevState, formData) => {
|
|
307
314
|
try {
|
|
@@ -327,7 +334,7 @@ export const updateUser = createFormAction(
|
|
|
327
334
|
} catch (error) {
|
|
328
335
|
// handle error
|
|
329
336
|
}
|
|
330
|
-
}
|
|
337
|
+
},
|
|
331
338
|
);
|
|
332
339
|
|
|
333
340
|
// call bind as usuall, the "123" becomes the "userId"
|
|
@@ -421,7 +428,7 @@ export const signUpAction = authAction
|
|
|
421
428
|
z
|
|
422
429
|
.object({
|
|
423
430
|
user: z.object({
|
|
424
|
-
email: z.
|
|
431
|
+
email: z.email(),
|
|
425
432
|
name: z.string(),
|
|
426
433
|
}),
|
|
427
434
|
password: z.string().min(8),
|
|
@@ -429,7 +436,7 @@ export const signUpAction = authAction
|
|
|
429
436
|
})
|
|
430
437
|
.refine((data) => data.password === data.confirm, {
|
|
431
438
|
message: "Passwords don't match",
|
|
432
|
-
})
|
|
439
|
+
}),
|
|
433
440
|
)
|
|
434
441
|
.run(async ({ ctx, input }) => {
|
|
435
442
|
return null;
|
package/dist/client.d.mts
CHANGED
|
@@ -3,10 +3,16 @@ import React__default, { PropsWithChildren, JSX } from 'react';
|
|
|
3
3
|
import { F as FormAction, A as ActionState, I as InitialState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-DjhozgiG.mjs';
|
|
4
4
|
import { $ZodErrorTree } from 'zod/v4/core';
|
|
5
5
|
|
|
6
|
-
type ActionProps<Data, Error, ValidationError> = PropsWithChildren<{
|
|
7
|
-
action: FormAction<Data, Error, ValidationError>;
|
|
6
|
+
type ActionProps<Data, Error, ValidationError, Arguments extends unknown[] = []> = PropsWithChildren<Arguments extends [unknown] ? {
|
|
7
|
+
action: FormAction<Data, Error, ValidationError, FormData, Arguments>;
|
|
8
|
+
args: Arguments;
|
|
8
9
|
initialData: Data;
|
|
9
10
|
permalink?: string;
|
|
11
|
+
} : {
|
|
12
|
+
action: FormAction<Data, Error, ValidationError, FormData, Arguments>;
|
|
13
|
+
initialData: Data;
|
|
14
|
+
args?: undefined;
|
|
15
|
+
permalink?: string;
|
|
10
16
|
}>;
|
|
11
17
|
type ActionStatusFlags<T extends ActionState<unknown, unknown, unknown>["type"] | unknown = unknown> = {
|
|
12
18
|
isInitial: T extends "initial" ? true : false;
|
|
@@ -28,8 +34,8 @@ type SpreadActionContext<Data = unknown, Error = unknown, ValidationError = unkn
|
|
|
28
34
|
/**
|
|
29
35
|
* A hook to consume the form action state from the context.
|
|
30
36
|
*/
|
|
31
|
-
declare function useActionContext<Data, Error, ValidationError>(action?: FormAction<Data, Error, ValidationError>): SpreadActionContext<Data, Error, ValidationError>;
|
|
32
|
-
declare function Action<Data, Error, ValidationError>({ children, action: formAction, initialData, permalink, }: ActionProps<Data, Error, ValidationError>): React__default.JSX.Element;
|
|
37
|
+
declare function useActionContext<Data, Error, ValidationError, Args extends unknown[] = []>(action?: FormAction<Data, Error, ValidationError, FormData, Args>): SpreadActionContext<Data, Error, ValidationError>;
|
|
38
|
+
declare function Action<Data, Error, ValidationError, Args extends unknown[] = []>({ children, action: formAction, initialData, args, permalink, }: ActionProps<Data, Error, ValidationError, Args>): React__default.JSX.Element;
|
|
33
39
|
|
|
34
40
|
type FormProps = Omit<JSX.IntrinsicElements["form"], "action"> & {
|
|
35
41
|
/**
|
|
@@ -65,7 +71,7 @@ declare function ZodFieldError<Errors extends $ZodErrorTree<object>, Name extend
|
|
|
65
71
|
/**
|
|
66
72
|
* Creates a typed components for actions created with the formAction builder.
|
|
67
73
|
*/
|
|
68
|
-
declare function createComponents<Data, Error, ValidationError extends $ZodErrorTree<any
|
|
74
|
+
declare function createComponents<Data, Error, ValidationError extends $ZodErrorTree<any>, Args extends unknown[] = []>(action: FormAction<Data, Error, ValidationError, FormData, Args>): {
|
|
69
75
|
FieldError: <Name extends "" | InferZodErrorPaths<ValidationError>>({ name, children, }: {
|
|
70
76
|
name: Name;
|
|
71
77
|
children?: (props: ZodFieldErrorChildrenProps<Name>) => React__default.ReactNode;
|
|
@@ -79,6 +85,15 @@ declare function createComponents<Data, Error, ValidationError extends $ZodError
|
|
|
79
85
|
data: Data;
|
|
80
86
|
}) => React__default.ReactNode;
|
|
81
87
|
}) => React__default.ReactNode;
|
|
88
|
+
Invalid: ({ children, }: PropsWithChildren | {
|
|
89
|
+
children?: (props: {
|
|
90
|
+
isInvalid: false;
|
|
91
|
+
validationError: null;
|
|
92
|
+
} | {
|
|
93
|
+
isInvalid: true;
|
|
94
|
+
validationError: ValidationError;
|
|
95
|
+
}) => React__default.ReactNode;
|
|
96
|
+
}) => React__default.ReactNode;
|
|
82
97
|
};
|
|
83
98
|
|
|
84
99
|
/**
|
package/dist/client.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{a as
|
|
1
|
+
"use client";import{a as f}from"./chunk-LPB4R2UB.mjs";import S from"react";import{useActionState as F,createContext as P,use as y}from"react";var c={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},E=P(null);function s(e){let t=y(E);if(!t)throw new Error("ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?");return t}function v({children:e,action:t,initialData:a,args:i,permalink:r}){let o=i?t.bind(null,...i):t,[n,l,d]=F(o,f(a),r),u=n.type==="initial"?{...n,...c,action:l,isPending:d,isInitial:!0}:n.type==="invalid"?{...n,...c,action:l,isPending:d,isInvalid:!0}:n.type==="failure"?{...n,...c,action:l,isPending:d,isFailure:!0}:{...n,...c,action:l,isPending:d,isSuccess:!0};return S.createElement(E,{value:u},e)}import h,{startTransition as g}from"react";function I({autoReset:e=!1,...t}){let{action:a}=s();return h.createElement("form",{...e?{action:a}:{onSubmit:r=>{r.preventDefault();let o=r.currentTarget;g(()=>{a(new FormData(o))})}},...t})}import m from"react";import x from"react";var C=".",p=Object.freeze({errors:Object.freeze([])});function A({errors:e,name:t,children:a=({error:i})=>x.createElement(x.Fragment,null,i)}){if(t.length===0)return a({name:t,error:e.errors[0],errors:e.errors});let i=t.split(C),r=e;for(;i.length;){let o=i.shift();if(!r.properties){r=p;break}r=r.properties[o]??p}return a({name:t,error:r.errors[0],errors:r.errors})}function J(e){function t({name:r,children:o}){let{isInvalid:n,validationError:l}=s(e);return m.createElement(A,{errors:l??p,name:r},o??(({error:u})=>n&&m.createElement(m.Fragment,null,u)))}function a({children:r}){let{isSuccess:o,data:n}=s(e);return typeof r=="function"?r(o?{isSuccess:o,data:n}:{isSuccess:o,data:n}):o&&r}function i({children:r}){let{isInvalid:o,validationError:n}=s(e);return typeof r=="function"?r(o?{isInvalid:o,validationError:n}:{isInvalid:o,validationError:n}):o&&r}return{FieldError:t,Success:a,Invalid:i}}function q({children:e}){let{isPending:t}=s();return typeof e=="function"?e({isPending:t}):t&&e}export{v as Action,I as Form,q as Pending,A as ZodFieldError,J as createComponents,p as noError,s as useActionContext};
|
package/dist/index.d.mts
CHANGED
|
@@ -9,9 +9,10 @@ type Flatten<T> = Identity<{
|
|
|
9
9
|
[K in keyof T]: T[K];
|
|
10
10
|
}>;
|
|
11
11
|
type Identity<T> = T;
|
|
12
|
-
type ErrorHandler<Context, Err> = (params: {
|
|
12
|
+
type ErrorHandler<Context, Err, Args extends ZodTuple> = (params: {
|
|
13
13
|
error: unknown;
|
|
14
14
|
ctx: Context;
|
|
15
|
+
args: z.infer<Args>;
|
|
15
16
|
}) => Promise<Err>;
|
|
16
17
|
type InitialContext = Record<"formData", FormData>;
|
|
17
18
|
/**
|
|
@@ -60,7 +61,7 @@ type FormActionBuilder<Schema extends ZodType | EmptyInput, TErr = unknown, Cont
|
|
|
60
61
|
* @param processError A function which receives action's errors.
|
|
61
62
|
* @returns FormActionBuilder
|
|
62
63
|
*/
|
|
63
|
-
error: <TErr>(processError: ErrorHandler<Context, TErr>) => FormActionBuilder<Schema, TErr, Context, Args>;
|
|
64
|
+
error: <TErr>(processError: ErrorHandler<Context, TErr, Args>) => FormActionBuilder<Schema, TErr, Context, Args>;
|
|
64
65
|
};
|
|
65
66
|
declare const formAction: FormActionBuilder<typeof emptyInput, unknown, InitialContext, z.ZodTuple<[], null>>;
|
|
66
67
|
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as h,b as f}from"./chunk-LPB4R2UB.mjs";import{z as T}from"zod/v4";import{zfd as
|
|
1
|
+
import{a as h,b as f}from"./chunk-LPB4R2UB.mjs";import{z as T}from"zod/v4";import{zfd as C}from"zod-form-data";var m=Symbol();function c(e,u=[],n,a){async function A(t){let r={formData:t};for(let d of u){let i=await d({ctx:r});r={...r,...i}}return r}return{args(t){return c(e,u,n,T.tuple(t))},input(t){if(e===m)return c(t,u,n,a);if(e._zod.def.checks)throw new Error("Previous input is not augmentable because it contains an effect.");if(t._zod.def.checks)throw new Error("Your input contains effect which prevents merging it with the previous inputs.");if(e._zod.def.type==="object"){let r=T.object({...e.shape,...t.shape});return c(r,u)}else throw Error("Merging inputs works only for object schemas without effects.")},use(t){return c(e,[...u,t],n,a)},error(t){return c(e,u,t,a)},run:e===m?t=>f(({success:r,failure:d,invalid:i},...s)=>async(E,g)=>{let p=await A(g);if(a){let o=a.safeParse(s);if(!o.success)return i(T.treeifyError(o.error))}try{return r(await t({args:s,ctx:p}))}catch(o){if(n)return d(await n({args:s,error:o,ctx:p}));throw o}}):e===m?void 0:t=>f(({success:r,failure:d,invalid:i},...s)=>{let E=C.formData(e);return async(g,p)=>{let o=await A(p);if(a){let x=a.safeParse(s);if(!x.success)return i(T.treeifyError(x.error))}let l=E.safeParse(p);if(!l.success)return i(T.treeifyError(l.error));let y=l.data;try{return r(await t({args:s,input:y,ctx:o}))}catch(x){if(n)return d(await n({args:s,error:x,ctx:o}));throw x}}})}}var j=c(m);export{f as createFormAction,j as formAction,h as initial};
|