react-form-action 2.9.2 → 2.10.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 CHANGED
@@ -22,6 +22,7 @@ End-to-end typesafe success, error & validation state control for Next.js form a
22
22
  - ✅ The `React.useActionState()` accessible via the `useActionContext()` hook.
23
23
  - ✅ Computes progress flags like `isInvalid`, `isSuccess` based on the envelope type.
24
24
  - ✅ Binds the action with the arguments from the _args_ prop.
25
+ - ✅ Has an optional `validate` prop to validate the form data client-side before calling the server action.
25
26
 
26
27
  **Context-bound `<Form />` component**
27
28
 
package/dist/client.d.mts CHANGED
@@ -7,11 +7,13 @@ type ActionProps<Data, Error, ValidationError, Arguments extends unknown[] = []>
7
7
  args: Arguments;
8
8
  initialData: Data;
9
9
  permalink?: string;
10
+ validate?: (payload: FormData) => null | ValidationError;
10
11
  } : {
11
12
  action: FormAction<Data, Error, ValidationError, FormData, Arguments>;
12
13
  initialData: Data;
13
14
  args?: undefined;
14
15
  permalink?: string;
16
+ validate?: (payload: FormData) => null | ValidationError;
15
17
  }>;
16
18
  type ActionStatusFlags<T extends ActionState<unknown, unknown, unknown>["type"] | unknown = unknown> = {
17
19
  isInitial: T extends "initial" ? true : false;
@@ -34,7 +36,7 @@ type SpreadActionContext<Data = unknown, Error = unknown, ValidationError = unkn
34
36
  * A hook to consume the form action state from the context.
35
37
  */
36
38
  declare function useActionContext<Data, Error, ValidationError, Args extends unknown[] = []>(action?: FormAction<Data, Error, ValidationError, FormData, Args>): SpreadActionContext<Data, Error, ValidationError>;
37
- declare function Action<Data, Error, ValidationError, Args extends unknown[] = []>({ children, action: formAction, initialData, args, permalink }: ActionProps<Data, Error, ValidationError, Args>): React$1.JSX.Element;
39
+ declare function Action<Data, Error, ValidationError, Args extends unknown[] = []>({ children, action: formAction, initialData, args, permalink, validate }: ActionProps<Data, Error, ValidationError, Args>): React$1.JSX.Element;
38
40
  //#endregion
39
41
  //#region src/Form.d.ts
40
42
  type FormProps = Omit<JSX.IntrinsicElements["form"], "action"> & {
package/dist/client.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{n as e}from"./createFormAction-BwMYAzm2.mjs";import t,{createContext as n,startTransition as r,use as i,useActionState as a}from"react";const o={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},s=n(null);function c(e){let t=i(s);if(!t)throw Error(`ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?`);return t}function l({children:n,action:r,initialData:i,args:c,permalink:l}){let[u,d,f]=a(c?r.bind(null,...c):r,e(i),l),p=u.type===`initial`?{...u,...o,action:d,isPending:f,isInitial:!0}:u.type===`invalid`?{...u,...o,action:d,isPending:f,isInvalid:!0}:u.type===`failure`?{...u,...o,action:d,isPending:f,isFailure:!0}:{...u,...o,action:d,isPending:f,isSuccess:!0};return t.createElement(s,{value:p},n)}function u({autoReset:e=!1,...n}){let{action:i}=c(),a=e?{action:i}:{onSubmit:e=>{e.preventDefault();let t=e.currentTarget;r(()=>{i(new FormData(t))})}};return t.createElement(`form`,{...a,...n})}const d=Object.freeze({errors:Object.freeze([])});function f({errors:e,name:n,children:r=({error:e})=>t.createElement(t.Fragment,null,e)}){if(n.length===0)return r({name:n,error:e.errors[0],errors:e.errors});let i=n.split(`.`),a=e;for(;i.length;){let e=i.shift();if(!a.properties){a=d;break}a=a.properties[e]??d}return r({name:n,error:a.errors[0],errors:a.errors})}function p(e){function n({name:n,children:r}){let{isInvalid:i,validationError:a}=c(e);return t.createElement(f,{errors:a??d,name:n},r??(({error:e})=>i&&t.createElement(t.Fragment,null,e)))}function r({children:t}){let{isSuccess:n,data:r}=c(e);return typeof t==`function`?t({isSuccess:n,data:r}):n&&t}function i({children:t}){let{isInvalid:n,validationError:r}=c(e);return typeof t==`function`?t({isInvalid:n,validationError:r}):n&&t}return{FieldError:n,Success:r,Invalid:i}}function m({children:e}){let{isPending:t}=c();return typeof e==`function`?e({isPending:t}):t&&e}export{l as Action,u as Form,m as Pending,f as ZodFieldError,p as createComponents,d as noError,c as useActionContext};
1
+ "use client";import{n as e,t}from"./createFormAction-BwMYAzm2.mjs";import n,{createContext as r,startTransition as i,use as a,useActionState as o}from"react";const s={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},c=r(null);function l(e){let t=a(c);if(!t)throw Error(`ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?`);return t}function u({children:r,action:i,initialData:a,args:l,permalink:u,validate:d}){let f=l?i.bind(null,...l):i,[p,m,h]=o(async(e,n)=>{if(d){let r=await t(({invalid:e,success:t})=>async(n,r)=>{let i=d(r);return i?e(i):t(!0)})(e,n);if(r.type===`invalid`)return r}return f(e,n)},e(a),u),g=p.type===`initial`?{...p,...s,action:m,isPending:h,isInitial:!0}:p.type===`invalid`?{...p,...s,action:m,isPending:h,isInvalid:!0}:p.type===`failure`?{...p,...s,action:m,isPending:h,isFailure:!0}:{...p,...s,action:m,isPending:h,isSuccess:!0};return n.createElement(c,{value:g},r)}function d({autoReset:e=!1,...t}){let{action:r}=l(),a=e?{action:r}:{onSubmit:e=>{e.preventDefault();let t=e.currentTarget;i(()=>{r(new FormData(t))})}};return n.createElement(`form`,{...a,...t})}const f=Object.freeze({errors:Object.freeze([])});function p({errors:e,name:t,children:r=({error:e})=>n.createElement(n.Fragment,null,e)}){if(t.length===0)return r({name:t,error:e.errors[0],errors:e.errors});let i=t.split(`.`),a=e;for(;i.length;){let e=i.shift();if(!a.properties){a=f;break}a=a.properties[e]??f}return r({name:t,error:a.errors[0],errors:a.errors})}function m(e){function t({name:t,children:r}){let{isInvalid:i,validationError:a}=l(e);return n.createElement(p,{errors:a??f,name:t},r??(({error:e})=>i&&n.createElement(n.Fragment,null,e)))}function r({children:t}){let{isSuccess:n,data:r}=l(e);return typeof t==`function`?t({isSuccess:n,data:r}):n&&t}function i({children:t}){let{isInvalid:n,validationError:r}=l(e);return typeof t==`function`?t({isInvalid:n,validationError:r}):n&&t}return{FieldError:t,Success:r,Invalid:i}}function h({children:e}){let{isPending:t}=l();return typeof e==`function`?e({isPending:t}):t&&e}export{u as Action,d as Form,h as Pending,p as ZodFieldError,m as createComponents,f as noError,l as useActionContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-form-action",
3
- "version": "2.9.2",
3
+ "version": "2.10.0",
4
4
  "description": "State management helpers for the react form actions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -70,7 +70,7 @@
70
70
  "tsdown": "^0.22.12",
71
71
  "typescript": "^6.0.3",
72
72
  "vitest": "^4.1.10",
73
- "zod": "^3.25.0",
73
+ "zod": "^4.4.3",
74
74
  "zod-form-data": "^3.0.3"
75
75
  }
76
76
  }