@yuntijs/ui
Version:
☁️ Yunti UI - an open-source UI component library for building Cloud Native web apps
357 lines (349 loc) • 13.6 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
/* eslint-disable no-empty */
import { shikiToMonaco } from '@shikijs/monaco';
import { useEffect, useRef, useState } from 'react';
import { createHighlighter } from 'shiki';
import { languageMap } from "../../hooks/languageMap";
import { themeMap } from "../../hooks/themeMap";
import { isBrowser } from "../../utils/tools";
import { getMonaco } from "./monaco";
// @todo fill type def for monaco editor without refering monaco editor
/**
* @see https://microsoft.github.io/monaco-editor/api/index.html
*/
var CURRENT_LANGUAGE = isBrowser ? (window.locale || window.localStorage.getItem('vdev-locale') || '').replace(/_/, '-') || 'zh-CN' : 'zh-CN';
export var WORD_EDITOR_INITIALIZING = CURRENT_LANGUAGE === 'en-US' ? 'Initializing Editor' : '编辑器初始化中';
export var INITIAL_OPTIONS = {
fontSize: 12,
tabSize: 2,
fontFamily: 'Menlo, Monaco, Courier New, monospace',
folding: true,
minimap: {
enabled: false
},
autoIndent: 'advanced',
contextmenu: true,
useTabStops: true,
// wordBasedSuggestions: true,
formatOnPaste: true,
automaticLayout: true,
lineNumbers: 'on',
wordWrap: 'off',
scrollBeyondLastLine: false,
fixedOverflowWidgets: false,
snippetSuggestions: 'top',
scrollbar: {
vertical: 'auto',
horizontal: 'auto',
verticalScrollbarSize: 10,
horizontalScrollbarSize: 10
}
};
var DIFF_EDITOR_INITIAL_OPTIONS = {
fontSize: 12,
fontFamily: 'Menlo, Monaco, Courier New, monospace',
folding: true,
minimap: {
enabled: false
},
autoIndent: 'advanced',
contextmenu: true,
useTabStops: true,
formatOnPaste: true,
automaticLayout: true,
lineNumbers: 'on',
wordWrap: 'off',
scrollBeyondLastLine: false,
fixedOverflowWidgets: false,
snippetSuggestions: 'top',
scrollbar: {
vertical: 'auto',
horizontal: 'auto',
verticalScrollbarSize: 10,
horizontalScrollbarSize: 10
}
};
function usePrevious(value) {
var ref = useRef(null);
useEffect(function () {
ref.current = value;
}, [value]);
return ref.current;
}
function getOrCreateModel(monaco, value, language, path) {
if (path) {
var prevModel = monaco.editor.getModel(monaco.Uri.parse(path));
if (prevModel) {
return prevModel;
}
}
return monaco.editor.createModel(value, language, path ? monaco.Uri.parse(path) : undefined);
}
function setHighlight(monaco, language, theme) {
var themes = themeMap.filter(function (t) {
return !!t;
});
if (!theme) return;
var matchedLanguage = languageMap.includes(language) ? language : 'txt';
createHighlighter({
langs: [matchedLanguage],
themes: [theme].concat(_toConsumableArray(themes))
}).then(function (highlighter) {
monaco === null || monaco === void 0 || monaco.languages.register({
id: matchedLanguage
});
shikiToMonaco(highlighter, monaco);
});
}
export var useEditor = function useEditor(type, props) {
var editorDidMount = props.editorDidMount,
editorWillMount = props.editorWillMount,
theme = props.theme,
value = props.value,
path = props.path,
language = props.language,
saveViewState = props.saveViewState,
defaultValue = props.defaultValue,
enhancers = props.enhancers,
placeholder = props.placeholder;
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
isEditorReady = _useState2[0],
setIsEditorReady = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
focused = _useState4[0],
setFocused = _useState4[1];
var _useState5 = useState(false),
_useState6 = _slicedToArray(_useState5, 2),
loading = _useState6[0],
setLoading = _useState6[1];
var defaultValueRef = useRef(defaultValue);
var valueRef = useRef(value);
var languageRef = useRef(language || 'text');
var pathRef = useRef(path);
var previousPath = usePrevious(path);
var requireConfigRef = useRef(props.requireConfig);
var optionRef = useRef(props.options);
var monacoRef = useRef(null);
var editorRef = useRef(null);
var containerRef = useRef(null);
var typeRef = useRef(type);
var editorDidMountRef = useRef(null);
var editorWillMountRef = useRef(null);
var decomposeRef = useRef(false);
var viewStatusRef = useRef(new Map());
var enhancersRef = useRef({});
useEffect(function () {
enhancersRef.current.enhancers = enhancers;
}, [enhancers]);
useEffect(function () {
editorDidMountRef.current = editorDidMount;
}, [editorDidMount]);
useEffect(function () {
editorWillMountRef.current = editorWillMount;
}, [editorWillMount]);
useEffect(function () {
valueRef.current = value;
}, [value]);
useEffect(function () {
languageRef.current = language;
}, [language]);
useEffect(function () {
defaultValueRef.current = defaultValue;
}, [defaultValue]);
// make sure loader / editor only init once
useEffect(function () {
setLoading(true);
getMonaco(requireConfigRef.current).then(function (monaco) {
var _enhancersRef$current;
// 兼容旧版本 monaco-editor 写死 MonacoEnvironment 的问题
window.MonacoEnvironment = undefined;
if (typeof window.define === 'function' && window.define.amd) {
// make monaco-editor's loader work with webpack's umd loader
// @see https://github.com/microsoft/monaco-editor/issues/2283
delete window.define.amd;
}
monacoRef.current = monaco;
try {
var _editorWillMountRef$c;
setHighlight(monaco, languageRef.current, theme);
(_editorWillMountRef$c = editorWillMountRef.current) === null || _editorWillMountRef$c === void 0 || _editorWillMountRef$c.call(editorWillMountRef, monaco);
} catch (_unused) {}
if (!containerRef.current) {
return;
}
if (editorRef.current) {
editorRef.current.dispose();
decomposeRef.current = false;
}
var editor;
if (typeRef.current === 'single') {
var _ref, _valueRef$current;
var model = getOrCreateModel(monaco, (_ref = (_valueRef$current = valueRef.current) !== null && _valueRef$current !== void 0 ? _valueRef$current : defaultValueRef.current) !== null && _ref !== void 0 ? _ref : '', languageRef.current, pathRef.current);
editor = monaco.editor.create(containerRef.current, _objectSpread(_objectSpread({
automaticLayout: true
}, INITIAL_OPTIONS), {}, {
placeholder: placeholder
}, optionRef.current));
editor.setModel(model);
} else {
var originalModel = monaco.editor.createModel(valueRef.current, languageRef.current);
var modifiedModel = monaco.editor.createModel(valueRef.current, languageRef.current);
editor = monaco.editor.createDiffEditor(containerRef.current, _objectSpread(_objectSpread({
automaticLayout: true
}, DIFF_EDITOR_INITIAL_OPTIONS), {}, {
placeholder: placeholder
}, optionRef.current));
editor.setModel({
original: originalModel,
modified: modifiedModel
});
}
editorRef.current = editor;
(_enhancersRef$current = enhancersRef.current.enhancers) === null || _enhancersRef$current === void 0 || _enhancersRef$current.forEach(function (en) {
return en(monaco, editor);
});
try {
var _editorDidMountRef$cu;
(_editorDidMountRef$cu = editorDidMountRef.current) === null || _editorDidMountRef$cu === void 0 || _editorDidMountRef$cu.call(editorDidMountRef, monaco, editor);
} catch (_unused2) {}
if (!decomposeRef.current) {
setIsEditorReady(true);
}
}).catch(function (error) {
// eslint-disable-next-line no-console
console.error('Monaco Editor Load Error!', error);
}).then(function () {
if (!decomposeRef.current) {
setLoading(false);
}
});
}, [placeholder, theme]);
useEffect(function () {
if (!isEditorReady) {
return;
}
try {
var _monacoRef$current;
(_monacoRef$current = monacoRef.current) === null || _monacoRef$current === void 0 || _monacoRef$current.editor.setTheme(theme);
} catch (_unused3) {}
}, [isEditorReady, theme]);
// focus status
useEffect(function () {
if (!isEditorReady) {
return;
}
var editor = type === 'diff' ? editorRef.current.getModifiedEditor() : editorRef.current;
editor === null || editor === void 0 || editor.onDidFocusEditorText(function () {
if (!decomposeRef.current) {
setFocused(true);
}
});
editor === null || editor === void 0 || editor.onDidBlurEditorText(function () {
if (!decomposeRef.current) {
setFocused(false);
}
});
}, [isEditorReady, type]);
// decomposing status
useEffect(function () {
return function () {
decomposeRef.current = true;
};
}, []);
// controlled value -- diff mode / without path only
useEffect(function () {
var _ref2, _monacoRef$current2, _editor$getOption;
if (!isEditorReady) {
return;
}
if (type !== 'diff' && !!path) {
return;
}
var editor = type === 'diff' ? editorRef.current.getModifiedEditor() : editorRef.current;
var nextValue = (_ref2 = value !== null && value !== void 0 ? value : defaultValueRef.current) !== null && _ref2 !== void 0 ? _ref2 : '';
var readOnly = (_monacoRef$current2 = monacoRef.current) === null || _monacoRef$current2 === void 0 ? void 0 : _monacoRef$current2.editor.EditorOption.readOnly;
if (readOnly && editor !== null && editor !== void 0 && (_editor$getOption = editor.getOption) !== null && _editor$getOption !== void 0 && _editor$getOption.call(editor, readOnly)) {
editor === null || editor === void 0 || editor.setValue(nextValue);
} else if (value !== (editor === null || editor === void 0 ? void 0 : editor.getValue())) {
editor === null || editor === void 0 || editor.executeEdits('', [{
range: editor === null || editor === void 0 ? void 0 : editor.getModel().getFullModelRange(),
text: nextValue,
forceMoveMarkers: true
}]);
editor === null || editor === void 0 || editor.pushUndoStop();
}
}, [isEditorReady, path, type, value]);
// multi-model && controlled value (shouldn't be diff mode)
useEffect(function () {
var _valueRef$current2, _editorRef$current;
if (!isEditorReady) {
return;
}
if (type === 'diff') {
return;
}
if (path === previousPath) {
return;
}
var model = getOrCreateModel(monacoRef.current, (_valueRef$current2 = valueRef.current) !== null && _valueRef$current2 !== void 0 ? _valueRef$current2 : defaultValueRef.current, languageRef.current, path);
var editor = editorRef.current;
if (valueRef.current !== null && valueRef.current !== undefined && model.getValue() !== valueRef.current) {
model.setValue(valueRef.current);
}
if (model !== ((_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.getModel())) {
if (saveViewState) {
viewStatusRef.current.set(previousPath, editor.saveViewState());
}
editor.setModel(model);
if (saveViewState) {
editor.restoreViewState(viewStatusRef.current.get(path));
}
}
}, [isEditorReady, value, path, previousPath, type, saveViewState]);
var retEditorRef = editorRef;
return {
isEditorReady: isEditorReady,
focused: focused,
loading: loading,
containerRef: containerRef,
monacoRef: monacoRef,
editorRef: retEditorRef,
valueRef: valueRef
};
};
export var useFullScreen = function useFullScreen(editor) {
var _useState7 = useState(false),
_useState8 = _slicedToArray(_useState7, 2),
isFullScreen = _useState8[0],
setIsFullScreen = _useState8[1];
var fullScreen = function fullScreen() {
if (isFullScreen) {
setIsFullScreen(false);
editor === null || editor === void 0 || editor.updateOptions(_objectSpread(_objectSpread({}, editor === null || editor === void 0 ? void 0 : editor.getOptions()), {}, {
minimap: {
enabled: false
}
}));
editor === null || editor === void 0 || editor.layout();
return;
}
setIsFullScreen(true);
// 更新小地图配置
editor === null || editor === void 0 || editor.updateOptions(_objectSpread(_objectSpread({}, editor === null || editor === void 0 ? void 0 : editor.getOptions()), {}, {
minimap: {
enabled: true
}
}));
editor === null || editor === void 0 || editor.layout();
};
return {
isFullScreen: isFullScreen,
fullScreen: fullScreen
};
};