Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new MonacoDiffEditor Blazor component (JS interop + Razor wrapper) to expose Monaco’s diff editor in BlueBlazor, and wires it into the docs navigation with example stories.
Changes:
- Introduces
MonacoDiffEditorcomponent with JS initialization, value binding, and disposal. - Adds docs stories demonstrating basic usage, inline diff, and overview ruler usage.
- Updates docs navigation data to include “Monaco diff editor”.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| BlueBlazor/Components/MonacoDiffEditor/MonacoDiffEditor.razor.js | JS module to load Monaco and create/manage diff editor instances + models |
| BlueBlazor/Components/MonacoDiffEditor/MonacoDiffEditor.razor.cs | Blazor wrapper component with parameters, binding, and JS interop lifecycle |
| BlueBlazor/Components/MonacoDiffEditor/MonacoDiffEditor.razor | Renders the editor host element and applies style/class |
| BlueBlazor.Docs/wwwroot/data/pages-data.json | Adds docs nav entry for the new component |
| BlueBlazor.Docs/Stories/MonacoDiffEditor/BasicUsage.razor | Basic example story |
| BlueBlazor.Docs/Stories/MonacoDiffEditor/InlineDiff.razor | Inline diff example story |
| BlueBlazor.Docs/Stories/MonacoDiffEditor/OverviewRulerEnabled.razor | Example story with overview ruler enabled |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
BlueBlazor/Components/MonacoDiffEditor/MonacoDiffEditor.razor.cs
Outdated
Show resolved
Hide resolved
| protected override async Task OnParametersSetAsync() | ||
| { | ||
| if (_currentValue != CurrentValue && _module is not null) | ||
| { | ||
| _currentValue = CurrentValue; | ||
| await _module.InvokeVoidAsync("SetModifiedValue", _id, CurrentValue); | ||
| } | ||
| } |
There was a problem hiding this comment.
OnParametersSetAsync only pushes updates to the modified model. Changes to OriginalValue and editor options like ReadOnly, RenderSideBySide, IgnoreTrimWhitespace, and RenderOverviewRuler after first render are ignored, so toggling these parameters won’t update the editor. Consider tracking previous values and either calling new JS interop methods (e.g., SetOriginalValue / UpdateOptions) or reinitializing (Destroy + Initialize) similar to MonacoEditor’s ReadOnly handling.
BlueBlazor/Components/MonacoDiffEditor/MonacoDiffEditor.razor.js
Outdated
Show resolved
Hide resolved
| var originalModel = monaco.editor.createModel(originalValue, "text/plain"); | ||
| var modifiedModel = monaco.editor.createModel(modifiedValue, "text/plain"); | ||
|
|
||
| var diffEditor = monaco.editor.createDiffEditor(element, { | ||
| enableSplitViewResizing: false, | ||
| automaticLayout: true, | ||
| renderSideBySide: renderSideBySide, | ||
| ignoreTrimWhitespace: ignoreTrimWhitespace, | ||
| renderOverviewRuler: renderOverviewRuler, | ||
| readOnly: readOnly | ||
| }); | ||
|
|
||
| diffEditor.setModel({ | ||
| original: originalModel, | ||
| modified: modifiedModel, | ||
| }); | ||
|
|
||
| if (!readOnly) { | ||
| modifiedModel.onDidChangeContent(() => { | ||
| dotNetHelper.invokeMethodAsync("InvokeChange", modifiedModel.getValue()); | ||
| }); | ||
| } | ||
|
|
||
| diffEditorCollection[id] = { diffEditor, originalModel, modifiedModel }; | ||
| } | ||
|
|
||
| export function SetModifiedValue(id, value) { | ||
| const item = diffEditorCollection[id]; | ||
| if (item?.modifiedModel) { | ||
| item.modifiedModel.setValue(value); | ||
| } | ||
| } | ||
|
|
||
| export function Destroy(id) { | ||
| const item = diffEditorCollection[id]; | ||
| if (item) { | ||
| item.diffEditor?.dispose(); | ||
| item.originalModel?.dispose(); | ||
| item.modifiedModel?.dispose(); | ||
| delete diffEditorCollection[id]; |
There was a problem hiding this comment.
This file mixes var declarations and semicolon-heavy formatting, which is inconsistent with the existing component JS modules (e.g., MonacoEditor.razor.js and TuiEditor.razor.js predominantly use const/let and omit semicolons). For consistency and easier maintenance, prefer const/let and match the prevailing formatting style in this repo.
| var originalModel = monaco.editor.createModel(originalValue, "text/plain"); | |
| var modifiedModel = monaco.editor.createModel(modifiedValue, "text/plain"); | |
| var diffEditor = monaco.editor.createDiffEditor(element, { | |
| enableSplitViewResizing: false, | |
| automaticLayout: true, | |
| renderSideBySide: renderSideBySide, | |
| ignoreTrimWhitespace: ignoreTrimWhitespace, | |
| renderOverviewRuler: renderOverviewRuler, | |
| readOnly: readOnly | |
| }); | |
| diffEditor.setModel({ | |
| original: originalModel, | |
| modified: modifiedModel, | |
| }); | |
| if (!readOnly) { | |
| modifiedModel.onDidChangeContent(() => { | |
| dotNetHelper.invokeMethodAsync("InvokeChange", modifiedModel.getValue()); | |
| }); | |
| } | |
| diffEditorCollection[id] = { diffEditor, originalModel, modifiedModel }; | |
| } | |
| export function SetModifiedValue(id, value) { | |
| const item = diffEditorCollection[id]; | |
| if (item?.modifiedModel) { | |
| item.modifiedModel.setValue(value); | |
| } | |
| } | |
| export function Destroy(id) { | |
| const item = diffEditorCollection[id]; | |
| if (item) { | |
| item.diffEditor?.dispose(); | |
| item.originalModel?.dispose(); | |
| item.modifiedModel?.dispose(); | |
| delete diffEditorCollection[id]; | |
| const originalModel = monaco.editor.createModel(originalValue, "text/plain") | |
| const modifiedModel = monaco.editor.createModel(modifiedValue, "text/plain") | |
| const diffEditor = monaco.editor.createDiffEditor(element, { | |
| enableSplitViewResizing: false, | |
| automaticLayout: true, | |
| renderSideBySide: renderSideBySide, | |
| ignoreTrimWhitespace: ignoreTrimWhitespace, | |
| renderOverviewRuler: renderOverviewRuler, | |
| readOnly: readOnly | |
| }) | |
| diffEditor.setModel({ | |
| original: originalModel, | |
| modified: modifiedModel, | |
| }) | |
| if (!readOnly) { | |
| modifiedModel.onDidChangeContent(() => { | |
| dotNetHelper.invokeMethodAsync("InvokeChange", modifiedModel.getValue()) | |
| }) | |
| } | |
| diffEditorCollection[id] = { diffEditor, originalModel, modifiedModel } | |
| } | |
| export function SetModifiedValue(id, value) { | |
| const item = diffEditorCollection[id] | |
| if (item?.modifiedModel) { | |
| item.modifiedModel.setValue(value) | |
| } | |
| } | |
| export function Destroy(id) { | |
| const item = diffEditorCollection[id] | |
| if (item) { | |
| item.diffEditor?.dispose() | |
| item.originalModel?.dispose() | |
| item.modifiedModel?.dispose() | |
| delete diffEditorCollection[id] |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Jira-Task
https://bruegmann.atlassian.net/browse/BLUE-52