UNPKG

react-code-view

Version:
148 lines (147 loc) 6.2 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; var _excluded = ["dependencies", "editor", "theme", "editable", "transformOptions", "code", "copyButtonAs", "copyButtonProps", "renderToolbar", "renderExtraFooter", "onOpenEditor", "onCloseEditor", "onChange", "beforeCompile", "afterCompile"], _excluded2 = ["classPrefix", "icon", "className", "buttonClassName", "showCodeButtonProps"]; /* eslint-disable @typescript-eslint/no-var-requires */ import classNames from 'classnames'; import CodeEditor from './CodeEditor'; import Preview from './Preview'; import canUseDOM from './utils/canUseDOM'; import evalCode from './utils/evalCode'; import CodeIcon from './icons/Code'; import { useEffect, useState, useCallback, createElement as _createElement } from 'react'; import { transform as transformCode } from 'sucrase'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; var React = require('react'); var ReactDOM = require('react-dom'); var defaultTransformOptions = { transforms: ['jsx'] }; var Renderer = React.forwardRef(function (props, ref) { var dependencies = props.dependencies, _props$editor = props.editor, editor = _props$editor === void 0 ? {} : _props$editor, _props$theme = props.theme, theme = _props$theme === void 0 ? 'light' : _props$theme, _props$editable = props.editable, isEditable = _props$editable === void 0 ? false : _props$editable, _props$transformOptio = props.transformOptions, transformOptions = _props$transformOptio === void 0 ? defaultTransformOptions : _props$transformOptio, code = props.code, copyButtonAs = props.copyButtonAs, copyButtonProps = props.copyButtonProps, renderToolbar = props.renderToolbar, renderExtraFooter = props.renderExtraFooter, onOpenEditor = props.onOpenEditor, onCloseEditor = props.onCloseEditor, onChange = props.onChange, beforeCompile = props.beforeCompile, afterCompile = props.afterCompile, rest = _objectWithoutPropertiesLoose(props, _excluded); var classPrefix = editor.classPrefix, codeIcon = editor.icon, editorClassName = editor.className, buttonClassName = editor.buttonClassName, showCodeButtonProps = editor.showCodeButtonProps, editorProps = _objectWithoutPropertiesLoose(editor, _excluded2); var _useState = useState(isEditable), editable = _useState[0], setEditable = _useState[1]; var _useState2 = useState(null), errorMessage = _useState2[0], setErrorMessage = _useState2[1]; var _useState3 = useState(null), compiledReactNode = _useState3[0], setCompiledReactNode = _useState3[1]; var handleExpandEditor = useCallback(function () { setEditable(!editable); if (editable) { onCloseEditor === null || onCloseEditor === void 0 ? void 0 : onCloseEditor(); } else if (!editable) { onOpenEditor === null || onOpenEditor === void 0 ? void 0 : onOpenEditor(); } }, [editable, onCloseEditor, onOpenEditor]); var handleError = useCallback(function (error) { setErrorMessage(error.message); }, []); var prefix = function prefix(name) { return classPrefix ? classPrefix + "-" + name : name; }; var executeCode = useCallback(function (pendCode) { if (pendCode === void 0) { pendCode = code; } if (!canUseDOM) { return; } var originalRender = ReactDOM.render; // Redefine the render function, which will reset to the default value after `eval` is executed. ReactDOM.render = function (element) { setCompiledReactNode(element); }; try { var beforeCompileCode = (beforeCompile === null || beforeCompile === void 0 ? void 0 : beforeCompile(pendCode)) || pendCode; if (beforeCompileCode) { var _transformCode = transformCode(beforeCompileCode, transformOptions), compiledCode = _transformCode.code; evalCode((afterCompile === null || afterCompile === void 0 ? void 0 : afterCompile(compiledCode)) || compiledCode, _extends({ React: React, ReactDOM: ReactDOM }, dependencies)); } } catch (err) { console.warn(err); } finally { // Reset the render function to the original value. ReactDOM.render = originalRender; } }, [code, dependencies, beforeCompile, transformOptions, afterCompile]); useEffect(function () { executeCode(code); }, [code, executeCode]); var handleCodeChange = useCallback(function (code) { onChange === null || onChange === void 0 ? void 0 : onChange(code); executeCode(code); setErrorMessage(null); }, [executeCode, onChange]); var toggleButtonProps = _extends({ role: 'switch', 'aria-checked': editable, 'aria-label': 'Show the full source', className: buttonClassName, onClick: handleExpandEditor }, showCodeButtonProps); var showCodeButton = /*#__PURE__*/_jsx("button", _extends({}, toggleButtonProps, { children: typeof codeIcon !== 'undefined' ? codeIcon : /*#__PURE__*/_jsx(CodeIcon, { className: classNames(prefix('icon'), prefix('icon-code')) }) })); var showCodeEditor = editable && code; var hasError = !!errorMessage; return /*#__PURE__*/_jsxs("div", _extends({ className: "rcv-container" }, rest, { ref: ref, children: [/*#__PURE__*/_jsx(Preview, { hasError: hasError, errorMessage: errorMessage, onError: handleError, children: compiledReactNode }), /*#__PURE__*/_jsx("div", { className: "rcv-toolbar", children: renderToolbar ? renderToolbar(showCodeButton, toggleButtonProps) : showCodeButton }), showCodeEditor && /*#__PURE__*/_createElement(CodeEditor, _extends({}, editorProps, { key: "jsx", copyButtonAs: copyButtonAs, copyButtonProps: copyButtonProps, onChange: handleCodeChange, className: classNames(editorClassName, 'rcv-editor'), editorConfig: { lineNumbers: true, theme: "base16-" + theme }, code: code })), renderExtraFooter === null || renderExtraFooter === void 0 ? void 0 : renderExtraFooter()] })); }); export default Renderer;