Improve CodeEditor wrapper (#114500)

This commit is contained in:
Anton Dosov 2021-10-15 12:47:18 +02:00 committed by GitHub
parent 033dfb3c22
commit 21760d4832
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 55 deletions

View file

@ -104,7 +104,7 @@ pageLoadAssetSize:
dataViews: 41532 dataViews: 41532
expressions: 140958 expressions: 140958
fieldFormats: 65209 fieldFormats: 65209
kibanaReact: 99422 kibanaReact: 84422
share: 71239 share: 71239
uiActions: 35121 uiActions: 35121
dataEnhanced: 24980 dataEnhanced: 24980

View file

@ -594,9 +594,13 @@ exports[`Source Viewer component renders json code editor 1`] = `
fallback={<Fallback />} fallback={<Fallback />}
> >
<Fallback> <Fallback>
<EuiDelayRender <div
delay={500} style={Object {}}
/> >
<EuiDelayRender
delay={500}
/>
</div>
</Fallback> </Fallback>
</Suspense> </Suspense>
</EuiErrorBoundary> </EuiErrorBoundary>

View file

@ -14,6 +14,7 @@ import { monaco } from '@kbn/monaco';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react'; import { FormattedMessage } from '@kbn/i18n/react';
import classNames from 'classnames'; import classNames from 'classnames';
import './register_languages';
import { import {
DARK_THEME, DARK_THEME,

View file

@ -0,0 +1,39 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import darkTheme from '@elastic/eui/dist/eui_theme_dark.json';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { EuiFormControlLayout } from '@elastic/eui';
import { CodeEditor, Props } from './code_editor';
/**
* Renders a Monaco code editor in the same style as other EUI form fields.
*/
export const CodeEditorField: React.FunctionComponent<Props> = (props) => {
const { width, height, options, fullWidth, useDarkTheme } = props;
const theme = useDarkTheme ? darkTheme : lightTheme;
const style = {
width,
height,
backgroundColor: options?.readOnly
? theme.euiFormBackgroundReadOnlyColor
: theme.euiFormBackgroundColor,
};
return (
<EuiFormControlLayout
append={<div hidden />}
style={style}
readOnly={options?.readOnly}
fullWidth={fullWidth}
>
<CodeEditor {...props} transparentBackground />
</EuiFormControlLayout>
);
};

View file

@ -7,28 +7,31 @@
*/ */
import React from 'react'; import React from 'react';
import { import { EuiDelayRender, EuiErrorBoundary, EuiLoadingContent } from '@elastic/eui';
EuiDelayRender,
EuiErrorBoundary,
EuiLoadingContent,
EuiFormControlLayout,
} from '@elastic/eui';
import darkTheme from '@elastic/eui/dist/eui_theme_dark.json';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { useUiSetting } from '../ui_settings';
import { Props } from './code_editor';
import './register_languages';
export * from './languages'; import { useUiSetting } from '../ui_settings';
import type { Props } from './code_editor';
export * from './languages/constants';
const LazyBaseEditor = React.lazy(() => import('./code_editor')); const LazyBaseEditor = React.lazy(() => import('./code_editor'));
const LazyCodeEditorField = React.lazy(() =>
const Fallback = () => ( import('./code_editor_field').then((m) => ({ default: m.CodeEditorField }))
<EuiDelayRender>
<EuiLoadingContent lines={3} />
</EuiDelayRender>
); );
const Fallback: React.FunctionComponent<{ height: Props['height'] }> = ({ height }) => {
return (
<>
{/* when height is known, set minHeight to avoid layout shift */}
<div style={height ? { minHeight: height } : {}}>
<EuiDelayRender>
<EuiLoadingContent lines={3} />
</EuiDelayRender>
</div>
</>
);
};
export type CodeEditorProps = Props; export type CodeEditorProps = Props;
/** /**
@ -40,7 +43,7 @@ export const CodeEditor: React.FunctionComponent<Props> = (props) => {
const darkMode = useUiSetting<boolean>('theme:darkMode'); const darkMode = useUiSetting<boolean>('theme:darkMode');
return ( return (
<EuiErrorBoundary> <EuiErrorBoundary>
<React.Suspense fallback={<Fallback />}> <React.Suspense fallback={<Fallback height={props.height} />}>
<LazyBaseEditor {...props} useDarkTheme={darkMode} /> <LazyBaseEditor {...props} useDarkTheme={darkMode} />
</React.Suspense> </React.Suspense>
</EuiErrorBoundary> </EuiErrorBoundary>
@ -51,38 +54,11 @@ export const CodeEditor: React.FunctionComponent<Props> = (props) => {
* Renders a Monaco code editor in the same style as other EUI form fields. * Renders a Monaco code editor in the same style as other EUI form fields.
*/ */
export const CodeEditorField: React.FunctionComponent<Props> = (props) => { export const CodeEditorField: React.FunctionComponent<Props> = (props) => {
const { width, height, options, fullWidth } = props;
const darkMode = useUiSetting<boolean>('theme:darkMode'); const darkMode = useUiSetting<boolean>('theme:darkMode');
const theme = darkMode ? darkTheme : lightTheme;
const style = {
width,
height,
backgroundColor: options?.readOnly
? theme.euiFormBackgroundReadOnlyColor
: theme.euiFormBackgroundColor,
};
return ( return (
<EuiErrorBoundary> <EuiErrorBoundary>
<React.Suspense <React.Suspense fallback={<Fallback height={props.height} />}>
fallback={ <LazyCodeEditorField {...props} useDarkTheme={darkMode} />
<EuiFormControlLayout
append={<div hidden />}
style={{ ...style, padding: theme.paddingSizes.m }}
readOnly={options?.readOnly}
>
<Fallback />
</EuiFormControlLayout>
}
>
<EuiFormControlLayout
append={<div hidden />}
style={style}
readOnly={options?.readOnly}
fullWidth={fullWidth}
>
<LazyBaseEditor {...props} useDarkTheme={darkMode} transparentBackground />
</EuiFormControlLayout>
</React.Suspense> </React.Suspense>
</EuiErrorBoundary> </EuiErrorBoundary>
); );

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { LANG as CssLang } from './css/constants';
export { LANG as MarkdownLang } from './markdown/constants';
export { LANG as YamlLang } from './yaml/constants';
export { LANG as HandlebarsLang } from './handlebars/constants';

View file

@ -66,7 +66,7 @@ export const UrlTemplateEditor: React.FC<UrlTemplateEditorProps> = ({
return; return;
} }
const { dispose } = monaco.languages.registerCompletionItemProvider(HandlebarsLang.ID, { const { dispose } = monaco.languages.registerCompletionItemProvider(HandlebarsLang, {
triggerCharacters: ['{', '/', '?', '&', '='], triggerCharacters: ['{', '/', '?', '&', '='],
provideCompletionItems(model, position, context, token) { provideCompletionItems(model, position, context, token) {
const { lineNumber } = position; const { lineNumber } = position;
@ -124,7 +124,7 @@ export const UrlTemplateEditor: React.FC<UrlTemplateEditorProps> = ({
return ( return (
<div className={'urlTemplateEditor__container'} onKeyDown={handleKeyDown}> <div className={'urlTemplateEditor__container'} onKeyDown={handleKeyDown}>
<Editor <Editor
languageId={HandlebarsLang.ID} languageId={HandlebarsLang}
height={height} height={height}
value={value} value={value}
onChange={onChange} onChange={onChange}

View file

@ -116,7 +116,7 @@ export class MarkdownEditor extends Component {
<div className="tvbMarkdownEditor__editor"> <div className="tvbMarkdownEditor__editor">
<CodeEditor <CodeEditor
editorDidMount={this.handleOnLoad} editorDidMount={this.handleOnLoad}
languageId={MarkdownLang.ID} languageId={MarkdownLang}
options={{ options={{
fontSize: '14px', fontSize: '14px',
wordWrap: 'on', wordWrap: 'on',

View file

@ -262,7 +262,7 @@ export class MarkdownPanelConfig extends Component<
<EuiSpacer size="s" /> <EuiSpacer size="s" />
<CodeEditor <CodeEditor
height="500px" height="500px"
languageId={CssLang.ID} languageId={CssLang}
options={{ fontSize: 14 }} options={{ fontSize: 14 }}
value={model.markdown_css ?? ''} value={model.markdown_css ?? ''}
onChange={this.handleCSSChange} onChange={this.handleCSSChange}