diff --git a/CHANGELOG.md b/CHANGELOG.md index ea3d1d6980f..60a4fec74cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ - Fixed bug in `EuiPagination` showing wrong page count when `compressed` prop is true. ([#3827](https://github.com/elastic/eui/pull/3827)) - Fixed bug in EUI's input field components where their `inputRef` couldn't be a `RefObject` ([#3822](https://github.com/elastic/eui/pull/3822)) - Moved `react-view` and `html-format` to be `devDependencies` ([#3828](https://github.com/elastic/eui/pull/3828)) -- Fix `EuiComboBox` keyboard selection when `sortMatchesBy=startsWith` ([#3823](https://github.com/elastic/eui/pull/3823)) +- Fixed `EuiComboBox` keyboard selection when `sortMatchesBy=startsWith` ([#3823](https://github.com/elastic/eui/pull/3823)) +- Fixed `EuiCodeEditor` not exiting edit mode with `esc` when `enableLiveAutocompletion=true` ([#3833](https://github.com/elastic/eui/pull/3833)) ## [`27.3.0`](https://github.com/elastic/eui/tree/v27.3.0) diff --git a/src/components/code_editor/code_editor.test.tsx b/src/components/code_editor/code_editor.test.tsx index 101475b0100..a4e3ecf4faf 100644 --- a/src/components/code_editor/code_editor.test.tsx +++ b/src/components/code_editor/code_editor.test.tsx @@ -112,6 +112,10 @@ describe('EuiCodeEditor', () => { }); test('pressing escape in ace textbox will enable overlay', () => { + // We cannot simulate the `commands` path, but this interaction still + // serves as a fallback in cases where `commands` is unavailable. + // @ts-ignore onFocusAce is known to exist + component.instance().onFocusAce(); // @ts-ignore onKeydownAce is known to exist and its params' values are unimportant component.instance().onKeydownAce({ preventDefault: () => {}, diff --git a/src/components/code_editor/code_editor.tsx b/src/components/code_editor/code_editor.tsx index 94f89c65ebc..fb6c7d50aab 100644 --- a/src/components/code_editor/code_editor.tsx +++ b/src/components/code_editor/code_editor.tsx @@ -114,17 +114,26 @@ export class EuiCodeEditor extends Component< } }; + onEscToExit = () => { + this.stopEditing(); + if (this.editorHint) { + this.editorHint.focus(); + } + }; + onKeydownAce = (event: KeyboardEvent) => { if (event.key === keys.ESCAPE) { - // If the autocompletion context menu is open then we want to let ESCAPE close it but - // **not** exit out of editing mode. - if (this.aceEditor !== null && !this.aceEditor.editor.completer) { - event.preventDefault(); - event.stopPropagation(); - this.stopEditing(); - if (this.editorHint) { - this.editorHint.focus(); - } + event.preventDefault(); + event.stopPropagation(); + // Handles exiting edit mode when `isReadOnly` is set. + // Other 'esc' cases handled by `stopEditingOnEsc` command. + // Would run after `stopEditingOnEsc`. + if ( + this.aceEditor !== null && + !this.aceEditor.editor.completer && + this.state.isEditing + ) { + this.onEscToExit(); } } }; @@ -210,13 +219,14 @@ export class EuiCodeEditor extends Component< const { width, height, - onBlur, // eslint-disable-line no-unused-vars + onBlur, isReadOnly, setOptions, cursorStart, mode = DEFAULT_MODE, 'data-test-subj': dataTestSubj = 'codeEditorContainer', theme = DEFAULT_THEME, + commands = [], ...rest } = this.props; @@ -230,7 +240,7 @@ export class EuiCodeEditor extends Component< let filteredCursorStart; - const options = { ...setOptions }; + const options: IAceEditorProps['setOptions'] = { ...setOptions }; if (isReadOnly) { // Put the cursor at the beginning of the editor, so that it doesn't look like @@ -312,6 +322,16 @@ export class EuiCodeEditor extends Component< $blockScrolling: Infinity, }} cursorStart={filteredCursorStart} + commands={[ + // Handles exiting edit mode in all cases except `isReadOnly` + // Runs before `onKeydownAce`. + { + name: 'stopEditingOnEsc', + bindKey: { win: 'Esc', mac: 'Esc' }, + exec: this.onEscToExit, + }, + ...commands, + ]} {...rest} />