Shih-hungg's picture
Migrate to shadcn
8b65a0f
'use client';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { cn } from '@/lib/utils';
export interface TextInputProps {
label: string;
value?: string;
defaultValue?: string;
onChange: (value: string) => void;
type?: 'text' | 'email' | 'password' | 'url' | 'tel';
className?: string;
disabled?: boolean;
placeholder?: string;
helpText?: string;
required?: boolean;
maxLength?: number;
minLength?: number;
pattern?: string;
isTextarea?: boolean;
rows?: number;
}
export default function TextInput({
label,
value,
defaultValue = '',
onChange,
type = 'text',
className = '',
disabled = false,
placeholder,
helpText,
required = false,
maxLength,
minLength,
pattern,
isTextarea = false,
rows = 3,
}: TextInputProps) {
const currentValue = value ?? defaultValue;
return (
<div className={className}>
<Label>
{label}
{required && <span className="text-destructive ml-1">*</span>}
</Label>
{isTextarea ? (
<Textarea
value={currentValue}
placeholder={placeholder}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
required={required}
maxLength={maxLength}
minLength={minLength}
rows={rows}
className={cn("mt-2", disabled && "opacity-50 cursor-not-allowed")}
/>
) : (
<Input
type={type}
value={currentValue}
placeholder={placeholder}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
required={required}
maxLength={maxLength}
minLength={minLength}
pattern={pattern}
className={cn("mt-2", disabled && "opacity-50 cursor-not-allowed")}
/>
)}
{helpText && (
<p className="text-xs text-muted-foreground mt-1">
{helpText}
</p>
)}
</div>
);
}