UNPKG

@aliemir/react-live

Version:

A production-focused playground for live editing React code

90 lines (81 loc) 2.39 kB
import React, { useEffect, useState, useRef, useCallback } from "react"; import PropTypes from "prop-types"; import { useEditable } from "use-editable"; import Highlight, { Prism } from "prism-react-renderer"; import { theme as liveTheme } from "../../constants/theme"; const CodeEditor = (props) => { const editorRef = useRef(null); const [code, setCode] = useState(props.code || ""); useEffect(() => { setCode(props.code); }, [props.code]); const onEditableChange = useCallback((_code) => { setCode(_code.slice(0, -1)); }, []); useEditable(editorRef, onEditableChange, { disabled: props.disabled, indentation: 2, }); useEffect(() => { if (props.onChange) { props.onChange(code); } }, [code]); return ( <div className={props.className} style={props.style}> <Highlight Prism={props.prism || Prism} code={code} theme={props.theme || liveTheme} language={props.language} > {({ className: _className, tokens, getLineProps, getTokenProps, style: _style, }) => ( <pre className={_className} style={{ margin: 0, outline: "none", padding: 10, fontFamily: "inherit", ...(!props.className || !props.theme ? {} : _style), }} ref={editorRef} spellCheck="false" > {tokens.map((line, lineIndex) => ( // eslint-disable-next-line react/jsx-key <div {...getLineProps({ line, key: `line-${lineIndex}` })}> {line .filter((token) => !token.empty) .map((token, tokenIndex) => ( // eslint-disable-next-line react/jsx-key <span {...getTokenProps({ token, key: `token-${tokenIndex}` })} /> ))} {"\n"} </div> ))} </pre> )} </Highlight> </div> ); }; CodeEditor.propTypes = { className: PropTypes.string, code: PropTypes.string, disabled: PropTypes.bool, language: PropTypes.string, onChange: PropTypes.func, prism: PropTypes.object, style: PropTypes.object, theme: PropTypes.object, }; export default CodeEditor;