import React from 'react'; import { cn } from '@/lib/utils'; import FormLabel from './FormLabel'; import FormError from './FormError'; import FormInput from './FormInput'; import FormTextarea from './FormTextarea'; import FormSelect from './FormSelect'; import FormCheckbox from './FormCheckbox'; import FormRadio from './FormRadio'; /** * FormField Component * Wrapper for form fields with label, input, and error * Supports different input types and provides consistent form experience */ export type FormFieldType = | 'text' | 'email' | 'tel' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'number' | 'password' | 'date' | 'time' | 'url'; export interface FormFieldProps { type?: FormFieldType; label?: string; name: string; value?: any; error?: string | string[]; helpText?: string; required?: boolean; disabled?: boolean; placeholder?: string; className?: string; containerClassName?: string; // For select, checkbox, radio options?: any[]; // For select multiple?: boolean; showSearch?: boolean; // For checkbox/radio layout?: 'vertical' | 'horizontal'; // For textarea rows?: number; showCharCount?: boolean; autoResize?: boolean; maxLength?: number; // For input prefix?: React.ReactNode; suffix?: React.ReactNode; showClear?: boolean; iconPosition?: 'prefix' | 'suffix'; // Callbacks onChange?: (value: any) => void; onBlur?: () => void; onClear?: () => void; // Additional props [key: string]: any; } export const FormField: React.FC = ({ type = 'text', label, name, value, error, helpText, required = false, disabled = false, placeholder, className, containerClassName, options = [], multiple = false, showSearch = false, layout = 'vertical', rows = 4, showCharCount = false, autoResize = false, maxLength, prefix, suffix, showClear = false, iconPosition = 'prefix', onChange, onBlur, onClear, ...props }) => { const commonProps = { name, value, onChange, onBlur, disabled, required, placeholder, 'aria-label': label, }; const renderInput = () => { switch (type) { case 'textarea': return ( ); case 'select': return ( ); case 'checkbox': return ( 0 : !!value} options={options} value={Array.isArray(value) ? value : []} onChange={onChange} disabled={disabled} containerClassName={className} /> ); case 'radio': return ( ); default: return ( ); } }; // For checkbox and radio, the label is handled internally const showExternalLabel = type !== 'checkbox' && type !== 'radio'; return (
{showExternalLabel && label && ( {label} )} {renderInput()} {!showExternalLabel && error && ( )}
); }; FormField.displayName = 'FormField'; export default FormField;