react-code-view
Version:
Code view for React
153 lines (151 loc) • 6.91 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports["default"] = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _classnames = _interopRequireDefault(require("classnames"));
var _CodeEditor = _interopRequireDefault(require("./CodeEditor"));
var _Preview = _interopRequireDefault(require("./Preview"));
var _canUseDOM = _interopRequireDefault(require("./utils/canUseDOM"));
var _evalCode = _interopRequireDefault(require("./utils/evalCode"));
var _Code = _interopRequireDefault(require("./icons/Code"));
var _react = require("react");
var _sucrase = require("sucrase");
var _jsxRuntime = require("react/jsx-runtime");
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 */
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 = (0, _objectWithoutPropertiesLoose2["default"])(props, _excluded);
var classPrefix = editor.classPrefix,
codeIcon = editor.icon,
editorClassName = editor.className,
buttonClassName = editor.buttonClassName,
showCodeButtonProps = editor.showCodeButtonProps,
editorProps = (0, _objectWithoutPropertiesLoose2["default"])(editor, _excluded2);
var _useState = (0, _react.useState)(isEditable),
editable = _useState[0],
setEditable = _useState[1];
var _useState2 = (0, _react.useState)(null),
errorMessage = _useState2[0],
setErrorMessage = _useState2[1];
var _useState3 = (0, _react.useState)(null),
compiledReactNode = _useState3[0],
setCompiledReactNode = _useState3[1];
var handleExpandEditor = (0, _react.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 = (0, _react.useCallback)(function (error) {
setErrorMessage(error.message);
}, []);
var prefix = function prefix(name) {
return classPrefix ? classPrefix + "-" + name : name;
};
var executeCode = (0, _react.useCallback)(function (pendCode) {
if (pendCode === void 0) {
pendCode = code;
}
if (!_canUseDOM["default"]) {
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 = (0, _sucrase.transform)(beforeCompileCode, transformOptions),
compiledCode = _transformCode.code;
(0, _evalCode["default"])((afterCompile === null || afterCompile === void 0 ? void 0 : afterCompile(compiledCode)) || compiledCode, (0, _extends2["default"])({
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]);
(0, _react.useEffect)(function () {
executeCode(code);
}, [code, executeCode]);
var handleCodeChange = (0, _react.useCallback)(function (code) {
onChange === null || onChange === void 0 ? void 0 : onChange(code);
executeCode(code);
setErrorMessage(null);
}, [executeCode, onChange]);
var toggleButtonProps = (0, _extends2["default"])({
role: 'switch',
'aria-checked': editable,
'aria-label': 'Show the full source',
className: buttonClassName,
onClick: handleExpandEditor
}, showCodeButtonProps);
var showCodeButton = /*#__PURE__*/(0, _jsxRuntime.jsx)("button", (0, _extends2["default"])({}, toggleButtonProps, {
children: typeof codeIcon !== 'undefined' ? codeIcon : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Code["default"], {
className: (0, _classnames["default"])(prefix('icon'), prefix('icon-code'))
})
}));
var showCodeEditor = editable && code;
var hasError = !!errorMessage;
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", (0, _extends2["default"])({
className: "rcv-container"
}, rest, {
ref: ref,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Preview["default"], {
hasError: hasError,
errorMessage: errorMessage,
onError: handleError,
children: compiledReactNode
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
className: "rcv-toolbar",
children: renderToolbar ? renderToolbar(showCodeButton, toggleButtonProps) : showCodeButton
}), showCodeEditor && /*#__PURE__*/(0, _react.createElement)(_CodeEditor["default"], (0, _extends2["default"])({}, editorProps, {
key: "jsx",
copyButtonAs: copyButtonAs,
copyButtonProps: copyButtonProps,
onChange: handleCodeChange,
className: (0, _classnames["default"])(editorClassName, 'rcv-editor'),
editorConfig: {
lineNumbers: true,
theme: "base16-" + theme
},
code: code
})), renderExtraFooter === null || renderExtraFooter === void 0 ? void 0 : renderExtraFooter()]
}));
});
var _default = exports["default"] = Renderer;