UNPKG

@churchapps/apphelper-markdown

Version:

ChurchApps markdown/lexical editor components

85 lines (84 loc) 3.56 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useState, useEffect } from "react"; import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"; import { $generateHtmlFromNodes, $generateNodesFromDOM } from "@lexical/html"; import { $getRoot, $insertNodes } from "lexical"; import { TextField, Box } from "@mui/material"; import { cleanHtml } from "../utils/cleanHtml"; export default function HtmlSourcePlugin({ isSourceMode }) { const [editor] = useLexicalComposerContext(); const [htmlSource, setHtmlSource] = useState(""); const [prevIsSourceMode, setPrevIsSourceMode] = useState(false); // Get HTML from editor when switching to source mode useEffect(() => { if (isSourceMode && !prevIsSourceMode) { editor.getEditorState().read(() => { const rawHtml = $generateHtmlFromNodes(editor); const cleanedHtml = cleanHtml(rawHtml); setHtmlSource(cleanedHtml); }); } setPrevIsSourceMode(isSourceMode); }, [isSourceMode, prevIsSourceMode, editor]); // Update editor when leaving source mode useEffect(() => { if (!isSourceMode && prevIsSourceMode && htmlSource !== undefined) { editor.update(() => { const parser = new DOMParser(); const dom = parser.parseFromString(htmlSource || "", "text/html"); const nodes = $generateNodesFromDOM(editor, dom); // Only clear and insert if we got valid nodes if (nodes && nodes.length > 0) { const root = $getRoot(); root.clear(); $insertNodes(nodes); } }); } }, [isSourceMode, prevIsSourceMode, htmlSource, editor]); // Update HTML on editor changes when not in source mode useEffect(() => { if (!isSourceMode) { return editor.registerUpdateListener(({ editorState }) => { editorState.read(() => { const rawHtml = $generateHtmlFromNodes(editor); const cleanedHtml = cleanHtml(rawHtml); setHtmlSource(cleanedHtml); }); }); } }, [editor, isSourceMode]); if (!isSourceMode) { return null; } return (_jsx(Box, { sx: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, bgcolor: "background.paper", zIndex: 10, display: "flex", flexDirection: "column" }, children: _jsx(TextField, { multiline: true, fullWidth: true, value: htmlSource, onChange: (e) => setHtmlSource(e.target.value), placeholder: "Enter HTML code...", variant: "outlined", sx: { flex: 1, height: "100%", "& .MuiOutlinedInput-root": { height: "100%", alignItems: "flex-start", fontFamily: 'Monaco, Consolas, "Courier New", monospace', fontSize: "14px", padding: "15px 10px", "& fieldset": { border: "none" } }, "& .MuiOutlinedInput-input": { height: "100%", minHeight: "150px", overflow: "auto", padding: 0, backgroundColor: "#f5f5f5", resize: "none" } } }) })); }