@nteract/monaco-editor
Version:
A React component for the monaco editor, tailored for nteract
210 lines (209 loc) • 8.26 kB
TypeScript
import { Channels } from "@nteract/messaging";
import { CellType, CellId } from "@nteract/commutable";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import * as React from "react";
import { ContentRef } from "@nteract/core";
import { IEditor } from "./layoutSchedule";
import * as intersectionObserver from "./intersectionObserver";
export declare type IModelContentChangedEvent = monaco.editor.IModelContentChangedEvent;
/**
* Settings for configuring keyboard shortcuts with Monaco
*/
export interface IMonacoShortCutProps {
cellType: CellType;
cellFocusDirection: string | undefined;
setCellFocusDirection: (direction?: string) => void;
focusCell: (payload: {
id: CellId;
contentRef: ContentRef;
}) => void;
focusAboveCellCommandMode: () => void;
focusBelowCellCommandMode: () => void;
insertCellBelow: (contentRef: ContentRef, cellType: CellType) => void;
executeCell: () => void;
focusEditor: () => void;
focusNextCellEditor: (setPosition?: boolean) => void;
focusPreviousCellEditor: () => void;
unfocusEditor: () => void;
}
/**
* Common props passed to the editor component
*/
export interface IMonacoComponentProps {
id: string;
contentRef: ContentRef;
theme: string;
readOnly?: boolean;
channels?: Channels | undefined;
value: string;
editorType?: string;
editorFocused?: boolean;
onChange?: (value: string, event?: any) => void;
onFocusChange?: (focus: boolean) => void;
}
/**
* Props passed for configuring Monaco Editor
*/
export interface IMonacoConfiguration {
/**
* modelUri acts an identifier to query the editor model
* without being tied to the UI
* Calling the getModel(modelUri) API
*/
modelUri?: monaco.Uri;
enableCompletion?: boolean;
shouldRegisterDefaultCompletion?: boolean;
onCursorPositionChange?: (selection: monaco.ISelection | null) => void;
onRegisterDocumentFormattingEditProvider?: (languageId: string) => void;
enableFormatting?: boolean;
onRegisterCompletionProvider?: (languageId: string) => void;
language: string;
lineNumbers?: boolean;
/** For better perf in resizing, when this is true, defer and batch the layout changes to avoid each editor layouting change cause individual browser refresh */
batchLayoutChanges?: boolean;
/**
* whether we call editor.layout() when the container has been resized even if the editor is not focused
* this way we don't need special CSS styles overriding monaco's built-in styles to make the editor resize
* This is better used together with batchLayoutChanges set to true so all editors layouts changes can be batched for better perf
*/
shouldUpdateLayoutWhenNotFocused?: boolean;
/**
* whether we should call editor.layout() when the container is not in the viewport
* default is false
*/
skipLayoutWhenNotInViewport?: boolean;
/**
* whether we should call editor.layout() when the container or its parent is hidden by "display:none" or the height is set to 0
* default is false
*/
skipLayoutWhenHidden?: boolean;
/** automatically adjust size to fit content, default is true */
autoFitContentHeight?: boolean;
/** set a max content height in number of pixels, this only works when autoFitContentHeight is true*/
maxContentHeight?: number;
/**
* Set the initial dimensions of the editor layout and the container
*/
initialDimension?: monaco.editor.IDimension;
/** set height of editor to fit the specified number of lines in display */
numberOfLines?: number;
indentSize?: number;
tabSize?: number;
options?: monaco.editor.IEditorOptions;
shortcutsOptions?: IMonacoShortCutProps;
shortcutsHandler?: (editor: monaco.editor.IStandaloneCodeEditor, settings?: IMonacoShortCutProps) => void;
cursorPositionHandler?: (editor: monaco.editor.IStandaloneCodeEditor, settings?: IMonacoProps) => void;
commandHandler?: (editor: monaco.editor.IStandaloneCodeEditor) => void;
onDidCreateEditor?: (editor: monaco.editor.IStandaloneCodeEditor) => void;
}
/**
* Initial props for Monaco Editor received from agnostic component
*/
export declare type IMonacoProps = IMonacoComponentProps & IMonacoConfiguration;
/**
* Creates a MonacoEditor instance
*/
export default class MonacoEditor extends React.Component<IMonacoProps> implements IEditor, intersectionObserver.IIntersectable {
editor?: monaco.editor.IStandaloneCodeEditor;
editorContainerRef: React.RefObject<HTMLDivElement>;
private cursorPositionListener?;
private mouseMoveListener?;
private intersectObservation?;
private isInViewport;
private deferredLayoutRequest;
private deferredLayoutDimension?;
constructor(props: IMonacoProps);
onDidChangeModelContent(e: monaco.editor.IModelContentChangedEvent): void;
readEditorDomSize(): monaco.editor.IDimension | undefined;
getLayoutDimension(): monaco.editor.IDimension | undefined;
isContainerHidden(): boolean;
/**
* write the layout to the DOM
*/
layout(layout: monaco.editor.IDimension): void;
/**
* Implementation for IEditor from layoutSchedule, could cause a DOM read operation
*/
shouldLayout(): boolean;
requestLayout(dimension?: monaco.editor.IDimension): void;
onIntersecting(isIntersecting: boolean): void;
updateIntersectRegistration(): void;
componentDidMount(): void;
/**
* Tells editor to check the surrounding container size and resize itself appropriately
*/
onResize(): void;
componentDidUpdate(prevProps: IMonacoProps): void;
componentWillUnmount(): void;
render(): JSX.Element;
/**
* Register default kernel-based completion provider.
* @param language Language
*/
registerDefaultCompletionProvider(language: string): void;
private onFocus;
private onBlur;
private registerCursorListener;
private unregisterCursorListener;
/**
* Toggle editor options based on if the editor is in active state (i.e. focused).
* When the editor is not active, we want to deactivate some of the visual noise.
* @param isActive Whether editor is active.
*/
private toggleEditorOptions;
/**
* Register language features for target language. Call before setting language type to model.
*/
private registerCompletionProvider;
private registerDocumentFormatter;
/**
* This will hide the parameter widget if the user is not hovering over
* the parameter widget for this monaco editor.
*
* Notes: See issue https://github.com/microsoft/vscode-python/issues/7851 for further info.
* Hide the parameter widget if the following conditions have been met:
* - Editor doesn't have focus
* - Mouse is not over (hovering) the parameter widget
*
* This method is only used for blurring at the moment given that parameter widgets from
* other cells are hidden by mouse move events.
*
* @private
* @returns
* @memberof MonacoEditor
*/
private hideParameterWidget;
/**
* Hides widgets such as parameters and hover, that belong to a given parent HTML element.
*
* @private
* @param {HTMLDivElement} widgetParent
* @param {string[]} selectors
* @memberof MonacoEditor
*/
private hideWidgets;
/**
* Hides the parameters widgets related to other monaco editors.
* Use this to ensure we only display parameters widgets for current editor (by hiding others).
*
* @private
* @returns
* @memberof MonacoEditor
*/
private hideAllOtherParameterWidgets;
/**
* Return true if (x,y) coordinates overlap with an element's bounding rect.
* @param {HTMLDivElement} element
* @param {number} x
* @param {number} y
* @param {number} padding
*/
private coordsInsideElement;
/**
* Hide all other widgets belonging to other cells only if the currently active
* parameter widget (at most one) is being hovered by the user.
* @param {number} x
* @param {number} y
*/
private handleCoordsOutsideWidgetActiveRegion;
}