@uiw/react-markdown-editor
Version:
A markdown editor with preview, implemented with React.js and TypeScript.
163 lines • 6.51 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
var _excluded = ["prefixCls", "className", "onChange", "toolbars", "toolbarsMode", "toolbarsFilter", "visible", "renderPreview", "visibleEditor", "hideToolbar", "toolbarBottom", "enableScroll", "previewProps", "extensions", "previewWidth", "reExtensions"];
import React, { useState, useRef, useImperativeHandle, Fragment, useEffect, useCallback } from 'react';
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
import { languages } from '@codemirror/language-data';
import { EditorView } from '@codemirror/view';
import * as events from '@uiw/codemirror-extensions-events';
import CodeMirror from '@uiw/react-codemirror';
import MarkdownPreview from '@uiw/react-markdown-preview';
import ToolBar from './components/ToolBar';
import { getCommands, getModeCommands } from './commands';
import { defaultTheme } from './theme';
import "./index.css";
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
export * from './theme';
export * from './commands';
export * from '@uiw/react-markdown-preview';
export var scrollerStyle = EditorView.theme({
'&.cm-editor, & .cm-scroller': {
borderBottomRightRadius: '3px',
borderBottomLeftRadius: '3px'
}
});
var MarkdownEditor = /*#__PURE__*/React.forwardRef(MarkdownEditorInternal);
MarkdownEditor.Markdown = MarkdownPreview;
export default MarkdownEditor;
function MarkdownEditorInternal(props, ref) {
var {
prefixCls = 'md-editor',
className,
onChange,
toolbars = getCommands(),
toolbarsMode = getModeCommands(),
toolbarsFilter,
visible = true,
renderPreview,
visibleEditor = true,
hideToolbar = true,
toolbarBottom = false,
enableScroll = true,
previewProps = {},
extensions = [],
previewWidth = '50%',
reExtensions
} = props,
codemirrorProps = _objectWithoutPropertiesLoose(props, _excluded);
var [value, setValue] = useState(props.value || '');
var codeMirror = useRef(null);
var container = useRef(null);
var containerEditor = useRef(null);
var preview = useRef(null);
var active = useRef('editor');
useImperativeHandle(ref, () => ({
editor: codeMirror,
preview: preview
}), [codeMirror]);
var toolBarProps = {
preview: preview,
editor: codeMirror,
container: container,
containerEditor: containerEditor,
editorProps: _extends({}, props, {
previewWidth
})
};
var height = typeof codemirrorProps.height === 'number' ? codemirrorProps.height + "px" : codemirrorProps.height;
var previewScrollHandle = useCallback(event => {
if (!enableScroll) return;
var target = event.target;
var percent = target.scrollTop / target.scrollHeight;
if (active.current === 'editor' && preview.current) {
var _preview$current;
var previewHeihgt = ((_preview$current = preview.current) == null ? void 0 : _preview$current.scrollHeight) || 0;
preview.current.scrollTop = previewHeihgt * percent;
} else if (codeMirror.current && codeMirror.current.view) {
var editorScrollDom = codeMirror.current.view.scrollDOM;
var editorScrollHeihgt = codeMirror.current.view.scrollDOM.scrollHeight || 0;
editorScrollDom.scrollTop = editorScrollHeihgt * percent;
}
}, [enableScroll]);
var mouseoverHandle = () => active.current = 'preview';
var mouseleaveHandle = () => active.current = 'editor';
useEffect(() => {
var $preview = preview.current;
if ($preview && enableScroll) {
$preview.addEventListener('mouseover', mouseoverHandle, false);
$preview.addEventListener('mouseleave', mouseleaveHandle, false);
$preview.addEventListener('scroll', previewScrollHandle, false);
}
return () => {
if ($preview && enableScroll) {
$preview.removeEventListener('mouseover', mouseoverHandle);
$preview.removeEventListener('mouseleave', mouseoverHandle);
$preview.addEventListener('mouseleave', previewScrollHandle, false);
}
};
}, [preview, enableScroll, previewScrollHandle]);
var scrollExtensions = events.scroll({
scroll: previewScrollHandle
});
var extensionsData = reExtensions ? reExtensions : [markdown({
base: markdownLanguage,
codeLanguages: languages
}), scrollerStyle, ...extensions];
if (enableScroll) {
extensionsData.push(scrollExtensions);
}
var clsPreview = prefixCls + "-preview";
var cls = [prefixCls, 'wmde-markdown-var', className].filter(Boolean).join(' ');
previewProps['source'] = value;
var handleChange = (value, viewUpdate) => {
setValue(value);
onChange && onChange(value, viewUpdate);
};
var conentView = /*#__PURE__*/_jsxs("div", {
className: prefixCls + "-content",
style: {
height: codemirrorProps.height
},
children: [/*#__PURE__*/_jsx("div", {
className: prefixCls + "-content-editor",
ref: containerEditor,
children: visibleEditor && /*#__PURE__*/_jsx(CodeMirror, _extends({
theme: defaultTheme
}, codemirrorProps, {
extensions: extensionsData,
height: height,
ref: codeMirror,
onChange: handleChange
}))
}), /*#__PURE__*/_jsx("div", {
className: clsPreview,
ref: preview,
children: renderPreview ? renderPreview(previewProps, !!visible) : /*#__PURE__*/_jsx(MarkdownPreview, _extends({}, previewProps, {
"data-visible": !!visible
}))
})]
});
var clsToolbar = [prefixCls && prefixCls + "-toolbar-warp", prefixCls && toolbarBottom && prefixCls + "-toolbar-bottom"].filter(Boolean).join(' ');
var tools = toolbarsFilter ? toolbars.filter(toolbarsFilter) : toolbars;
var toolsMode = toolbarsFilter ? toolbarsMode.filter(toolbarsFilter) : toolbarsMode;
var toolbarView = hideToolbar && /*#__PURE__*/_jsxs("div", {
className: clsToolbar,
children: [/*#__PURE__*/_jsx(ToolBar, _extends({}, toolBarProps, {
toolbars: tools
})), /*#__PURE__*/_jsx(ToolBar, _extends({}, toolBarProps, {
toolbars: toolsMode,
mode: true
}))]
});
var child = toolbarBottom ? /*#__PURE__*/_jsxs(Fragment, {
children: [conentView, toolbarView]
}) : /*#__PURE__*/_jsxs(Fragment, {
children: [toolbarView, conentView]
});
return /*#__PURE__*/_jsx("div", {
className: cls,
ref: container,
children: child
});
}