2024-10-21 09:29:49 -07:00
|
|
|
import { ChangeEventHandler, useLayoutEffect, useRef } from "react";
|
2024-08-26 21:31:42 +03:00
|
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
|
|
|
import { cn } from "@/util/utils";
|
|
|
|
|
|
2024-10-21 09:29:49 -07:00
|
|
|
type Props = {
|
|
|
|
|
value: string;
|
|
|
|
|
onChange?: ChangeEventHandler<HTMLTextAreaElement>;
|
|
|
|
|
className?: string;
|
|
|
|
|
readOnly?: boolean;
|
|
|
|
|
placeholder?: string;
|
|
|
|
|
};
|
2024-08-26 21:31:42 +03:00
|
|
|
|
2024-10-21 09:29:49 -07:00
|
|
|
function AutoResizingTextarea({
|
|
|
|
|
value,
|
|
|
|
|
onChange,
|
|
|
|
|
className,
|
|
|
|
|
readOnly,
|
|
|
|
|
placeholder,
|
|
|
|
|
}: Props) {
|
2024-08-26 21:31:42 +03:00
|
|
|
const ref = useRef<HTMLTextAreaElement>(null);
|
|
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
// size the textarea correctly on first render
|
|
|
|
|
if (!ref.current) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ref.current.style.height = `${ref.current.scrollHeight + 2}px`;
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
function setSize() {
|
|
|
|
|
if (!ref.current) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ref.current.style.height = "auto";
|
|
|
|
|
ref.current.style.height = `${ref.current.scrollHeight + 2}px`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Textarea
|
2024-10-21 09:29:49 -07:00
|
|
|
value={value}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
readOnly={readOnly}
|
|
|
|
|
placeholder={placeholder}
|
2024-09-30 07:12:01 -07:00
|
|
|
ref={ref}
|
2024-08-26 21:31:42 +03:00
|
|
|
onKeyDown={setSize}
|
|
|
|
|
onInput={setSize}
|
|
|
|
|
rows={1}
|
2024-10-21 09:29:49 -07:00
|
|
|
className={cn("min-h-0 resize-none overflow-y-hidden", className)}
|
2024-08-26 21:31:42 +03:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { AutoResizingTextarea };
|