/** * components/TextEditor.jsx * ───────────────────────── * Left panel: textarea, char/word counters, action buttons. * Toggles removed for a cleaner, opinionated UX. */ import { useRef, useState, useEffect } from 'react' import { motion, AnimatePresence } from 'framer-motion' const MAX_CHARS = 4096 const STYLES = ['professional', 'casual', 'academic', 'concise'] export default function TextEditor({ onCorrect, onRefine, onClear, loading, hasResult }) { const [text, setText] = useState('') const [focused, setFocused] = useState(false) const [style, setStyle] = useState('professional') const ref = useRef(null) // Listen for "use-as-input" event from Home useEffect(() => { function handler(e) { setText(e.detail || '') setTimeout(() => ref.current?.focus(), 100) } window.addEventListener('wr:loadText', handler) return () => window.removeEventListener('wr:loadText', handler) }, []) const words = text.trim() ? text.trim().split(/\s+/).length : 0 const chars = text.length const pct = Math.min((chars / MAX_CHARS) * 100, 100) function handleChange(e) { if (e.target.value.length <= MAX_CHARS) setText(e.target.value) } function handleClear() { setText(''); onClear(); ref.current?.focus() } const barColor = pct > 90 ? 'var(--red)' : pct > 70 ? 'var(--amber)' : 'linear-gradient(90deg, var(--accent), var(--accent-2))' return ( {/* ── Main input card ── */}
{/* Card header - simplified */}
Input Text
{/* Textarea */}