Skip to content

Commit 3b000e6

Browse files
authored
Add disabled prop (#10)
1 parent 78227c7 commit 3b000e6

File tree

7 files changed

+92
-62
lines changed

7 files changed

+92
-62
lines changed

package-lock.json

Lines changed: 53 additions & 53 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"playwright": "^1.49.1",
4141
"prettier": "^3.4.2",
4242
"typescript": "^5.7.3",
43-
"typescript-eslint": "^8.20.0",
43+
"typescript-eslint": "^8.21.0",
4444
"vitest": "^3.0.2",
4545
"vitest-browser-react": "^0.0.4"
4646
}

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@
3232
"react": ">=19.0.0"
3333
},
3434
"dependencies": {
35-
"type-fest": "^4.32.0"
35+
"type-fest": "^4.33.0"
3636
}
3737
}

packages/core/src/FormProvider.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ interface FormProviderProps<
6666
* ```
6767
*/
6868
ref: RefObject<HTMLFormElement | null>;
69+
/**
70+
* Disables all associated form inputs when `true`, unless overridden by setting `disabled` in `getFieldProps`.
71+
* This may be used with `isPending` from `useActionState` to disable inputs during a pending request.
72+
*/
73+
disabled?: boolean;
6974
children:
7075
| ReactNode
7176
| ((props: FormContextValue<DefaultValues, Meta>) => ReactNode);
@@ -78,13 +83,14 @@ export function FormProvider<
7883
defaultValues,
7984
meta,
8085
ref,
86+
disabled,
8187
children,
8288
}: FormProviderProps<DefaultValues, Meta>): JSX.Element {
8389
const props: FormContextValue<DefaultValues, Meta> = {
8490
defaultValues: serialize(defaultValues),
8591
meta,
8692
formRef: ref,
87-
getFieldProps: (options) => getFieldProps(ref, options),
93+
getFieldProps: (options) => getFieldProps(ref, { disabled, ...options }),
8894
};
8995

9096
return (

packages/core/src/getFieldProps.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ const validityMap: Readonly<
4444
export interface FieldOptions<FormValues> extends ConstraintOptions {
4545
name: PathsFromObject<FormValues>;
4646
onChange?: (event: ChangeEvent<any>) => void;
47+
disabled?: boolean | undefined;
4748
ref?: RefObject<unknown>;
4849
}
4950

5051
export interface FieldProps extends ConstraintProps {
5152
name: string;
53+
disabled?: boolean | undefined;
5254
onChange: (event: ChangeEvent<any>) => void;
5355
ref: RefCallback<unknown>;
5456
}
@@ -57,10 +59,11 @@ export function getFieldProps<FormValues>(
5759
formRef: RefObject<HTMLFormElement | null>,
5860
options: FieldOptions<FormValues>,
5961
): FieldProps {
60-
const { name, onChange, ref, ...constraints } = options;
62+
const { name, onChange, ref, disabled, ...constraints } = options;
6163

6264
return {
6365
name,
66+
disabled,
6467
...getConstraintProps(constraints),
6568
ref: getRefCallback(constraints, ref),
6669
onChange: getChangeHandler(constraints, onChange),

packages/core/test/browser/integration/fixtures/FormWithNativeReporting.tsx renamed to packages/core/test/browser/fixtures/FormWithNativeReporting.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useActionState, useRef } from "react";
2-
import { parse } from "../../../../src/parse.js";
3-
import { FormProvider } from "../../../../src/FormProvider.js";
4-
import { useFormContext } from "../../../../src/useFormContext.js";
2+
import { parse } from "../../../src/parse.js";
3+
import { FormProvider } from "../../../src/FormProvider.js";
4+
import { useFormContext } from "../../../src/useFormContext.js";
55

66
interface FormValues {
77
name: string;
@@ -41,7 +41,11 @@ async function submit(
4141
};
4242
}
4343

44-
export function FormWithNativeReporting() {
44+
export function FormWithNativeReporting({
45+
disabled = false,
46+
}: {
47+
disabled?: boolean;
48+
}) {
4549
const formRef = useRef<HTMLFormElement>(null);
4650
const [actionState, formAction, isPending] = useActionState(submit, {});
4751

@@ -50,6 +54,7 @@ export function FormWithNativeReporting() {
5054
ref={formRef}
5155
defaultValues={actionState.defaultValues}
5256
meta={actionState.meta}
57+
disabled={disabled}
5358
>
5459
{({ getFieldProps, defaultValues }) => (
5560
<form

packages/core/test/browser/integration/native_reporting.test.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, expect, it } from "vitest";
22
import { render } from "vitest-browser-react";
3-
import { FormWithNativeReporting } from "./fixtures/FormWithNativeReporting.js";
43
import { userEvent } from "@vitest/browser/context";
4+
import { FormWithNativeReporting } from "../fixtures/FormWithNativeReporting.js";
55

66
describe("UI integration tests with native validity reporting", () => {
77
it("displays success message after successful submit", async () => {
@@ -116,4 +116,20 @@ describe("UI integration tests with native validity reporting", () => {
116116
await expect.element(comment).toHaveValue("This is a long enough comment");
117117
await expect.element(agreement).toBeChecked();
118118
});
119+
120+
it("disables all associated fields when disabled prop in FormProvider is true", async () => {
121+
const screen = render(<FormWithNativeReporting disabled />);
122+
123+
const name = screen.getByLabelText("name");
124+
const animal = screen.getByLabelText("animal");
125+
const color = screen.getByLabelText("color");
126+
const comment = screen.getByLabelText("comment");
127+
const agreement = screen.getByLabelText("agreement");
128+
129+
await expect.element(name).toBeDisabled();
130+
await expect.element(animal).toBeDisabled();
131+
await expect.element(color).toBeDisabled();
132+
await expect.element(comment).toBeDisabled();
133+
await expect.element(agreement).toBeDisabled();
134+
});
119135
});

0 commit comments

Comments
 (0)