UNPKG

@rtdui/editor

Version:

React rich text editor based on tiptap

226 lines (224 loc) 10.2 kB
'use client'; const require_runtime = require('../_virtual/_rolldown/runtime.cjs'); const require_uploadImageWithResizable = require('./tiptap_extensions/extension-image-upload/uploadImageWithResizable.cjs'); const require_markdownPaste = require('./tiptap_extensions/extension-markdown-paste/markdownPaste.cjs'); const require_math_katex_inline = require('./tiptap_extensions/extension-math/math-katex-inline.cjs'); const require_math_katex_block = require('./tiptap_extensions/extension-math/math-katex-block.cjs'); const require_code_block_shiki = require('./tiptap_extensions/extension-code-block-shiki/code-block-shiki.cjs'); require('./tiptap.cjs'); const require_Toolbar = require('./toolbar/Toolbar.cjs'); require('./toolbar/index.cjs'); let react = require("react"); let clsx = require("clsx"); clsx = require_runtime.__toESM(clsx); let _tiptap_react = require("@tiptap/react"); let _tiptap_react_menus = require("@tiptap/react/menus"); let _tabler_icons_react = require("@tabler/icons-react"); let react_jsx_runtime = require("react/jsx-runtime"); let _tiptap_starter_kit = require("@tiptap/starter-kit"); let _tiptap_extension_table = require("@tiptap/extension-table"); let _tiptap_extension_list = require("@tiptap/extension-list"); let _tiptap_extension_superscript = require("@tiptap/extension-superscript"); let _tiptap_extension_subscript = require("@tiptap/extension-subscript"); let _tiptap_extension_highlight = require("@tiptap/extension-highlight"); let _tiptap_extensions = require("@tiptap/extensions"); let _tiptap_extension_text_align = require("@tiptap/extension-text-align"); let _tiptap_extension_text_style = require("@tiptap/extension-text-style"); //#region packages/editor/src/RichTextEditor/RichTextEditor.tsx function RichTextEditor(props) { const { ref, slots, editable = true, placeholder = "输入内容或者从剪贴板粘贴, 复制粘贴支持Markdown", limit, uploadImageUrl, imageResizable = true, className, ...other } = props; const editorOptions = { extensions: [ _tiptap_starter_kit.StarterKit.configure({ codeBlock: false, link: { openOnClick: !editable } }), _tiptap_extension_table.TableKit.configure({ table: { resizable: true }, tableCell: { HTMLAttributes: { class: "not-prose" } }, tableHeader: { HTMLAttributes: { class: "not-prose" } } }), _tiptap_extension_list.TaskItem.configure({ nested: true }), _tiptap_extension_list.TaskList, _tiptap_extension_superscript.Superscript, _tiptap_extension_subscript.Subscript, _tiptap_extension_highlight.Highlight, _tiptap_extensions.Placeholder.configure({ placeholder }), _tiptap_extension_text_align.TextAlign.configure({ types: [ "heading", "paragraph", "tableHeader", "tableCell" ] }), _tiptap_extension_text_style.TextStyleKit, require_code_block_shiki.CodeBlockShiki, require_uploadImageWithResizable.UploadImageWithResizable.configure({ resizable: imageResizable, inline: true, url: uploadImageUrl, method: "post" }), require_markdownPaste.MarkdownPaste, require_math_katex_inline.MathKatexInline, require_math_katex_block.MathKatexBlock ], editable }; if (limit) editorOptions.extensions?.push(_tiptap_extensions.CharacterCount.configure({ limit })); const editor = (0, _tiptap_react.useEditor)(editorOptions); const { charactersCount, wordsCount } = (0, _tiptap_react.useEditorState)({ editor, selector: (context) => ({ charactersCount: context.editor?.storage?.characterCount?.characters(), wordsCount: context.editor?.storage?.characterCount?.words() }) }); (0, react.useImperativeHandle)(ref, () => ({ getJSON: () => { if (editor) return editor.getJSON(); return null; }, setContent: (jsonOrHtml) => { if (editor) editor.commands.setContent(jsonOrHtml); } })); if (!editor) return null; return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { ...other, className: (0, clsx.default)(className), children: [ editable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Toolbar.Toolbar, { editor, className: (0, clsx.default)("editor-content", slots?.toolbar) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tiptap_react_menus.FloatingMenu, { editor, shouldShow: ({ editor }) => editor.isActive("tableCell") || editor.isActive("tableHeader"), options: { autoPlacement: { allowedPlacements: ["top-start", "top-end"] } }, children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { className: "join", children: [ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "插入表格", onClick: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconTable, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "左侧插入列", onClick: () => editor.chain().focus().addColumnBefore().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconColumnInsertLeft, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "右侧插入列", onClick: () => editor.chain().focus().addColumnAfter().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconColumnInsertRight, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "删除列", onClick: () => editor.chain().focus().deleteColumn().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconContainerOff, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "上方插入行", onClick: () => editor.chain().focus().addRowBefore().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconRowInsertTop, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "下方插入行", onClick: () => editor.chain().focus().addRowAfter().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconRowInsertBottom, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "删除行", onClick: () => editor.chain().focus().deleteRow().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconContainerOff, { className: "rotate-90", stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "删除表格", onClick: () => editor.chain().focus().deleteTable().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconTableOff, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "合并单元格", onClick: () => editor.chain().focus().mergeCells().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconViewportNarrow, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "拆分单元格", onClick: () => editor.chain().focus().splitCell().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowBarBoth, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "合并或拆分", onClick: () => editor.chain().focus().mergeOrSplit().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconSquareToggle, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "首列切换", onClick: () => editor.chain().focus().toggleHeaderColumn().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconBoxAlignLeft, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "首行切换", onClick: () => editor.chain().focus().toggleHeaderRow().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconBoxAlignTop, { stroke: 1 }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", className: "join-item btn btn-sm px-1", title: "单元格切换行头样式", onClick: () => editor.chain().focus().toggleHeaderCell().run(), children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconBoxAlignTopLeft, { stroke: 1 }) }) ] }) })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tiptap_react.EditorContent, { editor, className: (0, clsx.default)("editor-content prose max-w-none! overflow-y-auto", slots?.content) }), limit && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { className: "character-count text-xs flex flex-row-reverse px-1.5", children: [ charactersCount, " / ", limit ] }) ] }); } //#endregion exports.RichTextEditor = RichTextEditor;