"use client"; import classNames from "classnames"; import { InputHTMLAttributes, useCallback, useEffect, useLayoutEffect, useRef } from "react" interface TextAreaProps extends Omit, "onChange"> { isAutoExpanding?: boolean; // Set to true to enable auto-expanding text area behavior. Default is false. value: string; onChange: (value: string) => void; } export default function TextArea({ isAutoExpanding, style, name, value, onChange, className, placeholder = "", onKeyUp, ...props }: TextAreaProps) { const handleTextChange = useCallback((event: Event) => { const fakeTextAreaElement = event.target as HTMLDivElement; const newValue = fakeTextAreaElement.innerText; onChange?.(newValue); }, [onChange]); const handleKeyUp = useCallback((event: Event) => { if (onKeyUp) { onKeyUp(event as unknown as React.KeyboardEvent); } }, [onKeyUp]); const handleTextAreaFocus = (event: React.FocusEvent) => { if (event.target.innerText.trim() === placeholder) { event.target.innerText = ""; } }; const handleTextAreaBlur = (event: React.FocusEvent) => { if (value === "") { event.target.innerText = placeholder; } }; const handleChange = (event: React.ChangeEvent) => { onChange(event.target.value); }; const fakeTextAreaRef = useRef(null); useLayoutEffect(() => { const fakeTextAreaElement = fakeTextAreaRef.current; if (fakeTextAreaElement && fakeTextAreaElement.innerText.trim() !== "") { fakeTextAreaElement.innerText = placeholder; } }, [placeholder]); useLayoutEffect(() => { const fakeTextAreaElement = fakeTextAreaRef.current; if (fakeTextAreaElement) { fakeTextAreaElement.addEventListener("input", handleTextChange); fakeTextAreaElement.addEventListener("keyup", handleKeyUp); } return () => { if (fakeTextAreaElement) { fakeTextAreaElement.removeEventListener("input", handleTextChange); fakeTextAreaElement.removeEventListener("keyup", handleKeyUp); } }; }, [handleKeyUp, handleTextChange]); useEffect(() => { const fakeTextAreaElement = fakeTextAreaRef.current; const textAreaText = fakeTextAreaElement?.innerText; if (fakeTextAreaElement && (value === "" || value === "\n")) { fakeTextAreaElement.innerText = placeholder; return; } if (fakeTextAreaElement && textAreaText !== value) { fakeTextAreaElement.innerText = value; } }, [placeholder, value]); return isAutoExpanding ? ( <>
) : (