From 4e9c6a956d0bca549e649b79c6c42f93f4b49a40 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Fri, 5 Feb 2021 11:58:23 -0800 Subject: [PATCH] add code editor focus/blur keyboard controls --- .../CodeMirrorInput/CodeMirrorInput.jsx | 86 +++++++++++++------ 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/awx/ui_next/src/components/CodeMirrorInput/CodeMirrorInput.jsx b/awx/ui_next/src/components/CodeMirrorInput/CodeMirrorInput.jsx index a3d5c77324..f32d9d7d32 100644 --- a/awx/ui_next/src/components/CodeMirrorInput/CodeMirrorInput.jsx +++ b/awx/ui_next/src/components/CodeMirrorInput/CodeMirrorInput.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef, useCallback } from 'react'; import { oneOf, bool, number, string, func } from 'prop-types'; import AceEditor from 'react-ace'; // import * as ace from 'ace-builds'; @@ -79,6 +79,7 @@ const CodeMirror = styled(ReactCodeMirror)` `; function CodeMirrorInput({ + id, value, onChange, mode, @@ -89,19 +90,33 @@ function CodeMirrorInput({ className, placeholder, }) { - // Workaround for CodeMirror bug: If CodeMirror renders in a modal on the - // modal's initial render, it appears as an empty box due to mis-calculated - // element height. Forcing an initial render before mounting - // fixes this. - const [isInitialized, setIsInitialized] = useState(false); - useEffect(() => { - if (!isInitialized) { - setIsInitialized(true); + const wrapper = useRef(null); + const editor = useRef(null); + + useEffect(function removeTextareaTabIndex() { + const editorInput = editor.current.refEditor?.querySelector('textarea'); + if (editorInput) { + editorInput.tabIndex = -1; } - }, [isInitialized]); - if (!isInitialized) { - return
; - } + }, []); + + const listen = useCallback(event => { + if (wrapper.current === document.activeElement && event.key === 'Enter') { + const editorInput = editor.current.refEditor?.querySelector('textarea'); + if (editorInput) { + editorInput.focus(); + } + } + }, []); + + useEffect(function addKeyEventListeners() { + const wrapperEl = wrapper.current; + wrapperEl.addEventListener('keydown', listen); + + return () => { + wrapperEl.removeEventListener('keydown', listen); + }; + }); return ( <> @@ -121,19 +136,38 @@ function CodeMirrorInput({ fullHeight={fullHeight} rows={rows} /> */} - +
+ { + wrapper.current.focus(); + }, + }, + { + name: 'tab escape', + bindKey: { win: 'Shift-Tab', mac: 'Shift-Tab' }, + exec: () => { + wrapper.current.focus(); + }, + }, + ]} + ref={editor} + /> +
); }