/** * FormTextarea Component * * Reusable Textarea field for react-hook-form with register integration. * Handles label, error display, and description automatically. * * @module components/forms/FormTextarea */ 'use client'; import { ComponentProps } from 'react'; import type { FieldError, UseFormRegisterReturn } from 'react-hook-form'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; export interface FormTextareaProps extends Omit, 'children'> { /** Field label */ label: string; /** Field name (optional if provided via register) */ name?: string; /** Is field required? Shows asterisk if true */ required?: boolean; /** Form error from react-hook-form */ error?: FieldError; /** Helper text below the field */ description?: string; /** Register return object from useForm */ registration?: UseFormRegisterReturn; } /** * FormTextarea - Textarea field for react-hook-form * * Automatically handles: * - Label with required indicator * - Error message display * - Description/helper text * - Accessibility attributes * * @example * ```tsx * * ``` */ export function FormTextarea({ label, name: explicitName, required = false, error, description, registration, ...textareaProps }: FormTextareaProps) { // Extract name from props or registration const registerName = 'name' in textareaProps ? (textareaProps as { name: string }).name : undefined; const name = explicitName || registerName || registration?.name; if (!name) { throw new Error('FormTextarea: name must be provided either explicitly or via register()'); } const errorId = error ? `${name}-error` : undefined; const descriptionId = description ? `${name}-description` : undefined; const ariaDescribedBy = [errorId, descriptionId].filter(Boolean).join(' ') || undefined; // Merge registration props with other props const mergedProps = registration ? { ...registration, ...textareaProps } : textareaProps; return (
{description && (

{description}

)}