Skip to content

bek-BLUE-52: Add MonacoDiffEditor component#20

Open
bek-bsw wants to merge 5 commits intomasterfrom
bek-BLUE-52
Open

bek-BLUE-52: Add MonacoDiffEditor component#20
bek-bsw wants to merge 5 commits intomasterfrom
bek-BLUE-52

Conversation

@bek-bsw
Copy link
Copy Markdown

@bek-bsw bek-bsw commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 MonacoDiffEditor component 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.

Comment on lines +77 to +84
protected override async Task OnParametersSetAsync()
{
if (_currentValue != CurrentValue && _module is not null)
{
_currentValue = CurrentValue;
await _module.InvokeVoidAsync("SetModifiedValue", _id, CurrentValue);
}
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +77
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];
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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]

Copilot uses AI. Check for mistakes.
bek-bsw and others added 4 commits March 24, 2026 12:09
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants