Files
lti-web-client/src/components/input/TextArea.tsx
T
2026-01-31 13:15:47 +07:00

126 lines
2.8 KiB
TypeScript

'use client';
import { ChangeEventHandler, FocusEventHandler, ReactNode } from 'react';
import { cn } from '@/lib/helper';
export interface TextAreaProps {
label?: string;
bottomLabel?: string;
name: string;
value?: string | number;
placeholder?: string;
className?: {
wrapper?: string;
label?: string;
inputWrapper?: string;
input?: string;
};
isError?: boolean;
isValid?: boolean;
disabled?: boolean;
readOnly?: boolean;
required?: boolean;
isLoading?: boolean;
errorMessage?: string;
startAdornment?: ReactNode;
endAdornment?: ReactNode;
onChange?: ChangeEventHandler<HTMLTextAreaElement>;
onBlur?: FocusEventHandler<HTMLTextAreaElement>;
rows?: number;
ref?: React.RefObject<HTMLTextAreaElement | null>;
}
const TextArea = ({
label,
bottomLabel,
name,
value,
placeholder,
className,
isError,
isValid,
errorMessage,
startAdornment,
endAdornment,
disabled = false,
required = false,
onChange,
onBlur,
readOnly = false,
isLoading = false,
rows = 3,
ref,
}: TextAreaProps) => {
return (
<div
className={cn(
'w-full flex flex-col gap-0 text-start',
className?.wrapper
)}
>
{label && (
<label
htmlFor={name}
className={cn(
'w-full py-2 text-xs font-semibold leading-5',
{
'text-error': isError,
},
className?.label
)}
>
{label}
{required && (
<>
{' '}
<span className='tooltip tooltip-error' data-tip='required'>
<span className='text-error'> *</span>
</span>
</>
)}
</label>
)}
{startAdornment && startAdornment}
<textarea
className={cn(
'textarea h-auto px-3 py-2.5 text-sm text-base-content font-normal leading-6 w-full rounded-lg outline-none! transition-all bg-white border-base-content/10',
{
'border-error': isError,
'border-success!': isValid,
},
className?.inputWrapper
)}
id={name}
name={name}
placeholder={placeholder}
value={value}
rows={rows}
onChange={onChange}
onBlur={onBlur}
disabled={disabled}
readOnly={readOnly}
ref={ref}
/>
{(isLoading || endAdornment) && (
<div className='flex flex-row gap-2'>
{isLoading && <span className='loading loading-spinner' />}
{endAdornment && endAdornment}
</div>
)}
{!isError && bottomLabel && (
<p className='w-full mt-1.5 text-xs opacity-60'>{bottomLabel}</p>
)}
{isError && (
<p className='w-full mt-1.5 text-xs text-error'>{errorMessage}</p>
)}
</div>
);
};
export default TextArea;