Skip to content

Commit 6b68e97

Browse files
fix: shadcn FieldWrapper and SelectField
tests: add shadcn v4, v3 tests (native Enum)
1 parent 8156633 commit 6b68e97

File tree

5 files changed

+49
-16
lines changed

5 files changed

+49
-16
lines changed

apps/web/cypress/component/autoform/shadcn-zod/basic.cy.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@ import { ZodProvider, fieldConfig } from "@autoform/zod";
44
import { z } from "zod/v3";
55
import { TestWrapper } from "./utils";
66

7+
enum Sports {
8+
Football = "Football/Soccer",
9+
Basketball = "Basketballs",
10+
Baseball = "Baseballs",
11+
Hockey = "Hockey (Ice)",
12+
None = "I don't like sports",
13+
}
14+
715
describe("AutoForm Basic Tests (SHADCN-ZOD)", () => {
816
const basicSchema = z.object({
917
name: z.string().min(2, "Name must be at least 2 characters"),
1018
age: z.coerce.number().min(18, "Must be at least 18 years old"),
1119
email: z.string().email("Invalid email address"),
1220
website: z.string().url("Invalid URL").optional(),
21+
sports: z.nativeEnum(Sports),
1322
birthdate: z.coerce.date(),
1423
isStudent: z.boolean(),
1524
});
@@ -31,6 +40,7 @@ describe("AutoForm Basic Tests (SHADCN-ZOD)", () => {
3140
cy.get('input[name="age"]').should("have.attr", "type", "number");
3241
cy.get('input[name="email"]').should("exist");
3342
cy.get('input[name="website"]').should("exist");
43+
cy.get('button[name="sports"]').should("exist");
3444
cy.get('input[name="birthdate"]').should("exist");
3545
cy.get("button#isStudent").should("exist");
3646
});
@@ -47,6 +57,11 @@ describe("AutoForm Basic Tests (SHADCN-ZOD)", () => {
4757
cy.get('input[name="age"]').type("25");
4858
cy.get('input[name="email"]').type("[email protected]");
4959
cy.get('input[name="website"]').type("https://example.com");
60+
cy.get('button[name="sports"]').should("exist").click();
61+
cy.get('div[data-radix-collection-item][role="option"]')
62+
.should("be.visible")
63+
.contains("Hockey (Ice)")
64+
.click();
5065
cy.get('input[name="birthdate"]').type("1990-01-01");
5166
cy.get("button#isStudent").click();
5267

@@ -58,6 +73,7 @@ describe("AutoForm Basic Tests (SHADCN-ZOD)", () => {
5873
age: 25,
5974
6075
website: "https://example.com",
76+
sports: "Hockey (Ice)",
6177
birthdate: new Date("1990-01-01"),
6278
isStudent: true,
6379
});

apps/web/cypress/component/autoform/shadcn-zod4/basic.cy.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@ import { ZodProvider, fieldConfig } from "@autoform/zod";
44
import { z } from "zod/v4";
55
import { TestWrapper } from "./utils";
66

7+
enum Sports {
8+
Football = "Football/Soccer",
9+
Basketball = "Basketballs",
10+
Baseball = "Baseballs",
11+
Hockey = "Hockey (Ice)",
12+
None = "I don't like sports",
13+
}
14+
715
describe("AutoForm Basic Tests (SHADCN-ZOD-V4)", () => {
816
const basicSchema = z.object({
917
name: z.string().min(2, "Name must be at least 2 characters"),
1018
age: z.coerce.number().min(18, "Must be at least 18 years old"),
1119
email: z.string().email("Invalid email address"),
1220
website: z.string().url("Invalid URL").optional(),
21+
sports: z.enum(Sports),
1322
birthdate: z.coerce.date(),
1423
isStudent: z.boolean(),
1524
});
@@ -31,6 +40,7 @@ describe("AutoForm Basic Tests (SHADCN-ZOD-V4)", () => {
3140
cy.get('input[name="age"]').should("have.attr", "type", "number");
3241
cy.get('input[name="email"]').should("exist");
3342
cy.get('input[name="website"]').should("exist");
43+
cy.get('button[name="sports"]').should("exist");
3444
cy.get('input[name="birthdate"]').should("exist");
3545
cy.get("button#isStudent").should("exist");
3646
});
@@ -47,6 +57,11 @@ describe("AutoForm Basic Tests (SHADCN-ZOD-V4)", () => {
4757
cy.get('input[name="age"]').type("25");
4858
cy.get('input[name="email"]').type("[email protected]");
4959
cy.get('input[name="website"]').type("https://example.com");
60+
cy.get('button[name="sports"]').should("exist").click();
61+
cy.get('div[data-radix-collection-item][role="option"]')
62+
.should("be.visible")
63+
.contains("Hockey (Ice)")
64+
.click();
5065
cy.get('input[name="birthdate"]').type("1990-01-01");
5166
cy.get("button#isStudent").click();
5267

@@ -58,6 +73,7 @@ describe("AutoForm Basic Tests (SHADCN-ZOD-V4)", () => {
5873
age: 25,
5974
6075
website: "https://example.com",
76+
sports: "Hockey (Ice)",
6177
birthdate: new Date("1990-01-01"),
6278
isStudent: true,
6379
});

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/shadcn/src/components/ui/autoform/components/FieldWrapper.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const FieldWrapper: React.FC<FieldWrapperProps> = ({
1212
error,
1313
}) => {
1414
const isDisabled = DISABLED_LABELS.includes(field.type);
15+
const hideError = ["array", "object"].includes(field.type);
1516

1617
return (
1718
<div className="space-y-2">
@@ -27,7 +28,9 @@ export const FieldWrapper: React.FC<FieldWrapperProps> = ({
2728
{field.fieldConfig.description}
2829
</p>
2930
)}
30-
{error && <p className="text-sm text-destructive">{error}</p>}
31+
{!hideError && error && (
32+
<p className="text-sm text-destructive">{error}</p>
33+
)}
3134
</div>
3235
);
3336
};

packages/shadcn/src/components/ui/autoform/components/SelectField.tsx

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,33 @@ import {
77
} from "@/components/ui/select";
88
import { AutoFormFieldProps } from "@autoform/react";
99
import React from "react";
10+
import { useController } from "react-hook-form";
1011

1112
export const SelectField: React.FC<AutoFormFieldProps> = ({
1213
field,
1314
inputProps,
1415
error,
1516
id,
1617
}) => {
17-
const { key, ...props } = inputProps;
18+
const { key, onChange, onBlur, ref, ...props } = inputProps;
19+
const { field: formField } = useController({ name: id });
1820

1921
return (
2022
<Select
23+
onValueChange={formField.onChange}
24+
value={formField.value}
2125
{...props}
22-
onValueChange={(value) => {
23-
const syntheticEvent = {
24-
target: {
25-
value,
26-
name: field.key,
27-
},
28-
} as React.ChangeEvent<HTMLInputElement>;
29-
props.onChange(syntheticEvent);
30-
}}
31-
defaultValue={field.default}
3226
>
33-
<SelectTrigger id={id} className={error ? "border-destructive" : ""}>
34-
<SelectValue placeholder="Select an option" />
27+
<SelectTrigger
28+
id={id}
29+
{...formField}
30+
className={error ? "border-destructive" : ""}
31+
>
32+
<SelectValue placeholder={props.placeholder ?? "Select an option"} />
3533
</SelectTrigger>
3634
<SelectContent>
3735
{(field.options || []).map(([key, label]) => (
38-
<SelectItem key={key} value={key}>
36+
<SelectItem key={key} value={label}>
3937
{label}
4038
</SelectItem>
4139
))}

0 commit comments

Comments
 (0)