From ca4f705f2dd2a0a0486dab65e4abd3cc30f56da8 Mon Sep 17 00:00:00 2001 From: Takagi <1103069291@qq.com> Date: Wed, 21 Feb 2024 10:44:09 +0800 Subject: [PATCH] fix: resolve the issue of text editing not being effective before the table (#5365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind bug /area editor /area console #### What this PR does / why we need it: 在 #5191 中对表格新增了如果可以左右滚动时,则显示阴影的特性。而根据 `prosemirror` 的数据流处理策略,在 `decorations` 中,state 是 new EditorState,但通过 `this.editor.view` 获取到的 view 为 old EditorView,进而导致使用了最新的坐标,并且使用其坐标通过旧版本的 view 中获取 DOM 而产生的错误。 本 PR 使用 `NodeView` 而不是 `decorations` 来重新处理表格阴影。 #### How to test it? 在默认富文本编辑器中新建一个表格。在表格前使用拼音输入文本,查看此文本能否被输入。 同时查看表格阴影是否存在 #### Which issue(s) this PR fixes: Fixes #5352 #### Does this PR introduce a user-facing change? ```release-note 解决默认富文本编辑器表格前字符无法被编辑的问题。 ``` --- .../editor/src/extensions/table/index.ts | 83 ++++++++----------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/ui/packages/editor/src/extensions/table/index.ts b/ui/packages/editor/src/extensions/table/index.ts index f9862e5a29..30cba2308e 100644 --- a/ui/packages/editor/src/extensions/table/index.ts +++ b/ui/packages/editor/src/extensions/table/index.ts @@ -15,9 +15,6 @@ import { type NodeView, type EditorState, type DOMOutputSpec, - Plugin, - DecorationSet, - Decoration, } from "@/tiptap/pm"; import TableCell from "./table-cell"; import TableRow from "./table-row"; @@ -129,14 +126,22 @@ class TableView implements NodeView { this.containerDOM.addEventListener("wheel", (e) => { return this.handleHorizontalWheel(this.containerDOM, e); }); + + let mouseX = 0; + let mouseY = 0; + document.addEventListener("mousemove", function (event) { + mouseX = event.clientX; + mouseY = event.clientY; + }); + this.containerDOM.addEventListener("scroll", () => { if (!editor) { return false; } - const { state, view } = editor; - const { tr } = state; - view.dispatch(tr); - return false; + const { view } = editor; + const coords = { left: mouseX, top: mouseY }; + const pos = view.posAtCoords(coords); + editor.commands.setTextSelection(pos?.pos || 0); }); this.scrollDom = document.createElement("div"); @@ -147,6 +152,11 @@ class TableView implements NodeView { this.colgroup = this.table.appendChild(document.createElement("colgroup")); updateColumns(node, this.colgroup, this.table, cellMinWidth); this.contentDOM = this.table.appendChild(document.createElement("tbody")); + // delay execution during initialization, otherwise + // the correct scrollWidth cannot be obtained. + setTimeout(() => { + this.updateTableShadow(); + }); } update(node: ProseMirrorNode) { @@ -156,15 +166,32 @@ class TableView implements NodeView { this.node = node; updateColumns(node, this.colgroup, this.table, this.cellMinWidth); + this.updateTableShadow(); return true; } + updateTableShadow() { + const { scrollWidth, clientWidth, scrollLeft } = this + .containerDOM as HTMLElement; + if (scrollWidth > clientWidth && scrollLeft < scrollWidth - clientWidth) { + this.dom.classList.add("table-right-shadow"); + } else { + this.dom.classList.remove("table-right-shadow"); + } + if (scrollLeft > 0) { + this.dom.classList.add("table-left-shadow"); + } else { + this.dom.classList.remove("table-left-shadow"); + } + } + ignoreMutation( mutation: MutationRecord | { type: "selection"; target: Element } ) { return ( mutation.type === "attributes" && (mutation.target === this.table || + mutation.target === this.dom || this.colgroup.contains(mutation.target)) ); } @@ -487,48 +514,6 @@ const Table = TiptapTable.extend({ onTransaction() { editor = this.editor; }, - - addProseMirrorPlugins() { - const plugins = this.parent?.() ?? []; - return [ - ...plugins, - new Plugin({ - props: { - decorations: (state) => { - const { doc, tr } = state; - const decorations: Decoration[] = []; - doc.descendants((node, pos) => { - if (node.type.name === Table.name) { - const { view } = this.editor; - const nodeDom = view.nodeDOM(pos) || view.domAtPos(pos)?.node; - if (!nodeDom) { - return true; - } - const { scrollWidth, clientWidth, scrollLeft } = - nodeDom.firstChild as HTMLElement; - let classNames = ""; - if ( - scrollWidth > clientWidth && - scrollLeft < scrollWidth - clientWidth - ) { - classNames += "table-right-shadow "; - } - if (scrollLeft > 0) { - classNames += "table-left-shadow "; - } - decorations.push( - Decoration.node(pos, pos + node.nodeSize, { - class: classNames, - }) - ); - } - }); - return DecorationSet.create(tr.doc, decorations); - }, - }, - }), - ]; - }, }).configure({ resizable: true }); export default Table;