github.com/argoproj/argo-cd/v3@v3.2.1/ui/src/app/shared/components/monaco-editor.tsx (about) 1 import * as React from 'react'; 2 3 import * as monacoEditor from 'monaco-editor'; 4 import {services} from '../services'; 5 import {getTheme, useSystemTheme} from '../utils'; 6 7 export interface EditorInput { 8 text: string; 9 language?: string; 10 } 11 12 export interface MonacoProps { 13 minHeight?: number; 14 vScrollBar: boolean; 15 editor?: { 16 options?: monacoEditor.editor.IEditorOptions; 17 input: EditorInput; 18 getApi?: (api: monacoEditor.editor.IEditor) => any; 19 }; 20 } 21 22 function IsEqualInput(first?: EditorInput, second?: EditorInput) { 23 return first && second && first.text === second.text && (first.language || '') === (second.language || ''); 24 } 25 26 const DEFAULT_LINE_HEIGHT = 18; 27 28 const MonacoEditorLazy = React.lazy(() => 29 import('monaco-editor').then(monaco => { 30 const Component = (props: MonacoProps) => { 31 const [height, setHeight] = React.useState(0); 32 const [theme, setTheme] = React.useState('dark'); 33 34 React.useEffect(() => { 35 const destroySystemThemeListener = useSystemTheme(systemTheme => { 36 if (theme === 'auto') { 37 monaco.editor.setTheme(systemTheme === 'dark' ? 'vs-dark' : 'vs'); 38 } 39 }); 40 41 return () => { 42 destroySystemThemeListener(); 43 }; 44 }, [theme]); 45 46 React.useEffect(() => { 47 const subscription = services.viewPreferences.getPreferences().subscribe(preferences => { 48 setTheme(preferences.theme); 49 50 monaco.editor.setTheme(getTheme(preferences.theme) === 'dark' ? 'vs-dark' : 'vs'); 51 }); 52 53 return () => { 54 subscription.unsubscribe(); 55 }; 56 }, []); 57 58 return ( 59 <div 60 style={{ 61 height: `${Math.max(props.minHeight || 0, height + 100)}px`, 62 overflowY: 'hidden' 63 }} 64 ref={el => { 65 if (el) { 66 const container = el as { 67 editorApi?: monacoEditor.editor.IEditor; 68 prevEditorInput?: EditorInput; 69 }; 70 if (props.editor) { 71 if (!container.editorApi) { 72 const editor = monaco.editor.create(el, { 73 ...props.editor.options, 74 scrollBeyondLastLine: props.vScrollBar, 75 scrollbar: { 76 alwaysConsumeMouseWheel: false, 77 vertical: props.vScrollBar ? 'visible' : 'hidden' 78 } 79 }); 80 81 container.editorApi = editor; 82 } 83 84 const model = monaco.editor.createModel(props.editor.input.text, props.editor.input.language); 85 const lineCount = model.getLineCount(); 86 setHeight(lineCount * DEFAULT_LINE_HEIGHT); 87 88 if (!IsEqualInput(container.prevEditorInput, props.editor.input)) { 89 container.prevEditorInput = props.editor.input; 90 container.editorApi.setModel(model); 91 } 92 container.editorApi.updateOptions(props.editor.options); 93 container.editorApi.layout(); 94 if (props.editor.getApi) { 95 props.editor.getApi(container.editorApi); 96 } 97 } 98 } 99 }} 100 /> 101 ); 102 }; 103 104 return { 105 default: Component 106 }; 107 }) 108 ); 109 110 export const MonacoEditor = (props: MonacoProps) => ( 111 <React.Suspense fallback={<div>Loading...</div>}> 112 <MonacoEditorLazy {...props} /> 113 </React.Suspense> 114 );