mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[8.x] [React@18] `useLayoutEffect` when setting value from a prop in `react-monaco-editor` (#195775) (#196671)
# Backport This will backport the following commits from `main` to `8.x`: - [[React@18] `useLayoutEffect` when setting value from a prop in `react-monaco-editor` (#195775)](https://github.com/elastic/kibana/pull/195775) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Anton Dosov","email":"anton.dosov@elastic.co"},"sourceCommit":{"committedDate":"2024-10-17T11:24:06Z","message":"[React@18] `useLayoutEffect` when setting value from a prop in `react-monaco-editor` (#195775)\n\n## Summary\r\n\r\nThis PR is part of\r\nhttps://github.com/elastic/kibana-team/issues/1016#issuecomment-2399310175\r\nand needed to upgrade Kibana to React@18 in Legacy mode.\r\n\r\nWe've found a problem in `react-monaco-editor` component which is a very\r\nthin wrapper around `monaco` where it doesn't play nicely with React@18\r\nin legacy mode. You can read on details around the issue here\r\nhttps://github.com/elastic/eui/issues/8018 where we've found a similar\r\nissue in EUI's search bar component. The workaround we've found is to\r\nchange `useEffect` -> `useLayouEffect` where the value that is coming\r\nfrom the prop is set into the model. The issue and a fix might be a bit\r\ncontroversal and the component is very thin, so I decided that it might\r\nbe better to bring the fork into Kibana with only what's needed and with\r\na workaround.","sha":"dc3dda7d12662f3d7b5cb6c6c6366e07eae138fa","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:SharedUX","backport:prev-minor"],"title":"[React@18] `useLayoutEffect` when setting value from a prop in `react-monaco-editor`","number":195775,"url":"https://github.com/elastic/kibana/pull/195775","mergeCommit":{"message":"[React@18] `useLayoutEffect` when setting value from a prop in `react-monaco-editor` (#195775)\n\n## Summary\r\n\r\nThis PR is part of\r\nhttps://github.com/elastic/kibana-team/issues/1016#issuecomment-2399310175\r\nand needed to upgrade Kibana to React@18 in Legacy mode.\r\n\r\nWe've found a problem in `react-monaco-editor` component which is a very\r\nthin wrapper around `monaco` where it doesn't play nicely with React@18\r\nin legacy mode. You can read on details around the issue here\r\nhttps://github.com/elastic/eui/issues/8018 where we've found a similar\r\nissue in EUI's search bar component. The workaround we've found is to\r\nchange `useEffect` -> `useLayouEffect` where the value that is coming\r\nfrom the prop is set into the model. The issue and a fix might be a bit\r\ncontroversal and the component is very thin, so I decided that it might\r\nbe better to bring the fork into Kibana with only what's needed and with\r\na workaround.","sha":"dc3dda7d12662f3d7b5cb6c6c6366e07eae138fa"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/195775","number":195775,"mergeCommit":{"message":"[React@18] `useLayoutEffect` when setting value from a prop in `react-monaco-editor` (#195775)\n\n## Summary\r\n\r\nThis PR is part of\r\nhttps://github.com/elastic/kibana-team/issues/1016#issuecomment-2399310175\r\nand needed to upgrade Kibana to React@18 in Legacy mode.\r\n\r\nWe've found a problem in `react-monaco-editor` component which is a very\r\nthin wrapper around `monaco` where it doesn't play nicely with React@18\r\nin legacy mode. You can read on details around the issue here\r\nhttps://github.com/elastic/eui/issues/8018 where we've found a similar\r\nissue in EUI's search bar component. The workaround we've found is to\r\nchange `useEffect` -> `useLayouEffect` where the value that is coming\r\nfrom the prop is set into the model. The issue and a fix might be a bit\r\ncontroversal and the component is very thin, so I decided that it might\r\nbe better to bring the fork into Kibana with only what's needed and with\r\na workaround.","sha":"dc3dda7d12662f3d7b5cb6c6c6366e07eae138fa"}}]}] BACKPORT--> Co-authored-by: Anton Dosov <anton.dosov@elastic.co>
This commit is contained in:
parent
52f92a837f
commit
4849b41d69
12 changed files with 360 additions and 40 deletions
26
NOTICE.txt
26
NOTICE.txt
|
@ -214,6 +214,32 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---
|
||||
This code is forked from the `react-monaco-editor`
|
||||
https://github.com/react-monaco-editor/react-monaco-editor/blob/975cc47b5cb411ee2ffcbdb973daa9342e81a805/src/editor.tsx
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-present Leon Shi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---
|
||||
This code is part of the Services provided by FullStory, Inc. For license information, please refer to https://www.fullstory.com/legal/terms-and-conditions/
|
||||
Portions of this code are licensed under the following license:
|
||||
|
|
|
@ -1218,7 +1218,6 @@
|
|||
"react-intl": "6.6.6",
|
||||
"react-is": "^17.0.2",
|
||||
"react-markdown": "^6.0.3",
|
||||
"react-monaco-editor": "^0.54.0",
|
||||
"react-popper-tooltip": "^3.1.1",
|
||||
"react-recompose": "^0.33.0",
|
||||
"react-redux": "^7.2.8",
|
||||
|
|
|
@ -105,9 +105,9 @@ module.exports = {
|
|||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
transformIgnorePatterns: [
|
||||
// ignore all node_modules except monaco-editor, monaco-yaml and react-monaco-editor which requires babel transforms to handle dynamic import()
|
||||
// ignore all node_modules except monaco-editor, monaco-yaml which requires babel transforms to handle dynamic import()
|
||||
// since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842)
|
||||
'[/\\\\]node_modules(?)[/\\\\].+\\.js$',
|
||||
'[/\\\\]node_modules(?)[/\\\\].+\\.js$',
|
||||
'packages/kbn-pm/dist/index.js',
|
||||
'[/\\\\]node_modules(?)/dist/[/\\\\].+\\.js$',
|
||||
'[/\\\\]node_modules(?)/dist/util/[/\\\\].+\\.js$',
|
||||
|
|
|
@ -24,7 +24,6 @@ SRCS = glob(
|
|||
BUNDLER_DEPS = [
|
||||
"@npm//react",
|
||||
"@npm//tslib",
|
||||
"@npm//react-monaco-editor",
|
||||
]
|
||||
|
||||
js_library(
|
||||
|
|
|
@ -9,7 +9,7 @@ date: 2022-12-05
|
|||
|
||||
## Description
|
||||
|
||||
This component is an abstraction of the [Monaco Code Editor](https://microsoft.github.io/monaco-editor/) (and the [React Monaco Editor component](https://github.com/react-monaco-editor/react-monaco-editor)). This component still allows access to the other Monaco features.
|
||||
This component is an abstraction of the [Monaco Code Editor](https://microsoft.github.io/monaco-editor/). This component still allows access to the other Monaco features.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -18,10 +18,8 @@ import { MockedMonacoEditor, mockedEditorInstance } from '@kbn/code-editor-mock/
|
|||
|
||||
import { CodeEditor } from './code_editor';
|
||||
|
||||
jest.mock('react-monaco-editor', () => {
|
||||
return function JestMockEditor() {
|
||||
return MockedMonacoEditor;
|
||||
};
|
||||
jest.mock('./react_monaco_editor', () => {
|
||||
return { MonacoEditor: MockedMonacoEditor };
|
||||
});
|
||||
|
||||
// Mock the htmlIdGenerator to generate predictable ids for snapshot tests
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
*/
|
||||
|
||||
import React, { useState, useRef, useCallback, useMemo, useEffect, KeyboardEvent, FC } from 'react';
|
||||
import ReactMonacoEditor, {
|
||||
type MonacoEditorProps as ReactMonacoEditorProps,
|
||||
} from 'react-monaco-editor';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiToolTip,
|
||||
|
@ -34,6 +31,10 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { css } from '@emotion/react';
|
||||
import {
|
||||
MonacoEditor as ReactMonacoEditor,
|
||||
type MonacoEditorProps as ReactMonacoEditorProps,
|
||||
} from './react_monaco_editor';
|
||||
import './register_languages';
|
||||
import { remeasureFonts } from './remeasure_fonts';
|
||||
|
||||
|
@ -168,7 +169,7 @@ export interface CodeEditorProps {
|
|||
export const CodeEditor: React.FC<CodeEditorProps> = ({
|
||||
languageId,
|
||||
value,
|
||||
onChange: _onChange,
|
||||
onChange,
|
||||
width,
|
||||
height,
|
||||
options,
|
||||
|
@ -225,8 +226,6 @@ export const CodeEditor: React.FC<CodeEditorProps> = ({
|
|||
|
||||
const [isHintActive, setIsHintActive] = useState(true);
|
||||
|
||||
const onChange = useBug175684OnChange(_onChange);
|
||||
|
||||
const startEditing = useCallback(() => {
|
||||
setIsHintActive(false);
|
||||
_editor?.focus();
|
||||
|
@ -701,23 +700,6 @@ const useFitToContent = ({
|
|||
}, [editor, isFitToContent, minLines, maxLines, isFullScreen]);
|
||||
};
|
||||
|
||||
// https://github.com/elastic/kibana/issues/175684
|
||||
// 'react-monaco-editor' has a bug that it always calls the initial onChange callback, so the closure might become stale
|
||||
// we work this around by calling the latest onChange from props
|
||||
const useBug175684OnChange = (onChange: CodeEditorProps['onChange']) => {
|
||||
const onChangePropRef = useRef<CodeEditorProps['onChange']>(onChange);
|
||||
useEffect(() => {
|
||||
onChangePropRef.current = onChange;
|
||||
}, [onChange]);
|
||||
const onChangeWrapper = useCallback<NonNullable<CodeEditorProps['onChange']>>((_value, event) => {
|
||||
if (onChangePropRef.current) {
|
||||
onChangePropRef.current(_value, event);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return onChangeWrapper;
|
||||
};
|
||||
|
||||
const UseBug177756ReBroadcastMouseDown: FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [$codeWrapper, setCodeWrapper] = React.useState<HTMLElement | null>(null);
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
This is a fork of [react-monaco-editor project](https://github.com/react-monaco-editor/react-monaco-editor) that is a Monaco editor wrapper for React.
|
||||
This fork is needed to apply a change that fixes the editor behavior in Kibana when running React@18 in Legacy Mode and the bug is described [here](https://github.com/facebook/react/issues/31023)
|
||||
The change is to replace the `useEffect` hook with `useLayoutEffect` when the editor is in controlled mode and the value is updated from prop.
|
||||
|
||||
```diff
|
||||
---useEffect(() => {
|
||||
+++useLayoutEffect(() => {
|
||||
if (editor.current) {
|
||||
if (value === editor.current.getValue()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = editor.current.getModel();
|
||||
__prevent_trigger_change_event.current = true;
|
||||
editor.current.pushUndoStop();
|
||||
// pushEditOperations says it expects a cursorComputer, but doesn't seem to need one.
|
||||
model.pushEditOperations(
|
||||
[],
|
||||
[
|
||||
{
|
||||
range: model.getFullModelRange(),
|
||||
text: value,
|
||||
},
|
||||
],
|
||||
undefined,
|
||||
);
|
||||
editor.current.pushUndoStop();
|
||||
__prevent_trigger_change_event.current = false;
|
||||
}
|
||||
}, [value]);
|
||||
```
|
||||
|
||||
In addition, the fork only includes functionality that is used in Kibana and removes the rest of the code that is not needed.
|
|
@ -0,0 +1,278 @@
|
|||
/* eslint-disable @kbn/eslint/require-license-header */
|
||||
/**
|
||||
* @notice
|
||||
* This code is forked from the `react-monaco-editor`
|
||||
* https://github.com/react-monaco-editor/react-monaco-editor/blob/975cc47b5cb411ee2ffcbdb973daa9342e81a805/src/editor.tsx
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-present Leon Shi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { monaco as monacoEditor, monaco } from '@kbn/monaco';
|
||||
import * as React from 'react';
|
||||
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
||||
|
||||
export type EditorConstructionOptions = monacoEditor.editor.IStandaloneEditorConstructionOptions;
|
||||
|
||||
export type EditorWillMount = (monaco: typeof monacoEditor) => void | EditorConstructionOptions;
|
||||
|
||||
export type EditorDidMount = (
|
||||
editor: monacoEditor.editor.IStandaloneCodeEditor,
|
||||
monaco: typeof monacoEditor
|
||||
) => void;
|
||||
|
||||
export type EditorWillUnmount = (
|
||||
editor: monacoEditor.editor.IStandaloneCodeEditor,
|
||||
monaco: typeof monacoEditor
|
||||
) => void | EditorConstructionOptions;
|
||||
|
||||
export type ChangeHandler = (
|
||||
value: string,
|
||||
event: monacoEditor.editor.IModelContentChangedEvent
|
||||
) => void;
|
||||
|
||||
export interface MonacoEditorProps {
|
||||
/**
|
||||
* Width of editor. Defaults to 100%.
|
||||
*/
|
||||
width?: string | number;
|
||||
|
||||
/**
|
||||
* Height of editor. Defaults to 100%.
|
||||
*/
|
||||
height?: string | number;
|
||||
|
||||
/**
|
||||
* The initial value of the auto created model in the editor.
|
||||
*/
|
||||
defaultValue?: string;
|
||||
|
||||
/**
|
||||
* Value of the auto created model in the editor.
|
||||
* If you specify `null` or `undefined` for this property, the component behaves in uncontrolled mode.
|
||||
* Otherwise, it behaves in controlled mode.
|
||||
*/
|
||||
value?: string | null;
|
||||
|
||||
/**
|
||||
* The initial language of the auto created model in the editor. Defaults to 'javascript'.
|
||||
*/
|
||||
language?: string;
|
||||
|
||||
/**
|
||||
* Theme to be used for rendering.
|
||||
* The current out-of-the-box available themes are: 'vs' (default), 'vs-dark', 'hc-black'.
|
||||
* You can create custom themes via `monaco.editor.defineTheme`.
|
||||
*/
|
||||
theme?: string | null;
|
||||
|
||||
/**
|
||||
* Optional string classname to append to the editor.
|
||||
*/
|
||||
className?: string | null;
|
||||
|
||||
/**
|
||||
* Refer to Monaco interface {monaco.editor.IStandaloneEditorConstructionOptions}.
|
||||
*/
|
||||
options?: monacoEditor.editor.IStandaloneEditorConstructionOptions;
|
||||
|
||||
/**
|
||||
* An event emitted before the editor mounted (similar to componentWillMount of React).
|
||||
*/
|
||||
editorWillMount?: EditorWillMount;
|
||||
|
||||
/**
|
||||
* An event emitted when the editor has been mounted (similar to componentDidMount of React).
|
||||
*/
|
||||
editorDidMount?: EditorDidMount;
|
||||
|
||||
/**
|
||||
* An event emitted before the editor unmount (similar to componentWillUnmount of React).
|
||||
*/
|
||||
editorWillUnmount?: EditorWillUnmount;
|
||||
|
||||
/**
|
||||
* An event emitted when the content of the current model has changed.
|
||||
*/
|
||||
onChange?: ChangeHandler;
|
||||
}
|
||||
|
||||
export function MonacoEditor({
|
||||
width = '100%',
|
||||
height = '100%',
|
||||
value,
|
||||
defaultValue = '',
|
||||
language = 'javascript',
|
||||
theme,
|
||||
options,
|
||||
editorWillMount,
|
||||
editorDidMount,
|
||||
editorWillUnmount,
|
||||
onChange,
|
||||
className,
|
||||
}: MonacoEditorProps) {
|
||||
const containerElement = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const editor = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
|
||||
|
||||
const _subscription = useRef<monaco.IDisposable | null>(null);
|
||||
|
||||
const __prevent_trigger_change_event = useRef<boolean | null>(null);
|
||||
|
||||
const fixedWidth = processSize(width);
|
||||
|
||||
const fixedHeight = processSize(height);
|
||||
|
||||
const onChangeRef = useRef(onChange);
|
||||
onChangeRef.current = onChange;
|
||||
|
||||
const style = useMemo(
|
||||
() => ({
|
||||
width: fixedWidth,
|
||||
height: fixedHeight,
|
||||
}),
|
||||
[fixedWidth, fixedHeight]
|
||||
);
|
||||
|
||||
const handleEditorWillMount = () => {
|
||||
const finalOptions = editorWillMount?.(monaco);
|
||||
return finalOptions || {};
|
||||
};
|
||||
|
||||
const handleEditorDidMount = () => {
|
||||
editorDidMount?.(editor.current!, monaco);
|
||||
|
||||
_subscription.current = editor.current!.onDidChangeModelContent((event) => {
|
||||
if (!__prevent_trigger_change_event.current) {
|
||||
onChangeRef.current?.(editor.current!.getValue(), event);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleEditorWillUnmount = () => {
|
||||
editorWillUnmount?.(editor.current!, monaco);
|
||||
};
|
||||
|
||||
const initMonaco = () => {
|
||||
const finalValue = value !== null ? value : defaultValue;
|
||||
|
||||
if (containerElement.current) {
|
||||
// Before initializing monaco editor
|
||||
const finalOptions = { ...options, ...handleEditorWillMount() };
|
||||
|
||||
const model = monaco.editor.createModel(finalValue!, language);
|
||||
|
||||
editor.current = monaco.editor.create(containerElement.current, {
|
||||
model,
|
||||
...(className ? { extraEditorClassName: className } : {}),
|
||||
...finalOptions,
|
||||
...(theme ? { theme } : {}),
|
||||
});
|
||||
// After initializing monaco editor
|
||||
handleEditorDidMount();
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
useEffect(initMonaco, []);
|
||||
|
||||
// useLayoutEffect instead of useEffect to mitigate https://github.com/facebook/react/issues/31023 in React@18 Legacy Mode
|
||||
useLayoutEffect(() => {
|
||||
if (editor.current) {
|
||||
if (value === editor.current.getValue()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = editor.current.getModel();
|
||||
__prevent_trigger_change_event.current = true;
|
||||
editor.current.pushUndoStop();
|
||||
// pushEditOperations says it expects a cursorComputer, but doesn't seem to need one.
|
||||
model!.pushEditOperations(
|
||||
[],
|
||||
[
|
||||
{
|
||||
range: model!.getFullModelRange(),
|
||||
text: value!,
|
||||
},
|
||||
],
|
||||
// @ts-expect-error
|
||||
undefined
|
||||
);
|
||||
editor.current.pushUndoStop();
|
||||
__prevent_trigger_change_event.current = false;
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editor.current) {
|
||||
const model = editor.current.getModel();
|
||||
monaco.editor.setModelLanguage(model!, language);
|
||||
}
|
||||
}, [language]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editor.current) {
|
||||
// Don't pass in the model on update because monaco crashes if we pass the model
|
||||
// a second time. See https://github.com/microsoft/monaco-editor/issues/2027
|
||||
// @ts-expect-error
|
||||
const { model: _model, ...optionsWithoutModel } = options;
|
||||
editor.current.updateOptions({
|
||||
...(className ? { extraEditorClassName: className } : {}),
|
||||
...optionsWithoutModel,
|
||||
});
|
||||
}
|
||||
}, [className, options]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editor.current) {
|
||||
editor.current.layout();
|
||||
}
|
||||
}, [width, height]);
|
||||
|
||||
useEffect(() => {
|
||||
if (theme) {
|
||||
monaco.editor.setTheme(theme);
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
if (editor.current) {
|
||||
handleEditorWillUnmount();
|
||||
editor.current.dispose();
|
||||
}
|
||||
if (_subscription.current) {
|
||||
_subscription.current.dispose();
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[]
|
||||
);
|
||||
|
||||
return <div ref={containerElement} style={style} className="react-monaco-editor-container" />;
|
||||
}
|
||||
|
||||
MonacoEditor.displayName = 'MonacoEditor';
|
||||
|
||||
function processSize(size: number | string) {
|
||||
return !/^\d+$/.test(size as string) ? size : `${size}px`;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export * from './editor';
|
|
@ -8,8 +8,10 @@
|
|||
*/
|
||||
|
||||
import React, { useEffect, KeyboardEventHandler } from 'react';
|
||||
import { type MonacoEditorProps } from 'react-monaco-editor';
|
||||
import { monaco } from '@kbn/monaco';
|
||||
// TODO: circular dependency
|
||||
// import type { MonacoEditorProps } from '@kbn/code-editor/react_monaco_editor';
|
||||
type MonacoEditorProps = any;
|
||||
|
||||
function createEditorInstance() {
|
||||
const keyDownListeners: Array<(e?: unknown) => void> = [];
|
||||
|
|
|
@ -26943,13 +26943,6 @@ react-markdown@^6.0.3:
|
|||
unist-util-visit "^2.0.0"
|
||||
vfile "^4.0.0"
|
||||
|
||||
react-monaco-editor@^0.54.0:
|
||||
version "0.54.0"
|
||||
resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.54.0.tgz#ec9293249a991b08264be723c1ec0ca3a6d480d8"
|
||||
integrity sha512-9JwO69851mfpuhYLHlKbae7omQWJ/2ICE2lbL0VHyNyZR8rCOH7440u+zAtDgiOMpLwmYdY1sEZCdRefywX6GQ==
|
||||
dependencies:
|
||||
prop-types "^15.8.1"
|
||||
|
||||
react-popper-tooltip@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue