Files

72 lines
2.0 KiB
TypeScript

import { ChangeEvent, FocusEvent, ReactNode, useCallback, useEffect, useRef } from "react";
import { CommonInputProps } from "~~/components/scaffold-eth";
type TextAreaProps<T> = CommonInputProps<T> & {
error?: boolean;
prefix?: ReactNode;
suffix?: ReactNode;
reFocus?: boolean;
inputClassName?: string;
rows?: number;
};
export const TextArea = <T extends { toString: () => string } | undefined = string>({
name,
value,
onChange,
placeholder,
error,
disabled,
prefix,
suffix,
reFocus,
inputClassName = "",
rows = 8,
}: TextAreaProps<T>) => {
const inputReft = useRef<HTMLTextAreaElement>(null);
let modifier = "";
if (error) {
modifier = "border-error";
} else if (disabled) {
modifier = "border-disabled bg-base-300";
}
const handleChange = useCallback(
(e: ChangeEvent<HTMLTextAreaElement>) => {
onChange(e.target.value as unknown as T);
},
[onChange],
);
// Runs only when reFocus prop is passed, useful for setting the cursor
// at the end of the input. Example AddressInput
const onFocus = (e: FocusEvent<HTMLTextAreaElement, Element>) => {
if (reFocus !== undefined) {
e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length);
}
};
useEffect(() => {
if (reFocus !== undefined && reFocus === true) inputReft.current?.focus();
}, [reFocus]);
return (
<div className={`flex flex-1 border-none border-transparent bg-base-200 rounded-sm text-accent ${modifier}`}>
{prefix}
<textarea
className={`textarea textarea-ghost text-xs focus-within:border-transparent focus:outline-none focus:bg-transparent focus:text-gray-400 px-4 border-none w-full font-medium placeholder:text-accent/50 text-gray-400 ${inputClassName}`}
placeholder={placeholder}
name={name}
value={value?.toString()}
onChange={handleChange}
disabled={disabled}
autoComplete="off"
ref={inputReft}
onFocus={onFocus}
rows={rows}
/>
{suffix}
</div>
);
};