src/ui/editor.tsx (82 lines of code) (raw):

/* Copyright (c) Uber Technologies, Inc. This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. */ import * as React from "react"; import SimpleEditor from "react-simple-code-editor"; import { Highlight } from "prism-react-renderer"; import type { TEditorProps, TEditorLanguage } from "../index"; import lightTheme from "../light-theme"; import { getStyles, useValueDebounce } from "../utils"; const highlightCode = ({ code, theme, language, }: { code: string; theme: typeof lightTheme; language?: TEditorLanguage; }) => ( <Highlight code={code} theme={theme} language={language || "jsx"}> {({ tokens, getLineProps, getTokenProps }) => ( <React.Fragment> {tokens.map((line, i) => ( <div key={i} {...getLineProps({ line, key: i })}> {line.map((token, key) => { const tokenProps = getTokenProps({ token, key }); return <span key={key} {...tokenProps} />; })} </div> ))} </React.Fragment> )} </Highlight> ); const Editor: React.FC<TEditorProps> = ({ code: globalCode, onChange, placeholder, language, theme, ["data-testid"]: testid, className, }) => { const [focused, setFocused] = React.useState(false); const editorTheme = { ...(theme || lightTheme), plain: { whiteSpace: "break-spaces", ...(theme || lightTheme).plain, }, }; const [code, setCode] = useValueDebounce<string>(globalCode, onChange); return ( <div data-testid={testid} {...getStyles( { boxSizing: "border-box", paddingLeft: "4px", paddingRight: "4px", maxWidth: "auto", overflow: "hidden", border: focused ? "1px solid #276EF1" : "1px solid #CCC", borderRadius: "5px", }, className, )} > <style dangerouslySetInnerHTML={{ __html: `.npm__react-simple-code-editor__textarea { outline: none !important }`, }} /> <SimpleEditor value={code || ""} placeholder={placeholder} highlight={(code) => highlightCode({ code, theme: editorTheme, language }) } onValueChange={(code) => setCode(code)} onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} padding={8} style={editorTheme.plain as any} /> </div> ); }; export default Editor;