Auto-check after every word; disable browser spellcheck
- spellCheck={false} on EditorContent — LanguageTool's wavy marks
take over entirely, no double-squiggle confusion
- onUpdate schedules runLint() 1.5 s after the last keystroke via
lintDebounce ref; typing resets the timer so it only fires when
the writer pauses (naturally after finishing a word or sentence)
- runLintRef kept in sync with useEffect so the stale onUpdate
closure always calls the latest runLint
- Timer cleaned up on unmount
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bdafd3f2c3
commit
91071270a4
@ -111,6 +111,8 @@ const Editor = forwardRef(function Editor(
|
||||
const [lintCount, setLintCount] = useState(0)
|
||||
const [lintPopover, setLintPopover] = useState(null) // { top, left, message, replacements, from, to }
|
||||
const lintStatusRef = useRef('idle')
|
||||
const lintDebounce = useRef(null)
|
||||
const runLintRef = useRef(null) // always holds latest runLint, safe to call from onUpdate closure
|
||||
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
@ -126,11 +128,9 @@ const Editor = forwardRef(function Editor(
|
||||
content: '',
|
||||
onUpdate({ editor }) {
|
||||
onChange(stripLintMarks(editor.getJSON()))
|
||||
// Mark results as stale when the user edits so they know to re-check
|
||||
if (lintStatusRef.current === 'done') {
|
||||
lintStatusRef.current = 'stale'
|
||||
setLintStatus('stale')
|
||||
}
|
||||
// Debounced auto-check: fire 1.5 s after the last keystroke
|
||||
clearTimeout(lintDebounce.current)
|
||||
lintDebounce.current = setTimeout(() => runLintRef.current?.(), 1500)
|
||||
},
|
||||
})
|
||||
|
||||
@ -153,6 +153,11 @@ const Editor = forwardRef(function Editor(
|
||||
}, [editor, content])
|
||||
|
||||
// ── Lint check ───────────────────────────────────────────────────────────
|
||||
// Keep ref in sync so the onUpdate closure (which never re-captures) always
|
||||
// calls the latest version of runLint.
|
||||
useEffect(() => { runLintRef.current = runLint }, [runLint])
|
||||
useEffect(() => () => clearTimeout(lintDebounce.current), [])
|
||||
|
||||
const runLint = useCallback(async () => {
|
||||
if (!editor || lintStatusRef.current === 'checking') return
|
||||
lintStatusRef.current = 'checking'
|
||||
@ -265,7 +270,7 @@ const Editor = forwardRef(function Editor(
|
||||
lintCount={lintCount}
|
||||
/>
|
||||
<div className="editor-wrap" onClick={handleEditorClick}>
|
||||
<EditorContent editor={editor} className="editor-body" />
|
||||
<EditorContent editor={editor} className="editor-body" spellCheck={false} />
|
||||
<div className="word-count">{wordCount.toLocaleString()} {wordCount === 1 ? 'word' : 'words'}</div>
|
||||
</div>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user