documentation-site/components/yard/editor.tsx (107 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, { Prism } from "prism-react-renderer"; import { useStyletron } from "baseui"; import type { TTransformToken, TEditorProps } from "react-view"; import { lightTheme, useValueDebounce } from "react-view"; import darkTheme from "./dark-theme"; const highlightCode = ( code: string, theme: typeof lightTheme, transformToken?: TTransformToken, ) => ( <Highlight Prism={Prism} code={code} theme={theme} language="jsx"> {({ tokens, getLineProps, getTokenProps }) => ( <React.Fragment> {tokens.map((line, i) => ( // eslint-disable-next-line react/jsx-key <div {...getLineProps({ line, key: i })}> {line.map((token, key) => { const tokenProps = getTokenProps({ token, key }); if (transformToken) { return transformToken(tokenProps); } // eslint-disable-next-line react/jsx-key return <span {...tokenProps} />; })} </div> ))} </React.Fragment> )} </Highlight> ); const Editor: React.FC<TEditorProps> = ({ code: globalCode, transformToken, onChange, placeholder, small, }) => { const [css, theme] = useStyletron(); const [focused, setFocused] = React.useState(false); const plainStyles = theme.name.startsWith("light-theme") ? lightTheme : darkTheme; const editorTheme = { ...plainStyles, plain: { ...plainStyles.plain, fontSize: small ? "13px" : "14px", whiteSpace: "break-spaces", backgroundColor: focused ? theme.colors.inputFillActive : theme.colors.inputFill, }, }; const [code, setCode] = useValueDebounce<string>(globalCode, onChange); return ( <div className={css({ boxSizing: "border-box", backgroundColor: editorTheme.plain.backgroundColor, paddingLeft: "8px", paddingRight: "8px", paddingTop: "0px", paddingBottom: "0px", overflow: "hidden", borderLeftWidth: "2px", borderRightWidth: "2px", borderTopWidth: "2px", borderBottomWidth: "2px", borderLeftStyle: "solid", borderTopStyle: "solid", borderRightStyle: "solid", borderBottomStyle: "solid", borderTopRightRadius: "8px", borderTopLeftRadius: "8px", borderBottomRightRadius: "8px", borderBottomLeftRadius: "8px", borderLeftColor: focused ? theme.colors.borderSelected : theme.colors.inputBorder, borderTopColor: focused ? theme.colors.borderSelected : theme.colors.inputBorder, borderRightColor: focused ? theme.colors.borderSelected : theme.colors.inputBorder, borderBottomColor: focused ? theme.colors.borderSelected : theme.colors.inputBorder, })} > <style dangerouslySetInnerHTML={{ __html: `.npm__react-simple-code-editor__textarea { outline: none !important }`, }} /> <SimpleEditor ignoreTabKey={true} value={code || ""} placeholder={placeholder} highlight={(code) => highlightCode(code, editorTheme, transformToken)} onValueChange={(code) => setCode(code)} onFocus={() => setFocused(true)} onBlur={() => setFocused(false)} padding={small ? 4 : 12} style={editorTheme.plain as React.CSSProperties} /> </div> ); }; export default Editor;