fix: prevent Monaco onChange echo from dismissing parameter stepper

ScriptBodyEditor's onChange fired when the value prop changed externally
(from handleAcceptCandidate inserting placeholders), creating a feedback
loop that reset acceptingCandidateRef before the second useEffect cycle.
Guard onChange to only propagate when the value actually differs from the
current prop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-28 22:18:17 +00:00
parent 96602a6676
commit 0483b6f0f5

View File

@@ -1,4 +1,4 @@
import { useCallback } from 'react'
import { useCallback, useRef } from 'react'
import Editor, { type BeforeMount } from '@monaco-editor/react'
import { resolutionFlowTheme, THEME_ID } from '@/components/tree-editor/code-mode/resolutionFlowTheme'
import { Spinner } from '@/components/common/Spinner'
@@ -10,11 +10,22 @@ interface Props {
}
export function ScriptBodyEditor({ value, onChange, disabled }: Props) {
const lastValueRef = useRef(value)
lastValueRef.current = value
const handleBeforeMount: BeforeMount = useCallback((monaco) => {
// Register our dark theme if not already defined
monaco.editor.defineTheme(THEME_ID, resolutionFlowTheme)
}, [])
const handleChange = useCallback((v: string | undefined) => {
const next = v ?? ''
// Only propagate user-initiated edits, not echoes from external value prop changes
if (next !== lastValueRef.current) {
onChange(next)
}
}, [onChange])
return (
<div className="rounded-xl border border-border overflow-hidden">
<Editor
@@ -22,7 +33,7 @@ export function ScriptBodyEditor({ value, onChange, disabled }: Props) {
language="powershell"
theme={THEME_ID}
value={value}
onChange={v => onChange(v ?? '')}
onChange={handleChange}
beforeMount={handleBeforeMount}
loading={
<div className="flex h-[300px] items-center justify-center bg-card">