@uiw/react-monacoeditor
Version:
Monaco Editor component for React.
136 lines • 4.33 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
var _excluded = ["width", "height", "value", "theme", "language", "autoComplete", "options", "editorDidMount", "onChange", "defaultValue"];
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useImperativeHandle, useEffect, useRef, useState, useCallback } from 'react';
import * as monaco from 'monaco-editor';
import { editor, languages } from 'monaco-editor';
// @ts-ignore
import codicon from 'monaco-editor/min/vs/base/browser/ui/codicons/codicon/codicon.ttf';
import { jsx as _jsx } from "react/jsx-runtime";
function noop() {}
export function loadFont(_x, _x2) {
return _loadFont.apply(this, arguments);
}
function _loadFont() {
_loadFont = _asyncToGenerator(function* (fontFamily, url) {
var font = new FontFace(fontFamily, "local(" + fontFamily + "), url(" + url + ")");
// wait for font to be loaded
yield font.load();
// add font to document
document.fonts.add(font);
});
return _loadFont.apply(this, arguments);
}
function MonacoEditor(props, ref) {
var {
width = '100%',
height = '100%',
value = '',
theme = '',
language = 'javascript',
autoComplete,
options = {},
editorDidMount = noop,
onChange = noop,
defaultValue = ''
} = props,
other = _objectWithoutPropertiesLoose(props, _excluded);
options.language = language || options.language;
options.theme = theme || options.theme;
var [val, setVal] = useState(defaultValue);
var container = useRef();
var $editor = useRef();
useImperativeHandle(ref, () => ({
container: container.current || null,
editor: $editor.current,
monaco
}));
useEffect(() => setVal(value), [value]);
useEffect(() => {
if ($editor.current) {
$editor.current.setValue(val);
}
}, [val]);
useEffect(() => {
if (options.theme) {
editor.setTheme(options.theme);
}
}, [options.theme]);
useEffect(() => {
var CPDisposable;
if ($editor.current && autoComplete) {
if ($editor.current.getModel() && $editor.current.getPosition()) {
CPDisposable = languages.registerCompletionItemProvider(language, {
provideCompletionItems: (model, position) => {
return {
suggestions: autoComplete(model, position)
};
}
});
}
}
return () => {
CPDisposable && CPDisposable.dispose();
};
}, [language, autoComplete]);
useEffect(() => {
if ($editor.current) {
var model = $editor.current.getModel();
if (model) {
editor.setModelLanguage(model, props.language || '');
}
}
}, [language]);
useEffect(() => {
if ($editor.current) {
var optionsRaw = $editor.current.getRawOptions();
Object.keys(optionsRaw).forEach(keyname => {
var propsOpt = options[keyname];
if (optionsRaw[keyname] !== propsOpt && propsOpt !== undefined) {
$editor.current.updateOptions({
[keyname]: propsOpt
});
}
});
}
}, [options]);
var refElement = useCallback(node => {
if (node !== null) {
container.current = node;
$editor.current = editor.create(node, _extends({
value: val,
language
}, options));
if (options.theme) {
editor.setTheme(options.theme);
}
// After initializing monaco editor
editorDidMount($editor.current, monaco);
$editor.current.onDidChangeModelContent(event => {
var valueCurrent = $editor.current.getValue();
// Always refer to the latest value
onChange(valueCurrent, event);
});
loadFont('codicon', codicon).catch(e => {
if (e) {
throw new Error('Failed to load font codicon!!');
}
});
} else {
if ($editor.current) {
$editor.current.dispose();
$editor.current = undefined;
}
}
}, []);
return /*#__PURE__*/_jsx("div", _extends({}, other, {
ref: refElement,
style: _extends({}, other.style, {
width,
height
})
}));
}
export default /*#__PURE__*/React.forwardRef(MonacoEditor);