a tool for shared writing and social publishing
1import { 2 forwardRef, 3 useEffect, 4 useImperativeHandle, 5 useRef, 6 useState, 7} from "react"; 8import styles from "./textarea-styles.module.css"; 9 10export type AutosizeTextareaProps = React.DetailedHTMLProps< 11 React.TextareaHTMLAttributes<HTMLTextAreaElement>, 12 HTMLTextAreaElement 13> & { noWrap?: boolean }; 14export const AutosizeTextarea = forwardRef< 15 HTMLTextAreaElement, 16 AutosizeTextareaProps 17>((props: AutosizeTextareaProps & { noWrap?: boolean }, ref) => { 18 let textarea = useRef<HTMLTextAreaElement | null>(null); 19 let { noWrap, ...rest } = props; 20 useImperativeHandle(ref, () => textarea.current as HTMLTextAreaElement); 21 22 return ( 23 <div 24 className={`${styles["grow-wrap"]} ${props.className} ${noWrap ? styles["no-wrap"] : ""}`} 25 data-replicated-value={props.value} 26 style={props.style} 27 > 28 <textarea 29 rows={1} 30 {...rest} 31 ref={textarea} 32 className={`placeholder:text-tertiary bg-transparent ${props.className}`} 33 /> 34 </div> 35 ); 36}); 37 38export const AsyncValueAutosizeTextarea = forwardRef< 39 HTMLTextAreaElement, 40 AutosizeTextareaProps 41>((props: AutosizeTextareaProps, ref) => { 42 let [intermediateState, setIntermediateState] = useState( 43 props.value as string, 44 ); 45 46 useEffect(() => { 47 setIntermediateState(props.value as string); 48 }, [props.value]); 49 50 return ( 51 <AutosizeTextarea 52 {...props} 53 ref={ref} 54 value={intermediateState} 55 onChange={async (e) => { 56 if (!props.onChange) return; 57 setIntermediateState(e.currentTarget.value); 58 await Promise.all([props.onChange(e)]); 59 }} 60 /> 61 ); 62}); 63 64AutosizeTextarea.displayName = "Textarea";