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
|
-
|
|
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
|
|
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
|
|
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(
|
|
362
|
+
const { FieldError } = createComponents(signUpAction);
|
|
363
363
|
|
|
364
364
|
export function SignUpForm() {
|
|
365
365
|
return (
|
|
366
|
-
<Action action={
|
|
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
|
-
|
|
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 {
|
|
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, }:
|
|
65
|
-
name?: "" | InferZodErrorPaths<ValidationError
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
2
|
-
export {
|
|
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
|
|
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
|
-
"
|
|
27
|
-
"
|
|
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
|
-
"
|
|
33
|
-
"
|
|
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": "^
|
|
62
|
-
"npm-check-updates": "^17.1.
|
|
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": "^
|
|
67
|
-
"tsup": "^
|
|
68
|
-
"typescript": "^5.
|
|
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"
|