You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Global-sales/src/components/LexicalEditor/index.jsx

215 lines
7.9 KiB
JavaScript

import { createContext, useEffect, useState } from 'react';
import ExampleTheme from "./themes/ExampleTheme";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import {PlainTextPlugin} from '@lexical/react/LexicalPlainTextPlugin';
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
import {LexicalErrorBoundary} from "@lexical/react/LexicalErrorBoundary";
import {TabIndentationPlugin} from '@lexical/react/LexicalTabIndentationPlugin';
import TreeViewPlugin from "./plugins/TreeViewPlugin";
import ToolbarPlugin from "./plugins/ToolbarPlugin";
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
import { ListItemNode, ListNode } from "@lexical/list";
import { CodeHighlightNode, CodeNode } from "@lexical/code";
import { AutoLinkNode, LinkNode } from "@lexical/link";
// import {ClickableLinkPlugin} from '@lexical/react/LexicalClickableLinkPlugin';
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
import {HorizontalRulePlugin} from '@lexical/react/LexicalHorizontalRulePlugin';
import {HorizontalRuleNode} from '@lexical/react/LexicalHorizontalRuleNode';
import { TRANSFORMERS } from "@lexical/markdown";
import ListMaxIndentLevelPlugin from "./plugins/ListMaxIndentLevelPlugin";
import CodeHighlightPlugin from "./plugins/CodeHighlightPlugin";
import AutoLinkPlugin from "./plugins/AutoLinkPlugin";
import TabFocusPlugin from './plugins/TabFocusPlugin';
import EditorRefPlugin from './plugins/EditorRefPlugin'
import ImagesPlugin from './plugins/ImagesPlugin';
import InlineImagePlugin from './plugins/InlineImagePlugin';
import DragDropPaste from './plugins/DragDropPastePlugin';
import { ImageNode } from './nodes/ImageNode';
import {InlineImageNode} from './nodes/InlineImageNode/InlineImageNode';
import { ExtendedTextNode } from './nodes/ExtendedTextNode';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
// import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
import {TablePlugin} from '@lexical/react/LexicalTablePlugin';
import TableCellActionMenuPlugin from './plugins/TableActionMenuPlugin';
import TableCellResizer from './plugins/TableCellResizer';
// import TableHoverActionsPlugin from './plugins/TableHoverActionsPlugin';
// import {useLexicalEditable} from '@lexical/react/useLexicalEditable';
import FormatPaintPlugin from './plugins/FormatPaint';
import { TextNode, $getRoot, $getSelection, $createParagraphNode } from 'lexical';
import { $generateHtmlFromNodes, $generateNodesFromDOM, } from '@lexical/html';
// import { } from '@lexical/clipboard';
import { isEmpty } from '@/utils/commons';
import {useSettings} from './context/SettingsContext';
import './styles.css';
function Placeholder() {
return <div className="editor-placeholder">Enter some rich text...</div>;
}
const editorConfig = {
// The editor theme
// theme: {},
theme: ExampleTheme,
// Handling of errors during update
onError(error) {
console.log(error)
throw error;
},
// Any custom nodes go here
nodes: [
ExtendedTextNode,
{
replace: TextNode,
with: (node) => new ExtendedTextNode(node.__text),
withKlass: ExtendedTextNode,
},
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode,
HorizontalRuleNode,
ImageNode,InlineImageNode,
]
};
function LexicalDefaultValuePlugin({ value = '' }= {}) {
const [editor] = useLexicalComposerContext();
const updateHTML = (editor, value, clear) => {
const root = $getRoot();
if (clear) {
root.clear();
}
if (isEmpty(value)) {
root.clear();
} else {
const parser = new DOMParser();
const dom = parser.parseFromString(value, "text/html");
const nodes = $generateNodesFromDOM(editor, dom);
nodes.filter(n => n.__size !== 0).forEach((n) => {
const paragraphNode = $createParagraphNode();
paragraphNode.append(n);
root.append(paragraphNode);
});
}
};
useEffect(() => {
if (editor) {
editor.update(() => {
updateHTML(editor, value, true);
});
}
}, [editor, value]);
return null;
}
function MyOnChangePlugin({ ignoreHistoryMergeTagChange = true, ignoreSelectionChange = true, onChange }) {
const [editor] = useLexicalComposerContext();
useEffect(() => {
if (typeof onChange === 'function') {
return editor.registerUpdateListener(({editorState, dirtyElements, dirtyLeaves, prevEditorState, tags}) => {
if (
(ignoreSelectionChange &&
dirtyElements.size === 0 &&
dirtyLeaves.size === 0) ||
(ignoreHistoryMergeTagChange && tags.has('history-merge')) ||
prevEditorState.isEmpty()
) {
return;
}
editorState.read(() => {
const root = $getRoot();
const textContent = root.getTextContent();
const html = $generateHtmlFromNodes(editor);
onChange({ editorStateJSON: editorState.toJSON(), editor, tags, htmlContent: html, textContent });
});
});
}
}, [editor, ignoreHistoryMergeTagChange, ignoreSelectionChange, onChange]);
return null;
}
export default function Editor({ isRichText, isDebug, editorRef, onChange, defaultValue, stateJson, ...props }) {
const {
settings: {
isCollab,
isAutocomplete,
isMaxLength,
isCharLimit,
isCharLimitUtf8,
// isRichText,
showTreeView,
showTableOfContents,
shouldUseLexicalContextMenu,
shouldPreserveNewLinesInMarkdown,
tableCellMerge,
tableCellBackgroundColor,
},
} = useSettings();
return (
<LexicalComposer initialConfig={editorConfig}>
<div className='editor-container'>
{isRichText && <ToolbarPlugin />}
<div className='editor-inner'>
{/* <LexicalPlainText /> */}
{isRichText ? (
<RichTextPlugin contentEditable={<ContentEditable className='editor-input' />} placeholder={<Placeholder />} ErrorBoundary={LexicalErrorBoundary} />
) : (
<PlainTextPlugin contentEditable={<ContentEditable className='editor-pure-input' />} ErrorBoundary={LexicalErrorBoundary} />
)}
<HistoryPlugin />
{(import.meta.env.DEV && isDebug) && <TreeViewPlugin />}
<LexicalDefaultValuePlugin value={defaultValue} />
<DragDropPaste />
<AutoFocusPlugin />
<CodeHighlightPlugin />
<ListPlugin />
<ListMaxIndentLevelPlugin maxDepth={7} />
<AutoLinkPlugin />
<LinkPlugin />
<MarkdownShortcutPlugin transformers={TRANSFORMERS} />
<TablePlugin hasCellMerge={tableCellMerge} hasCellBackgroundColor={tableCellBackgroundColor} />
<TableCellResizer />
{/* <TableHoverActionsPlugin /> */}
<TableCellActionMenuPlugin
// anchorElem={floatingAnchorElem}
cellMerge={true}
/>
<TabFocusPlugin />
<TabIndentationPlugin />
<HorizontalRulePlugin />
<EditorRefPlugin editorRef={editorRef} />
<ImagesPlugin />
<InlineImagePlugin />
<FormatPaintPlugin />
<MyOnChangePlugin onChange={onChange}/>
</div>
</div>
</LexicalComposer>
);
}