UNPKG

@nteract/monaco-editor

Version:

A React component for the monaco editor, tailored for nteract

210 lines (209 loc) 8.26 kB
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; }