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  );