83 lines
1.6 KiB
TypeScript
83 lines
1.6 KiB
TypeScript
import * as React from "react"
|
|
|
|
import { cn } from "@/lib/utils"
|
|
import { Label } from "@/Components/ui/label"
|
|
|
|
function Form({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<"form">) {
|
|
return (
|
|
<form
|
|
data-slot="form"
|
|
className={cn("space-y-4", className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
interface FormFieldProps extends React.ComponentProps<"div"> {
|
|
label: string
|
|
htmlFor?: string
|
|
required?: boolean
|
|
error?: string
|
|
description?: string
|
|
}
|
|
|
|
function FormField({
|
|
label,
|
|
htmlFor,
|
|
required,
|
|
error,
|
|
description,
|
|
className,
|
|
children,
|
|
...props
|
|
}: FormFieldProps) {
|
|
return (
|
|
<div
|
|
data-slot="form-field"
|
|
className={cn("space-y-1.5", className)}
|
|
{...props}
|
|
>
|
|
<Label htmlFor={htmlFor}>
|
|
{label}
|
|
{required && <span className="text-destructive ml-0.5">*</span>}
|
|
</Label>
|
|
<div className="w-full [&_[data-slot=select-trigger]]:w-full">
|
|
{children}
|
|
</div>
|
|
{description && <FormDescription>{description}</FormDescription>}
|
|
{error && <FormMessage>{error}</FormMessage>}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function FormDescription({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<"p">) {
|
|
return (
|
|
<p
|
|
data-slot="form-description"
|
|
className={cn("text-xs text-muted-foreground", className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function FormMessage({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<"p">) {
|
|
return (
|
|
<p
|
|
data-slot="form-message"
|
|
className={cn("text-sm text-destructive", className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export { Form, FormField, FormDescription, FormMessage }
|