mirror of https://github.com/halo-dev/halo
fix: resolve the issue of text editing not being effective before the table (#5365)
#### 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 解决默认富文本编辑器表格前字符无法被编辑的问题。 ```pull/5382/head v2.12.3
parent
50e954d297
commit
ca4f705f2d
|
@ -15,9 +15,6 @@ import {
|
||||||
type NodeView,
|
type NodeView,
|
||||||
type EditorState,
|
type EditorState,
|
||||||
type DOMOutputSpec,
|
type DOMOutputSpec,
|
||||||
Plugin,
|
|
||||||
DecorationSet,
|
|
||||||
Decoration,
|
|
||||||
} from "@/tiptap/pm";
|
} from "@/tiptap/pm";
|
||||||
import TableCell from "./table-cell";
|
import TableCell from "./table-cell";
|
||||||
import TableRow from "./table-row";
|
import TableRow from "./table-row";
|
||||||
|
@ -129,14 +126,22 @@ class TableView implements NodeView {
|
||||||
this.containerDOM.addEventListener("wheel", (e) => {
|
this.containerDOM.addEventListener("wheel", (e) => {
|
||||||
return this.handleHorizontalWheel(this.containerDOM, 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", () => {
|
this.containerDOM.addEventListener("scroll", () => {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const { state, view } = editor;
|
const { view } = editor;
|
||||||
const { tr } = state;
|
const coords = { left: mouseX, top: mouseY };
|
||||||
view.dispatch(tr);
|
const pos = view.posAtCoords(coords);
|
||||||
return false;
|
editor.commands.setTextSelection(pos?.pos || 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.scrollDom = document.createElement("div");
|
this.scrollDom = document.createElement("div");
|
||||||
|
@ -147,6 +152,11 @@ class TableView implements NodeView {
|
||||||
this.colgroup = this.table.appendChild(document.createElement("colgroup"));
|
this.colgroup = this.table.appendChild(document.createElement("colgroup"));
|
||||||
updateColumns(node, this.colgroup, this.table, cellMinWidth);
|
updateColumns(node, this.colgroup, this.table, cellMinWidth);
|
||||||
this.contentDOM = this.table.appendChild(document.createElement("tbody"));
|
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) {
|
update(node: ProseMirrorNode) {
|
||||||
|
@ -156,15 +166,32 @@ class TableView implements NodeView {
|
||||||
|
|
||||||
this.node = node;
|
this.node = node;
|
||||||
updateColumns(node, this.colgroup, this.table, this.cellMinWidth);
|
updateColumns(node, this.colgroup, this.table, this.cellMinWidth);
|
||||||
|
this.updateTableShadow();
|
||||||
return true;
|
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(
|
ignoreMutation(
|
||||||
mutation: MutationRecord | { type: "selection"; target: Element }
|
mutation: MutationRecord | { type: "selection"; target: Element }
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
mutation.type === "attributes" &&
|
mutation.type === "attributes" &&
|
||||||
(mutation.target === this.table ||
|
(mutation.target === this.table ||
|
||||||
|
mutation.target === this.dom ||
|
||||||
this.colgroup.contains(mutation.target))
|
this.colgroup.contains(mutation.target))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -487,48 +514,6 @@ const Table = TiptapTable.extend<ExtensionOptions & TableOptions>({
|
||||||
onTransaction() {
|
onTransaction() {
|
||||||
editor = this.editor;
|
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 });
|
}).configure({ resizable: true });
|
||||||
|
|
||||||
export default Table;
|
export default Table;
|
||||||
|
|
Loading…
Reference in New Issue