@ceedcv-maya/shared-editor-react
v0.15.0
Published
Unified rich-text editor for Maya: MayaEditor (TipTap) with lite/full modes, HTML SSR renderer, anchored-comments support.
Maintainers
Readme
@ceedcv-maya/shared-editor-react
Unified TipTap editor for the Maya ecosystem.
Components
<MayaEditor mode="lite" | "full" />— single editor with two visual modes.litefor short comments and alerts;fullfor templates and documents.<EditorContentHtml html />— read-only renderer with DOMPurify sanitisation (aligned with the server-sideTiptapHtmlRenderer).<EditorToolbar />— toolbar builder, used internally byMayaEditorand exposed for custom integrations.
Extensions
IframeBlock— sandboxed iframe block with optional domain allowlist.AlertBlock— variants info / warning / success / danger.CommentMark— anchored-comment mark (paired withAnchoredCommentControllerserver-side).
Document import & block splitting
Helpers behind the "Import from Word → blocks" flow (DocxBlockSplitter in maya_dms):
docxToHtml(file)/docxToHtmlResult(file)— convert a.docxFileto sanitised, editor-ready HTML via mammoth (loaded dynamically, ~430KB).docxToHtmlResultalso returns mammoth'smessages(warnings for unrecognised styles / track changes that may not import cleanly).splitHtmlIntoBlocks(html)— split an HTML fragment into top-levelBlockChunk[](heading / paragraph / list / table / figure / blockquote / codeBlock / horizontalRule / other), preserving each element'souterHTMLfor a lossless round-trip. List items are exploded one chunk per<li>(re-wrapped in their<ul>/<ol>) so callers can assign each bullet to a different block. Empty whitespace/<br>-only paragraphs are flaggedisEmpty.htmlToTiptapDoc(html, extensions?)— convert HTML to a TipTap JSON doc using a headless editor with the canonical Maya extensions, so the round-trip matches what the live editor persists. Empty input yields a doc with one empty paragraph (TipTap's normalised empty state).buildMayaEditorExtensions(mode)— the canonical TipTap extension list, shared byMayaEditorandhtmlToTiptapDoc(single source of truth for the schema).
const html = await docxToHtml(file);
const chunks = splitHtmlIntoBlocks(html).filter((c) => !c.isEmpty);
// …user groups chunks into blocks…
const doc = htmlToTiptapDoc(groupHtml); // → persist doc.contentKnown mammoth limitations: track changes and comments are dropped; non-standard Word styles may not map. docxToHtmlResult().messages surfaces these.
Anchored comments
getAnchorRange(editor, commentId)/setAnchorRange(editor, id, range)rebaseAnchors(anchors, tr)— applies a ProseMirrorTransaction.mappingto a list of anchors and flags collapsed ones as invalid.
Sanitisation
sanitizeEditorHtml(rawHtml)— DOMPurify config covering the full set of tags emitted byTiptapHtmlRenderer(paragraph, headings, lists, tables, blockquote, code, images, iframes withsandbox, alerts).
Usage
import { MayaEditor } from '@ceedcv-maya/shared-editor-react';
<MayaEditor
mode="full"
initialContent={template.html}
editable={canEdit}
onChange={(html) => save(html)}
isDark={theme === 'dark'}
/>Lite mode for short comments:
<MayaEditor mode="lite" initialContent={comment.body} onChange={setBody} />