Skip to content

Commit

Permalink
fix: update editor resize handler to incorporate the new
Browse files Browse the repository at this point in the history
contentSizeChange event, adopt the new padding option to do away with
the TopMargin hack

Monaco 0.20 introduced a `getContentHeight` API that enables us to get
the current editor height without resorting to hacks around line counts.
This also handles cases such as code folding. See this issue for
details: microsoft/monaco-editor#794

Also added more type checking in the editor instantiation, leveraged the
new padding option to do away with the TopMargin work around.
  • Loading branch information
vivek1729 committed Jul 24, 2021
1 parent 2413d2a commit 3dc8b93
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 55 deletions.
60 changes: 17 additions & 43 deletions packages/monaco-editor/src/MonacoEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,42 +118,31 @@ export default class MonacoEditor extends React.Component<IMonacoProps> {
if (this.props.onChange) {
this.props.onChange(this.editor.getValue(), e);
}

this.calculateHeight();
}
}

/**
* Adjust the height of editor
* Adjust the height of editor container
*
* @param height Expected height of the editor container
* We check the editor's content height and set the container height to match it
*
* @remarks
* The way to determine how many lines we should display in editor:
* If numberOfLines is not set or set to 0, we adjust the height to fit the content
* If numberOfLines is specified we respect that setting
*/
calculateHeight() {
calculateHeight(height?: number) {
// Make sure we have an editor
if (!this.editor) {
return;
}

// Make sure we have a model
const model = this.editor.getModel();
if (!model) {
return;
if (typeof height === "undefined") {
// Retrieve content height directly from the editor if no height provided as param
height = this.editor.getContentHeight();
}

if (this.editorContainerRef && this.editorContainerRef.current) {
const expectedLines = this.props.numberOfLines || model.getLineCount();
// The find & replace menu takes up 2 lines, that is why 2 line is set as the minimum number of lines
const finalizedLines = Math.max(expectedLines, 1) + 1;
const lineHeight = this.editor.getOption(monaco.editor.EditorOption.lineHeight);
const contentHeight = finalizedLines * lineHeight;

if (this.contentHeight !== contentHeight) {
this.editorContainerRef.current.style.height = contentHeight + "px";
if (this.contentHeight !== height) {
this.editorContainerRef.current.style.height = height + "px";
this.editor.layout();
this.contentHeight = contentHeight;
this.contentHeight = height;
}
}
}
Expand Down Expand Up @@ -229,8 +218,6 @@ export default class MonacoEditor extends React.Component<IMonacoProps> {
this.props.onDidCreateEditor(this.editor);
}

this.addEditorTopMargin();

// Handle custom keyboard shortcuts
if (this.editor && this.props.shortcutsHandler && this.props.shortcutsOptions) {
this.props.shortcutsHandler(this.editor, this.props.shortcutsOptions);
Expand Down Expand Up @@ -265,7 +252,12 @@ export default class MonacoEditor extends React.Component<IMonacoProps> {
this.editor.trigger("redo-event", "redo", {});
}
});

// Resize Editor container on content size change
this.editor.onDidContentSizeChange((info) => {
if (info.contentHeightChanged) {
this.calculateHeight(info.contentHeight);
}
});
this.editor.onDidChangeModelContent(this.onDidChangeModelContent);
this.editor.onDidFocusEditorText(this.onFocus);
this.editor.onDidBlurEditorText(this.onBlur);
Expand All @@ -290,23 +282,6 @@ export default class MonacoEditor extends React.Component<IMonacoProps> {
}
}

addEditorTopMargin() {
if (this.editor) {
// Monaco editor doesn't have margins
// https://github.com/notable/notable/issues/551
// This is a workaround to add an editor area 12px padding at the top
// so that cursors decorators and context menus can be rendered correctly.
this.editor.changeViewZones((changeAccessor) => {
const domNode = document.createElement("div");
changeAccessor.addZone({
afterLineNumber: 0,
heightInPx: 12,
domNode
});
});
}
}

/**
* Tells editor to check the surrounding container size and resize itself appropriately
*/
Expand Down Expand Up @@ -363,7 +338,6 @@ export default class MonacoEditor extends React.Component<IMonacoProps> {

// Set new model targeting the changed language.
editor.setModel(monaco.editor.createModel(value, language, newUri));
this.addEditorTopMargin();

// Restore cursor position to new model.
if (position) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { connect } from "react-redux";

import { selectors, AppState, ContentRef } from "@nteract/core";
import MonacoEditor, {LightThemeName, DarkThemeName, Mode, mapCodeMirrorModeToMonaco} from "@nteract/monaco-editor";
import * as monaco from "@nteract/monaco-editor";

import { userTheme } from "../../config-options";
import { Channels } from "@nteract/messaging";
Expand All @@ -25,12 +25,12 @@ function getMonacoTheme(theme?: string) : string {
if (typeof theme === "string") {
switch (theme) {
case "dark":
return DarkThemeName;
return monaco.DarkThemeName;
default:
return LightThemeName;
return monaco.LightThemeName;
}
} else {
return LightThemeName;
return monaco.LightThemeName;
}
}

Expand All @@ -39,15 +39,15 @@ const makeMapStateToProps = (initialState: AppState, ownProps: ComponentProps) =
function mapStateToProps(state: any) {
const model = selectors.model(state, { contentRef });
const theme = userTheme(state) || "vs";
let wordWrap = "on";
let editorMode: any = Mode.raw;
let wordWrap:monaco.editor.IEditorOptions["wordWrap"] = "on";
let editorMode: string = monaco.Mode.raw;
if (model && model.type === "notebook") {
const cell = selectors.notebook.cellById(model, { id });
if (cell) {
// Bring all changes to the options based on cell type
switch (cell.cell_type) {
case "markdown":
editorMode = Mode.markdown;
editorMode = monaco.Mode.markdown;
break;
case "code": {
wordWrap = "off";
Expand All @@ -59,18 +59,22 @@ const makeMapStateToProps = (initialState: AppState, ownProps: ComponentProps) =
kernel && kernel.info
? kernel.info.codemirrorMode
: selectors.notebook.codeMirrorMode(model);
editorMode = mapCodeMirrorModeToMonaco(mode);
editorMode = monaco.mapCodeMirrorModeToMonaco(mode);
break;
}
default:
editorMode = Mode.raw;
editorMode = monaco.Mode.raw;
break;
}
}
}
const defaultEditorOptions = {
const defaultEditorOptions: monaco.editor.IEditorOptions = {
wordWrap,
autoClosingBrackets: "never"
autoClosingBrackets: "never",
padding: {
top: 12,
bottom: 5
}
}
const options = {
...defaultEditorOptions,
Expand All @@ -91,4 +95,4 @@ const makeMapStateToProps = (initialState: AppState, ownProps: ComponentProps) =
return mapStateToProps;
};

export default connect(makeMapStateToProps)(MonacoEditor);
export default connect(makeMapStateToProps)(monaco.default);

0 comments on commit 3dc8b93

Please sign in to comment.