diff --git a/packages/console/src/components/CodeEditor/index.tsx b/packages/console/src/components/CodeEditor/index.tsx index 61cff5395..b7c232f15 100644 --- a/packages/console/src/components/CodeEditor/index.tsx +++ b/packages/console/src/components/CodeEditor/index.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import { ChangeEvent } from 'react'; +import { ChangeEvent, KeyboardEvent, useRef } from 'react'; import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'; import { a11yDark as theme } from 'react-syntax-highlighter/dist/esm/styles/prism'; @@ -12,11 +12,39 @@ type Props = { isReadonly?: boolean; value?: string; onChange?: (value: string) => void; + tabSize?: number; }; -const CodeEditor = ({ className, language, isReadonly = false, value = '', onChange }: Props) => { +const CodeEditor = ({ + className, + language, + isReadonly = false, + value = '', + onChange, + tabSize = 2, +}: Props) => { + const textareaRef = useRef(null); + const handleChange = (event: ChangeEvent) => { - onChange?.(event.currentTarget.value); + const { value } = event.currentTarget; + onChange?.(value); + }; + + const handleKeydown = (event: KeyboardEvent) => { + if (event.key === 'Tab') { + const { value, selectionStart } = event.currentTarget; + + event.preventDefault(); + const newText = + value.slice(0, selectionStart) + ' '.repeat(tabSize) + value.slice(selectionStart); + + // Need to update value to set selection without useEffect + // eslint-disable-next-line @silverhand/fp/no-mutation + event.currentTarget.value = newText; + event.currentTarget.setSelectionRange(selectionStart + tabSize, selectionStart + tabSize); + + onChange?.(newText); + } }; return ( @@ -26,6 +54,7 @@ const CodeEditor = ({ className, language, isReadonly = false, value = '', onCha {/* SyntaxHighlighter is a readonly component, so a transparent