mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
[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:
parent
88ebda42ff
commit
0ad8bf7664
@ -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;
|
||||
}
|
||||
|
@ -218,6 +218,10 @@ export const Table = Node.create({
|
||||
addKeyboardShortcuts() {
|
||||
return {
|
||||
Tab: () => {
|
||||
if (this.editor.isActive("table")) {
|
||||
if (this.editor.isActive("listItem") || this.editor.isActive("taskItem")) {
|
||||
return false;
|
||||
}
|
||||
if (this.editor.commands.goToNextCell()) {
|
||||
return true;
|
||||
}
|
||||
@ -227,6 +231,8 @@ export const Table = Node.create({
|
||||
}
|
||||
|
||||
return this.editor.chain().addRowAfter().goToNextCell().run();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
"Shift-Tab": () => this.editor.commands.goToPreviousCell(),
|
||||
Backspace: deleteTableWhenAllCellsSelected,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
[
|
||||
const elements = document.elementsFromPoint(coords.x, coords.y);
|
||||
const generalSelectors = [
|
||||
"li",
|
||||
"p:not(:first-child)",
|
||||
".code-block",
|
||||
"blockquote",
|
||||
"h1, h2, h3",
|
||||
"table",
|
||||
".table-wrapper",
|
||||
"[data-type=horizontalRule]",
|
||||
].join(", ")
|
||||
)
|
||||
);
|
||||
].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) {
|
||||
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,
|
||||
}),
|
||||
];
|
||||
},
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user