Uecko_ERP/packages/rdx-ui/src/components/form/checkbox-field.tsx

103 lines
2.7 KiB
TypeScript

import {
Checkbox,
Field,
FieldContent,
FieldDescription,
FieldError,
} from "@repo/shadcn-ui/components";
import { cn } from "@repo/shadcn-ui/lib/utils";
import * as React from "react";
import { Controller, type FieldPath, type FieldValues, useFormContext } from "react-hook-form";
import { FormFieldLabel } from "./form-field-label.tsx";
type CheckboxFieldProps<TFormValues extends FieldValues> = {
name: FieldPath<TFormValues>;
label: string;
description?: string;
reserveDescriptionSpace?: boolean;
disabled?: boolean;
required?: boolean;
readOnly?: boolean;
orientation?: "vertical" | "horizontal" | "responsive";
className?: string;
inputClassName?: string;
};
export const CheckboxField = <TFormValues extends FieldValues>({
name,
label,
description,
reserveDescriptionSpace = false,
disabled = false,
required = false,
readOnly = false,
orientation = "horizontal",
className,
inputClassName,
}: CheckboxFieldProps<TFormValues>) => {
const { control, formState } = useFormContext<TFormValues>();
const inputId = React.useId();
const descriptionId = description ? `${inputId}-description` : undefined;
const isDisabled = disabled || readOnly || formState.isSubmitting;
return (
<Controller
control={control}
name={name}
render={({ field, fieldState }) => {
const hasError = Boolean(fieldState.error);
return (
<Field
className={cn("gap-2", className)}
data-invalid={hasError}
orientation={orientation}
>
<Checkbox
aria-describedby={descriptionId}
aria-invalid={hasError || undefined}
aria-required={required || undefined}
checked={field.value === true}
className={cn(inputClassName)}
disabled={isDisabled}
id={inputId}
name={field.name}
onBlur={field.onBlur}
onCheckedChange={(checked) => {
field.onChange(checked === true);
}}
ref={field.ref}
required={required}
/>
<FieldContent className="gap-1">
<FormFieldLabel className="font-normal" htmlFor={inputId} required={required}>
{label}
</FormFieldLabel>
{description ? (
<FieldDescription>{description}</FieldDescription>
) : reserveDescriptionSpace ? (
<div aria-hidden="true" className="min-h-5" />
) : null}
<FieldError errors={[fieldState.error]} />
</FieldContent>
</Field>
);
}}
/>
);
};