mirror of https://github.com/buster-so/buster.git
166 lines
4.8 KiB
TypeScript
166 lines
4.8 KiB
TypeScript
'use client';
|
|
|
|
//https://github.com/popsql/monaco-sql-languages/blob/main/example/src/App.js#L2
|
|
//https://dtstack.github.io/monaco-sql-languages/
|
|
|
|
import React, { forwardRef, useMemo } from 'react';
|
|
import { CircleSpinnerLoaderContainer } from '../../loaders/CircleSpinnerLoaderContainer';
|
|
import { useMemoizedFn } from '@/hooks';
|
|
import { cn } from '@/lib/classMerge';
|
|
import type { editor } from 'monaco-editor/esm/vs/editor/editor.api';
|
|
import './MonacoWebWorker';
|
|
import { configureMonacoToUseYaml } from './yamlHelper';
|
|
|
|
//import GithubLightTheme from 'monaco-themes/themes/Github Light.json';
|
|
//import NightOwnTheme from 'monaco-themes/themes/Night Owl.json';
|
|
//https://github.com/brijeshb42/monaco-ace-tokenizer
|
|
|
|
import { Editor as DynamicEditor } from '@monaco-editor/react';
|
|
import { useTheme } from 'next-themes';
|
|
|
|
export interface AppCodeEditorProps {
|
|
className?: string;
|
|
onChangeEditorHeight?: (height: number) => void;
|
|
height?: string;
|
|
isDarkMode?: boolean;
|
|
onMount?: (editor: editor.IStandaloneCodeEditor, monaco: typeof import('monaco-editor')) => void;
|
|
value?: string;
|
|
onChange?: (value: string) => void;
|
|
style?: React.CSSProperties;
|
|
language?: string;
|
|
readOnly?: boolean;
|
|
readOnlyMessage?: string;
|
|
defaultValue?: string;
|
|
monacoEditorOptions?: editor.IStandaloneEditorConstructionOptions;
|
|
variant?: 'bordered' | null;
|
|
onMetaEnter?: () => void;
|
|
}
|
|
|
|
export interface AppCodeEditorHandle {
|
|
resetCodeEditor: () => void;
|
|
}
|
|
|
|
export const AppCodeEditor = forwardRef<AppCodeEditorHandle, AppCodeEditorProps>(
|
|
(
|
|
{
|
|
style,
|
|
monacoEditorOptions,
|
|
defaultValue = '',
|
|
language = 'pgsql',
|
|
className,
|
|
readOnly,
|
|
onChange,
|
|
onChangeEditorHeight,
|
|
height = '100%',
|
|
isDarkMode,
|
|
onMount,
|
|
value,
|
|
readOnlyMessage = 'Editing code is not allowed',
|
|
variant,
|
|
onMetaEnter
|
|
},
|
|
ref
|
|
) => {
|
|
// const { cx, styles } = useStyles();
|
|
|
|
const isDarkModeContext = useTheme()?.theme === 'dark';
|
|
const useDarkMode = isDarkMode ?? isDarkModeContext;
|
|
|
|
const memoizedMonacoEditorOptions: editor.IStandaloneEditorConstructionOptions = useMemo(() => {
|
|
return {
|
|
language,
|
|
readOnly,
|
|
folding: false,
|
|
lineDecorationsWidth: 15,
|
|
lineNumbersMinChars: 3,
|
|
tabSize: 7,
|
|
wordWrap: 'off',
|
|
wordWrapColumn: 999,
|
|
wrappingStrategy: 'simple',
|
|
overviewRulerLanes: 0,
|
|
scrollBeyondLastLine: false,
|
|
minimap: {
|
|
enabled: false
|
|
},
|
|
padding: {
|
|
top: 10
|
|
},
|
|
hover: {
|
|
enabled: false
|
|
},
|
|
contextmenu: false,
|
|
readOnlyMessage: {
|
|
value: readOnlyMessage
|
|
},
|
|
...monacoEditorOptions
|
|
};
|
|
}, [readOnlyMessage, monacoEditorOptions]);
|
|
|
|
const onMountCodeEditor = useMemoizedFn(
|
|
async (editor: editor.IStandaloneCodeEditor, monaco: typeof import('monaco-editor')) => {
|
|
const [GithubLightTheme, NightOwlTheme] = await Promise.all([
|
|
(await import('./themes/github_light_theme')).default,
|
|
(await import('./themes/tomorrow_night_theme')).default
|
|
]);
|
|
|
|
if (language === 'yaml') {
|
|
await configureMonacoToUseYaml(monaco);
|
|
}
|
|
|
|
monaco.editor.defineTheme('github-light', GithubLightTheme);
|
|
monaco.editor.defineTheme('night-owl', NightOwlTheme);
|
|
editor.updateOptions({
|
|
theme: useDarkMode ? 'night-owl' : 'github-light'
|
|
});
|
|
if (onChangeEditorHeight) {
|
|
editor.onDidContentSizeChange(() => {
|
|
const contentHeight = editor.getContentHeight();
|
|
onChangeEditorHeight(contentHeight);
|
|
});
|
|
}
|
|
onMount?.(editor, monaco);
|
|
|
|
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
|
|
onMetaEnter?.();
|
|
});
|
|
}
|
|
);
|
|
|
|
const onChangeCodeEditor = useMemoizedFn((v: string | undefined) => {
|
|
if (!readOnly) {
|
|
onChange?.(v || '');
|
|
}
|
|
});
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'app-code-editor relative h-full w-full border',
|
|
variant === 'bordered' && 'overflow-hidden border',
|
|
className
|
|
)}
|
|
style={style}>
|
|
<DynamicEditor
|
|
key={useDarkMode ? 'dark' : 'light'}
|
|
height={height}
|
|
loading={<LoadingContainer />}
|
|
language={language}
|
|
className={className}
|
|
defaultValue={defaultValue}
|
|
value={value}
|
|
theme={useDarkMode ? 'night-owl' : 'github-light'}
|
|
onMount={onMountCodeEditor}
|
|
onChange={onChangeCodeEditor}
|
|
options={memoizedMonacoEditorOptions}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
AppCodeEditor.displayName = 'AppCodeEditor';
|
|
|
|
const LoadingContainer = React.memo(() => {
|
|
return <CircleSpinnerLoaderContainer />;
|
|
});
|
|
LoadingContainer.displayName = 'LoadingContainer';
|