[WEB-1118] fix: table selections using drag handle fixed (#4429)

* fix: table selections in using drag handle fixed

* fix: not show drag handles for empty p tags
This commit is contained in:
M. Palanikannan 2024-05-10 17:32:23 +05:30 committed by GitHub
parent 88ebda42ff
commit 0ad8bf7664
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 82 additions and 47 deletions

View File

@ -97,6 +97,9 @@ const replaceCodeBlockWithContent = (editor: Editor) => {
const startPos = pos;
const endPos = pos + node.nodeSize;
const textContent = node.textContent;
if (textContent.length === 0) {
editor.chain().focus().toggleCodeBlock().run();
}
replaceCodeBlock(startPos, endPos, textContent);
return false;
}

View File

@ -218,15 +218,21 @@ export const Table = Node.create({
addKeyboardShortcuts() {
return {
Tab: () => {
if (this.editor.commands.goToNextCell()) {
return true;
}
if (this.editor.isActive("table")) {
if (this.editor.isActive("listItem") || this.editor.isActive("taskItem")) {
return false;
}
if (this.editor.commands.goToNextCell()) {
return true;
}
if (!this.editor.can().addRowAfter()) {
return false;
}
if (!this.editor.can().addRowAfter()) {
return false;
}
return this.editor.chain().addRowAfter().goToNextCell().run();
return this.editor.chain().addRowAfter().goToNextCell().run();
}
return false;
},
"Shift-Tab": () => this.editor.commands.goToPreviousCell(),
Backspace: deleteTableWhenAllCellsSelected,

View File

@ -15,7 +15,6 @@ export function CoreEditorProps(editorClassName: string): EditorProps {
if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
const slashCommand = document.querySelector("#slash-command");
if (slashCommand) {
console.log("registered");
return true;
}
}

View File

@ -14,6 +14,21 @@ export interface DragHandleOptions {
};
}
export const DragAndDrop = (setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void) =>
Extension.create({
name: "dragAndDrop",
addProseMirrorPlugins() {
return [
DragHandle({
dragHandleWidth: 24,
scrollThreshold: { up: 300, down: 100 },
setHideDragHandle,
}),
];
},
});
function createDragHandleElement(): HTMLElement {
const dragHandleElement = document.createElement("div");
dragHandleElement.draggable = true;
@ -49,23 +64,31 @@ function absoluteRect(node: Element) {
}
function nodeDOMAtCoords(coords: { x: number; y: number }) {
return document
.elementsFromPoint(coords.x, coords.y)
.find(
(elem: Element) =>
elem.parentElement?.matches?.(".ProseMirror") ||
elem.matches(
[
"li",
"p:not(:first-child)",
".code-block",
"blockquote",
"h1, h2, h3",
"table",
"[data-type=horizontalRule]",
].join(", ")
)
);
const elements = document.elementsFromPoint(coords.x, coords.y);
const generalSelectors = [
"li",
"p:not(:first-child)",
".code-block",
"blockquote",
"h1, h2, h3",
".table-wrapper",
"[data-type=horizontalRule]",
].join(", ");
for (const elem of elements) {
// if the element is a <p> tag that is the first child of a td or th
if (
(elem.matches("td > p:first-child") || elem.matches("th > p:first-child")) &&
elem?.textContent?.trim() !== ""
) {
return elem; // Return only if p tag is not empty
}
// apply general selector
if (elem.matches(generalSelectors)) {
return elem;
}
}
return null;
}
function nodePosAtDOM(node: Element, view: EditorView, options: DragHandleOptions) {
@ -86,15 +109,19 @@ function nodePosAtDOMForBlockquotes(node: Element, view: EditorView) {
})?.inside;
}
function calcNodePos(pos: number, view: EditorView) {
function calcNodePos(pos: number, view: EditorView, node: Element) {
const maxPos = view.state.doc.content.size;
const safePos = Math.max(0, Math.min(pos, maxPos));
const $pos = view.state.doc.resolve(safePos);
if ($pos.depth > 1) {
const newPos = $pos.before($pos.depth);
return Math.max(0, Math.min(newPos, maxPos));
if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
// only for nested lists
const newPos = $pos.before($pos.depth);
return Math.max(0, Math.min(newPos, maxPos));
}
}
return safePos;
}
@ -114,12 +141,12 @@ function DragHandle(options: DragHandleOptions) {
let draggedNodePos = nodePosAtDOM(node, view, options);
if (draggedNodePos == null || draggedNodePos < 0) return;
draggedNodePos = calcNodePos(draggedNodePos, view);
draggedNodePos = calcNodePos(draggedNodePos, view, node);
const { from, to } = view.state.selection;
const diff = from - to;
const fromSelectionPos = calcNodePos(from, view);
const fromSelectionPos = calcNodePos(from, view, node);
let differentNodeSelected = false;
const nodePos = view.state.doc.resolve(fromSelectionPos);
@ -148,6 +175,19 @@ function DragHandle(options: DragHandleOptions) {
listType = node.parentElement!.tagName;
}
if (node.matches("blockquote")) {
let nodePosForBlockquotes = nodePosAtDOMForBlockquotes(node, view);
if (nodePosForBlockquotes === null || nodePosForBlockquotes === undefined) return;
const docSize = view.state.doc.content.size;
nodePosForBlockquotes = Math.max(0, Math.min(nodePosForBlockquotes, docSize));
if (nodePosForBlockquotes >= 0 && nodePosForBlockquotes <= docSize) {
const nodeSelection = NodeSelection.create(view.state.doc, nodePosForBlockquotes);
view.dispatch(view.state.tr.setSelection(nodeSelection));
}
}
const slice = view.state.selection.content();
const { dom, text } = __serializeForClipboard(view, slice);
@ -190,7 +230,7 @@ function DragHandle(options: DragHandleOptions) {
if (nodePos === null || nodePos === undefined) return;
// Adjust the nodePos to point to the start of the node, ensuring NodeSelection can be applied
nodePos = calcNodePos(nodePos, view);
nodePos = calcNodePos(nodePos, view, node);
// Use NodeSelection to select the node at the calculated position
const nodeSelection = NodeSelection.create(view.state.doc, nodePos);
@ -279,9 +319,11 @@ function DragHandle(options: DragHandleOptions) {
// Li markers
if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
rect.top += 4;
rect.left -= 18;
}
if (node.matches(".table-wrapper")) {
rect.top += 8;
}
rect.width = options.dragHandleWidth;
@ -352,18 +394,3 @@ function DragHandle(options: DragHandleOptions) {
},
});
}
export const DragAndDrop = (setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void) =>
Extension.create({
name: "dragAndDrop",
addProseMirrorPlugins() {
return [
DragHandle({
dragHandleWidth: 24,
scrollThreshold: { up: 300, down: 100 },
setHideDragHandle,
}),
];
},
});