Three Editable Surfaces, One Source of Truth: Retrofitting the Controlled-Input Pattern
TLDR
Managing multiple editable HTML views (HTML preview tab, visual diff panel, Monaco code editor) without a centralized coordinator leads to silent state overwrites and caret destruction when surface lifecycles diverge. Implementing a controlled-input coordinator using a sharedisSyncing guard flag and a skipEl source-exclusion rule synchronizes all editing surfaces while preserving user cursor position and performance.
| Surface Architecture | State Flow | Caret Preservation | Cross-Surface Consistency |
|---|---|---|---|
| Uncoordinated Surface Listeners | Divergent / Independent DOMs | Fragile (Overwritten on tab switch) | Low (Surfaces disagree) |
| Controlled Multi-Surface Coordinator | Centralized via isSyncing guard | 100% Retained via skipEl | 100% Synchronized |
Technical multi-surface synchronization architecture
// Centralized Multi-Surface Synchronizer with Shared Guard & Source Skipping
let isSyncingState = false;
export function isSyncing() { return isSyncingState; }
export function applyHtmlEverywhere(updatedHtml, sourceElement = null, state, monacoEditor) { if (isSyncingState) return; isSyncingState = true;
try { // 1. Update canonical application state state.extractedHTML = updatedHtml; const sanitizedHtml = window.DOMPurify ? window.DOMPurify.sanitize(updatedHtml) : updatedHtml;
// 2. Synchronize DOM contenteditable surfaces (skipping active input source) const surfaceIds = ['html-preview', 'visual-diff-html']; for (const id of surfaceIds) { const el = document.getElementById(id); if (el && el !== sourceElement && el.innerHTML !== sanitizedHtml) { el.innerHTML = sanitizedHtml; } }
// 3. Synchronize Monaco code editor model if (monacoEditor && monacoEditor.getValue() !== updatedHtml) { monacoEditor.getModel()?.setValue(updatedHtml); } } finally { isSyncingState = false; } }
Rule of thumb: Pass the active input element as askipElparameter when broadcasting state updates across multiplecontenteditablesurfaces to protect the user's active cursor.