UNPKG

@churchapps/apphelper-markdown

Version:
86 lines (85 loc) 5.59 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import React, { useCallback, useMemo } from "react"; import "./editor.css"; import { LexicalComposer } from "@lexical/react/LexicalComposer"; import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"; import { ContentEditable } from "@lexical/react/LexicalContentEditable"; import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin"; import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin"; import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin"; import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary"; import { ListPlugin } from "@lexical/react/LexicalListPlugin"; import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin"; import { TRANSFORMERS, $convertToMarkdownString, $convertFromMarkdownString } from "@lexical/markdown"; import { HeadingNode, QuoteNode } from "@lexical/rich-text"; import { ListItemNode, ListNode } from "@lexical/list"; import { TableCellNode, TableNode, TableRowNode } from "@lexical/table"; import { AutoLinkNode, LinkNode } from "@lexical/link"; import { CodeHighlightNode, CodeNode } from "@lexical/code"; import { theme } from "./theme"; import { ToolbarPlugin, CustomAutoLinkPlugin, ListMaxIndentLevelPlugin, PLAYGROUND_TRANSFORMERS, ReadOnlyPlugin, ControlledEditorPlugin } from "./plugins"; import FloatingTextFormatToolbarPlugin from "./plugins/FloatingTextMenu/FloatingTextFormatToolbarPlugin"; import { MarkdownModal } from "./MarkdownModal"; import CustomLinkNodePlugin from "./plugins/customLink/CustomLinkNodePlugin"; import { CustomLinkNode } from "./plugins/customLink/CustomLinkNode"; import EmojisPlugin from "./plugins/emoji/EmojisPlugin"; import { EmojiNode } from "./plugins/emoji/EmojiNode"; import EmojiPickerPlugin from "./plugins/emoji/EmojiPickerPlugin"; function Editor({ value, onChange = () => { }, mode = "interactive", textAlign = "left", style, placeholder = "Enter some text...", showFloatingEditor = false, ...props }) { const [fullScreen, setFullScreen] = React.useState(false); const handleChange = useCallback((editorState) => { editorState.read(() => { const markdown = $convertToMarkdownString(PLAYGROUND_TRANSFORMERS); onChange(markdown); }); }, [onChange]); const onError = useCallback((error) => { console.error(error); }, []); const handleModalOnChange = useCallback((value) => { onChange(value); }, [onChange]); const handleCloseFullScreen = useCallback(() => { setFullScreen(false); }, []); const initialConfig = useMemo(() => ({ editorState: () => $convertFromMarkdownString(value, PLAYGROUND_TRANSFORMERS), namespace: "editor", theme, onError, nodes: [ HeadingNode, ListNode, ListItemNode, QuoteNode, CodeNode, CodeHighlightNode, TableNode, TableCellNode, TableRowNode, AutoLinkNode, LinkNode, CustomLinkNode, EmojiNode, { replace: LinkNode, with: (node) => (new CustomLinkNode(node.getURL(), node.getTarget(), [])) }, ], markdown: { transformers: PLAYGROUND_TRANSFORMERS } }), [value, onError]); const textAlignClass = useMemo(() => { switch (textAlign) { case "center": return "text-center"; case "right": return "text-right"; case "left": default: return "text-left"; } }, [textAlign]); return (_jsxs(_Fragment, { children: [_jsx(LexicalComposer, { initialConfig: initialConfig, children: _jsxs("div", { id: "markdown-editor-container", className: mode === "preview" ? `editor-container preview ${textAlignClass}` : `editor-container ${textAlignClass}`, style: useMemo(() => Object.assign({ border: mode === "preview" ? "none" : "1px solid lightgray" }, style), [mode, style]), children: [mode !== "preview" && (_jsx(ToolbarPlugin, { goFullScreen: useCallback(() => { setFullScreen(true); }, []) })), _jsxs("div", { id: "markdown-editor-inner", className: "editor-inner", children: [!fullScreen && (_jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { id: "markdown-editor-content", className: "editor-input", style: { minHeight: mode === "preview" ? "auto" : "150px" }, "data-element": JSON.stringify(props.element) }), placeholder: mode !== "preview" ? (_jsx("div", { id: "markdown-editor-placeholder", className: "editor-placeholder", children: placeholder })) : null, ErrorBoundary: LexicalErrorBoundary })), _jsx(CustomLinkNodePlugin, {}), mode !== "preview" && _jsx(EmojiPickerPlugin, {}), _jsx(EmojisPlugin, {}), showFloatingEditor && _jsx(FloatingTextFormatToolbarPlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange }), mode !== "preview" && _jsx(AutoFocusPlugin, {}), _jsx(HistoryPlugin, {}), _jsx(ListPlugin, {}), _jsx(CustomAutoLinkPlugin, {}), _jsx(ListMaxIndentLevelPlugin, { maxDepth: 7 }), _jsx(ReadOnlyPlugin, { isDisabled: mode === "preview" }), _jsx(ControlledEditorPlugin, { isFullscreen: fullScreen, value: value, isPreview: mode === "preview" }), _jsx(MarkdownShortcutPlugin, { transformers: TRANSFORMERS })] })] }) }), fullScreen && (_jsx(MarkdownModal, { onChange: handleModalOnChange, value: value, hideModal: handleCloseFullScreen }))] })); } export default Editor;