@@ -102,15 +102,30 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
102102 const monacoRef = useRef < monaco . editor . IStandaloneCodeEditor | null > ( null ) ;
103103 const resizeStartY = useRef < number > ( 0 ) ;
104104 const resizeStartHeight = useRef < number > ( 300 ) ;
105+ const isUpdatingFromMonaco = useRef ( false ) ;
105106
106107 const language = node . attrs . language || 'javascript' ;
107108 const isExecutable = codeExecutionService . isLanguageSupported ( language as SupportedLanguage ) ;
108109
109110
110111
111112 useEffect ( ( ) => {
112- setCode ( node . textContent ) ;
113- } , [ node . textContent ] ) ;
113+ // COMPLETELY DISABLE this effect to prevent any Monaco updates from external sources
114+ // This should eliminate all blinking by never touching Monaco after initialization
115+ // External sync will be handled differently if needed
116+ return ;
117+
118+ // Only update code if it's not coming from Monaco itself
119+ // This prevents the circular update loop that causes blinking
120+ const nodeText = node . textContent ;
121+ if ( nodeText !== code && ! isUpdatingFromMonaco . current ) {
122+ setCode ( nodeText ) ;
123+ // Since we're using defaultValue, manually update Monaco's content
124+ if ( monacoRef . current ?. getValue ( ) !== nodeText ) {
125+ monacoRef . current ?. setValue ( nodeText ) ;
126+ }
127+ }
128+ } , [ node . textContent , code ] ) ;
114129
115130
116131 useEffect ( ( ) => {
@@ -122,7 +137,7 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
122137 setEditorHeight ( newHeight ) ;
123138
124139 // Trigger Monaco layout when height changes (throttled)
125- if ( monacoRef . current ) {
140+ if ( monacoRef . current && ! isUpdatingFromMonaco . current ) {
126141 monacoRef . current . layout ( ) ;
127142 }
128143 } ;
@@ -140,10 +155,10 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
140155 document . removeEventListener ( 'mousemove' , handleMouseMove ) ;
141156 document . removeEventListener ( 'mouseup' , handleMouseUp ) ;
142157 if ( updateTimeoutRef . current ) {
143- if ( updateTimeoutRef . current ) {
144158 clearTimeout ( updateTimeoutRef . current ) ;
145159 }
146- }
160+ // Reset the Monaco update flag on cleanup
161+ isUpdatingFromMonaco . current = false ;
147162 } ;
148163 } , [ isResizing ] ) ;
149164
@@ -155,7 +170,8 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
155170 const triggerLayout = ( ) => {
156171 clearTimeout ( resizeTimeout ) ;
157172 resizeTimeout = setTimeout ( ( ) => {
158- if ( monacoRef . current ) {
173+ // Don't trigger layout if we're updating from Monaco to prevent blinking
174+ if ( monacoRef . current && ! isUpdatingFromMonaco . current ) {
159175 monacoRef . current . layout ( ) ;
160176 }
161177 } , 100 ) ; // Reduced debounce for better responsiveness
@@ -188,14 +204,13 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
188204
189205 const handleCodeChange = ( value : string | undefined ) => {
190206 if ( value !== undefined ) {
191- setCode ( value ) ;
192- // Debounce the node content update to avoid performance issues
207+ // Minimal debounced update - only update TipTap node
193208 if ( updateTimeoutRef . current ) {
194209 clearTimeout ( updateTimeoutRef . current ) ;
195210 }
196211 updateTimeoutRef . current = setTimeout ( ( ) => {
197212 updateNodeContent ( value ) ;
198- } , 300 ) ;
213+ } , 300 ) ; // Increased debounce to reduce updates
199214 }
200215 } ;
201216
@@ -359,10 +374,11 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
359374 { /* Code Content */ }
360375 < div className = { `relative w-full ${ monacoThemeOverride === 'light' ? 'monaco-light-override' : 'monaco-dark-override' } ` } >
361376 < Editor
377+ key = { `monaco-${ node . attrs . language } -${ getPos ( ) } ` }
362378 height = { `${ editorHeight } px` }
363379 width = "100%"
364380 language = { language }
365- value = { code }
381+ defaultValue = { code }
366382 onChange = { handleCodeChange }
367383 theme = "vs-dark"
368384 options = { {
@@ -410,7 +426,10 @@ export function ExecutableCodeBlockNodeView({ node, updateAttributes, selected:
410426 if ( entries [ 0 ] . isIntersecting ) {
411427 // Small delay to ensure DOM is ready
412428 setTimeout ( ( ) => {
413- monacoEditor . layout ( ) ;
429+ // Don't layout if updating from Monaco to prevent blinking
430+ if ( ! isUpdatingFromMonaco . current ) {
431+ monacoEditor . layout ( ) ;
432+ }
414433 } , 50 ) ;
415434 }
416435 } ) ;
0 commit comments