react-form-action 2.0.1 → 2.2.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
@@ -328,7 +328,7 @@ export function UpdateUserForm() {
328
328
 
329
329
  Use the `createComponents(action)` helper to create components which use the ActionContext and have types bound to the action type.
330
330
 
331
- ### `<FielError>` Component
331
+ #### `<FielError>` Component
332
332
 
333
333
  ```tsx
334
334
  "use client";
@@ -338,7 +338,7 @@ import { Form, createComponents } from "react-form-action/client";
338
338
 
339
339
  import { authAction } from "./actions";
340
340
 
341
- export const signUp = authAction
341
+ export const signUpAction = authAction
342
342
  .input(
343
343
  z
344
344
  .object({
@@ -357,13 +357,13 @@ export const signUp = authAction
357
357
  return null;
358
358
  });
359
359
 
360
- // 🌟 The FieldError is now bound do the signUp input schema which allows autocompletion for its "name" prop
360
+ // 🌟 The FieldError is now bound do the signUpAction input schema which allows autocompletion for its "name" prop
361
361
  // ⚠️ Usable only with actions created with the formAction builder
362
- const { FieldError } = createComponents(signUp);
362
+ const { FieldError } = createComponents(signUpAction);
363
363
 
364
364
  export function SignUpForm() {
365
365
  return (
366
- <Action action={signUp} initialData={null}>
366
+ <Action action={signUpAction} initialData={null}>
367
367
  <Form>
368
368
  {/* 1️⃣ When the "name" prop is ommited, the top-level error will be rendered e.g.:
369
369
  "Passwords don't match" */}
@@ -378,23 +378,87 @@ export function SignUpForm() {
378
378
  }
379
379
  ```
380
380
 
381
+ #### `<Success>`
382
+
383
+ #### When children are JSX
384
+
385
+ ```tsx
386
+ import { Action, createComponents } from "react-form-action/client";
387
+
388
+ const { Success } = createComponents(signUpAction);
389
+
390
+ function MyForm() {
391
+ return (
392
+ <Action action={signUpAction}>
393
+ <Success>
394
+ {/* 👉 The message will render only after the action has succeeded */}
395
+ <p>You've been signed up!</p>
396
+ </Success>
397
+ </Action>
398
+ );
399
+ }
400
+ ```
401
+
402
+ #### When children is a render prop
403
+
404
+ ```tsx
405
+ import { createComponents } from "react-form-action/client";
406
+
407
+ const { Success } = createComponents(signUpAction);
408
+
409
+ function Label({children}: PropsWithChildren) {
410
+ return (
411
+ <Success>
412
+ {({ isSuccess, data }) => (
413
+ {/* 👉 With a render prop, the children are always mounted, regardles of the isSuccess flag */}
414
+ <label className={isSuccess ? "green" : ""}>
415
+ {children}
416
+ </label>
417
+ )}
418
+ </Success>
419
+ );
420
+ };
421
+ ```
422
+
381
423
  ### `<Pending>`
382
424
 
383
425
  Render children when the action is pending:
384
426
 
427
+ #### When children are JSX
428
+
385
429
  ```tsx
386
430
  import { Action, Pending } from "react-form-action/client";
387
431
 
388
432
  import { Spinner } from "./components";
389
433
 
390
- return function MyForm() {
434
+ function MyForm() {
391
435
  return (
392
436
  <Action action={action}>
393
437
  {/* 👉 Unlike the React.useFormStatus() hook, we don't need here the <form> element at all. */}
394
438
  <Pending>
439
+ {/* 👉 The spinner will UNMOUNT when the action is NOT pending */}
395
440
  <Spinner />
396
441
  </Pending>
397
442
  </Action>
398
443
  );
444
+ }
445
+ ```
446
+
447
+ #### When children is a render prop
448
+
449
+ ```tsx
450
+ import { Pending } from "react-form-action/client";
451
+
452
+ function SubmitButton() {
453
+ return (
454
+ <Pending>
455
+ {({ isPending }) => (
456
+ {/* 👉 With a render prop, the children are always mounted, regardles of the isPending flag */}
457
+ <button type="submit" disabled={isPending}>
458
+ {isPending ? "Submitting..." : "Submit"}
459
+ </button>
460
+ )}
461
+ </Pending>
462
+ );
399
463
  };
400
464
  ```
package/dist/client.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { PropsWithChildren, JSX } from 'react';
3
- import { b as FormAction, A as ActionState, a as InitialState, I as InvalidState, F as FailureState, S as SuccessState } from './createFormAction-277e6e21.js';
3
+ import { F as FormAction, A as ActionState, I as InitialState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-CX4Fk5xA.mjs';
4
4
  import { ZodFormattedError } from 'zod';
5
- import { RenderProp } from 'react-render-prop-type';
5
+ import { RenderProp, RP } from 'react-render-prop-type';
6
6
  import { useFormStatus } from 'react-dom';
7
7
 
8
8
  type ActionProps<Data, Error, ValidationError> = PropsWithChildren<{
@@ -61,9 +61,16 @@ declare function ZodFieldError<Errors extends ZodFormattedError<any>>({ errors,
61
61
  * Creates a typed components for actions created with the formAction builder.
62
62
  */
63
63
  declare function createComponents<Data, Error, ValidationError extends ZodFormattedError<any>>(action: FormAction<Data, Error, ValidationError>): {
64
- FieldError: ({ name, }: React__default.PropsWithChildren<{
65
- name?: "" | InferZodErrorPaths<ValidationError> | undefined;
64
+ FieldError: ({ name, }: PropsWithChildren<{
65
+ name?: "" | InferZodErrorPaths<ValidationError>;
66
66
  }>) => false | React__default.JSX.Element;
67
+ Success: ({ children, }: PropsWithChildren | RP<{
68
+ isSuccess: false;
69
+ data: Data | null;
70
+ } | {
71
+ isSuccess: true;
72
+ data: Data;
73
+ }>) => React__default.ReactNode;
67
74
  };
68
75
 
69
76
  declare function FormStatus({ children, }: RenderProp<ReturnType<typeof useFormStatus>>): React.ReactNode;
@@ -71,6 +78,8 @@ declare function FormStatus({ children, }: RenderProp<ReturnType<typeof useFormS
71
78
  /**
72
79
  * Conditionally renders the children, when the form action is in the "pending" state.
73
80
  */
74
- declare function Pending({ children }: PropsWithChildren): React.ReactNode;
81
+ declare function Pending({ children, }: PropsWithChildren | RP<{
82
+ isPending: boolean;
83
+ }>): React.ReactNode;
75
84
 
76
- export { Action, ActionContextState, ActionProps, Form, FormProps, FormStatus, InferZodErrorPaths, Paths, Pending, ZodFieldError, ZodFieldErrorProps, createComponents, useActionContext };
85
+ export { Action, type ActionContextState, type ActionProps, Form, type FormProps, FormStatus, type InferZodErrorPaths, type Paths, Pending, ZodFieldError, type ZodFieldErrorProps, createComponents, useActionContext };
package/dist/client.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{a as c}from"./chunk-HL47DG4L.mjs";import f from"react";import{createContext as E,use as x}from"react";import{useActionState as S}from"react";var p={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},m=E(null);function a(t){let o=x(m);if(!o)throw new Error("ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?");return o}function v({children:t,action:o,initialData:e,permalink:n}){let[r,i,s]=S(o,c(e),n),d=r.type==="initial"?{...r,...p,action:i,isPending:s,isInitial:!0}:r.type==="invalid"?{...r,...p,action:i,isPending:s,isInvalid:!0}:r.type==="failure"?{...r,...p,action:i,isPending:s,isFailure:!0}:{...r,...p,action:i,isPending:s,isSuccess:!0};return f.createElement(m,{value:d},t)}import y,{startTransition as A}from"react";function V({autoReset:t=!1,...o}){let{action:e}=a();return y.createElement("form",{...t?{action:e}:{onSubmit:r=>{r.preventDefault();let i=r.currentTarget;A(()=>{e(new FormData(i))})}},...o})}import h from"react";import l from"react";var F=".",P=Object.freeze({_errors:Object.freeze([])});function u({errors:t,name:o="",children:e=({errors:n})=>l.createElement(l.Fragment,null,n[0])}){if(o.length===0)return e({errors:t._errors});let n=o.split(F),r=t;for(;n.length;){let i=n.shift();r=r[i]??P}return e({errors:r._errors})}function $(t){function o({name:e}){let{isInvalid:n,validationError:r}=a(t);return n&&h.createElement(u,{errors:r,name:e})}return{FieldError:o}}import{useFormStatus as C}from"react-dom";function X({children:t}){return t(C())}function q({children:t}){let{isPending:o}=a();return o&&t}export{v as Action,V as Form,X as FormStatus,q as Pending,u as ZodFieldError,$ as createComponents,a as useActionContext};
1
+ "use client";import{a as c}from"./chunk-HL47DG4L.mjs";import f from"react";import{createContext as E,use as x}from"react";import{useActionState as y}from"react";var p={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},u=E(null);function a(t){let o=x(u);if(!o)throw new Error("ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?");return o}function g({children:t,action:o,initialData:i,permalink:e}){let[r,n,s]=y(o,c(i),e),d=r.type==="initial"?{...r,...p,action:n,isPending:s,isInitial:!0}:r.type==="invalid"?{...r,...p,action:n,isPending:s,isInvalid:!0}:r.type==="failure"?{...r,...p,action:n,isPending:s,isFailure:!0}:{...r,...p,action:n,isPending:s,isSuccess:!0};return f.createElement(u,{value:d},t)}import S,{startTransition as A}from"react";function R({autoReset:t=!1,...o}){let{action:i}=a();return S.createElement("form",{...t?{action:i}:{onSubmit:r=>{r.preventDefault();let n=r.currentTarget;A(()=>{i(new FormData(n))})}},...o})}import C from"react";import m from"react";var F=".",P=Object.freeze({_errors:Object.freeze([])});function l({errors:t,name:o="",children:i=({errors:e})=>m.createElement(m.Fragment,null,e[0])}){if(o.length===0)return i({errors:t._errors});let e=o.split(F),r=t;for(;e.length;){let n=e.shift();r=r[n]??P}return i({errors:r._errors})}function $(t){function o({name:e}){let{isInvalid:r,validationError:n}=a(t);return r&&C.createElement(l,{errors:n,name:e})}function i({children:e}){let{isSuccess:r,data:n}=a(t);return typeof e=="function"?e(r?{isSuccess:r,data:n}:{isSuccess:r,data:n}):r&&e}return{FieldError:o,Success:i}}import{useFormStatus as h}from"react-dom";function X({children:t}){return t(h())}function q({children:t}){let{isPending:o}=a();return typeof t=="function"?t({isPending:o}):o&&t}export{g as Action,R as Form,X as FormStatus,q as Pending,l as ZodFieldError,$ as createComponents,a as useActionContext};
@@ -31,4 +31,4 @@ declare function createFormAction<Data, Error = Data, ValidationError = Record<s
31
31
  invalid: (validationError: ValidationError) => InvalidState<ValidationError>;
32
32
  }) => FormAction<Data, Error, ValidationError, Payload>): (state: ActionState<Data, Error, ValidationError>, payload: Payload) => Promise<ActionState<Data, Error, ValidationError>>;
33
33
 
34
- export { ActionState as A, FailureState as F, InvalidState as I, SuccessState as S, InitialState as a, FormAction as b, createFormAction as c, initial as i };
34
+ export { type ActionState as A, type FormAction as F, type InitialState as I, type SuccessState as S, type InvalidState as a, type FailureState as b, createFormAction as c, initial as i };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as ActionState, I as InvalidState, F as FailureState, S as SuccessState } from './createFormAction-277e6e21.js';
2
- export { b as FormAction, a as InitialState, c as createFormAction, i as initial } from './createFormAction-277e6e21.js';
1
+ import { A as ActionState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-CX4Fk5xA.mjs';
2
+ export { F as FormAction, I as InitialState, c as createFormAction, i as initial } from './createFormAction-CX4Fk5xA.mjs';
3
3
  import { ZodTypeAny, ZodType, ZodObject, ZodRawShape, objectUtil, z, ZodSchema, ZodEffects } from 'zod';
4
4
 
5
5
  declare const emptyInput: unique symbol;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-form-action",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "State management helpers for the react form actions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,14 +23,14 @@
23
23
  ".": {
24
24
  "import": "./dist/index.mjs",
25
25
  "module": "./dist/index.mjs",
26
- "default": "./dist/index.mjs",
27
- "types": "./dist/index.d.mts"
26
+ "types": "./dist/index.d.mts",
27
+ "default": "./dist/index.mjs"
28
28
  },
29
29
  "./client": {
30
30
  "import": "./dist/client.mjs",
31
31
  "module": "./dist/client.mjs",
32
- "default": "./dist/client.mjs",
33
- "types": "./dist/client.d.mts"
32
+ "types": "./dist/client.d.mts",
33
+ "default": "./dist/client.mjs"
34
34
  }
35
35
  },
36
36
  "keywords": [
@@ -58,14 +58,14 @@
58
58
  "@types/react": "^19.0.0",
59
59
  "@types/react-dom": "^19.0.1",
60
60
  "@vitejs/plugin-react": "^4.3.4",
61
- "happy-dom": "^15.11.7",
62
- "npm-check-updates": "^17.1.11",
61
+ "happy-dom": "^16.0.0",
62
+ "npm-check-updates": "^17.1.12",
63
63
  "prettier": "^3.4.2",
64
64
  "react": "^19.0.0",
65
65
  "react-dom": "^19.0.0",
66
- "react-render-prop-type": "^0.1.0",
67
- "tsup": "^7.2.0",
68
- "typescript": "^5.2.2",
66
+ "react-render-prop-type": "^1.0.0",
67
+ "tsup": "^8.3.5",
68
+ "typescript": "^5.7.2",
69
69
  "vitest": "^1.3.1",
70
70
  "zod": "^3.23.8",
71
71
  "zod-form-data": "^2.0.2"