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 startPos = pos;
|
||||||
const endPos = pos + node.nodeSize;
|
const endPos = pos + node.nodeSize;
|
||||||
const textContent = node.textContent;
|
const textContent = node.textContent;
|
||||||
|
if (textContent.length === 0) {
|
||||||
|
editor.chain().focus().toggleCodeBlock().run();
|
||||||
|
}
|
||||||
replaceCodeBlock(startPos, endPos, textContent);
|
replaceCodeBlock(startPos, endPos, textContent);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,10 @@ export const Table = Node.create({
|
|||||||
addKeyboardShortcuts() {
|
addKeyboardShortcuts() {
|
||||||
return {
|
return {
|
||||||
Tab: () => {
|
Tab: () => {
|
||||||
|
if (this.editor.isActive("table")) {
|
||||||
|
if (this.editor.isActive("listItem") || this.editor.isActive("taskItem")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (this.editor.commands.goToNextCell()) {
|
if (this.editor.commands.goToNextCell()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -227,6 +231,8 @@ export const Table = Node.create({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.editor.chain().addRowAfter().goToNextCell().run();
|
return this.editor.chain().addRowAfter().goToNextCell().run();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
"Shift-Tab": () => this.editor.commands.goToPreviousCell(),
|
"Shift-Tab": () => this.editor.commands.goToPreviousCell(),
|
||||||
Backspace: deleteTableWhenAllCellsSelected,
|
Backspace: deleteTableWhenAllCellsSelected,
|
||||||
|
@ -15,7 +15,6 @@ export function CoreEditorProps(editorClassName: string): EditorProps {
|
|||||||
if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
|
if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
|
||||||
const slashCommand = document.querySelector("#slash-command");
|
const slashCommand = document.querySelector("#slash-command");
|
||||||
if (slashCommand) {
|
if (slashCommand) {
|
||||||
console.log("registered");
|
|
||||||
return true;
|
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 {
|
function createDragHandleElement(): HTMLElement {
|
||||||
const dragHandleElement = document.createElement("div");
|
const dragHandleElement = document.createElement("div");
|
||||||
dragHandleElement.draggable = true;
|
dragHandleElement.draggable = true;
|
||||||
@ -49,23 +64,31 @@ function absoluteRect(node: Element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nodeDOMAtCoords(coords: { x: number; y: number }) {
|
function nodeDOMAtCoords(coords: { x: number; y: number }) {
|
||||||
return document
|
const elements = document.elementsFromPoint(coords.x, coords.y);
|
||||||
.elementsFromPoint(coords.x, coords.y)
|
const generalSelectors = [
|
||||||
.find(
|
|
||||||
(elem: Element) =>
|
|
||||||
elem.parentElement?.matches?.(".ProseMirror") ||
|
|
||||||
elem.matches(
|
|
||||||
[
|
|
||||||
"li",
|
"li",
|
||||||
"p:not(:first-child)",
|
"p:not(:first-child)",
|
||||||
".code-block",
|
".code-block",
|
||||||
"blockquote",
|
"blockquote",
|
||||||
"h1, h2, h3",
|
"h1, h2, h3",
|
||||||
"table",
|
".table-wrapper",
|
||||||
"[data-type=horizontalRule]",
|
"[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) {
|
function nodePosAtDOM(node: Element, view: EditorView, options: DragHandleOptions) {
|
||||||
@ -86,15 +109,19 @@ function nodePosAtDOMForBlockquotes(node: Element, view: EditorView) {
|
|||||||
})?.inside;
|
})?.inside;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcNodePos(pos: number, view: EditorView) {
|
function calcNodePos(pos: number, view: EditorView, node: Element) {
|
||||||
const maxPos = view.state.doc.content.size;
|
const maxPos = view.state.doc.content.size;
|
||||||
const safePos = Math.max(0, Math.min(pos, maxPos));
|
const safePos = Math.max(0, Math.min(pos, maxPos));
|
||||||
const $pos = view.state.doc.resolve(safePos);
|
const $pos = view.state.doc.resolve(safePos);
|
||||||
|
|
||||||
if ($pos.depth > 1) {
|
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);
|
const newPos = $pos.before($pos.depth);
|
||||||
return Math.max(0, Math.min(newPos, maxPos));
|
return Math.max(0, Math.min(newPos, maxPos));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return safePos;
|
return safePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,12 +141,12 @@ function DragHandle(options: DragHandleOptions) {
|
|||||||
|
|
||||||
let draggedNodePos = nodePosAtDOM(node, view, options);
|
let draggedNodePos = nodePosAtDOM(node, view, options);
|
||||||
if (draggedNodePos == null || draggedNodePos < 0) return;
|
if (draggedNodePos == null || draggedNodePos < 0) return;
|
||||||
draggedNodePos = calcNodePos(draggedNodePos, view);
|
draggedNodePos = calcNodePos(draggedNodePos, view, node);
|
||||||
|
|
||||||
const { from, to } = view.state.selection;
|
const { from, to } = view.state.selection;
|
||||||
const diff = from - to;
|
const diff = from - to;
|
||||||
|
|
||||||
const fromSelectionPos = calcNodePos(from, view);
|
const fromSelectionPos = calcNodePos(from, view, node);
|
||||||
let differentNodeSelected = false;
|
let differentNodeSelected = false;
|
||||||
|
|
||||||
const nodePos = view.state.doc.resolve(fromSelectionPos);
|
const nodePos = view.state.doc.resolve(fromSelectionPos);
|
||||||
@ -148,6 +175,19 @@ function DragHandle(options: DragHandleOptions) {
|
|||||||
listType = node.parentElement!.tagName;
|
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 slice = view.state.selection.content();
|
||||||
const { dom, text } = __serializeForClipboard(view, slice);
|
const { dom, text } = __serializeForClipboard(view, slice);
|
||||||
|
|
||||||
@ -190,7 +230,7 @@ function DragHandle(options: DragHandleOptions) {
|
|||||||
if (nodePos === null || nodePos === undefined) return;
|
if (nodePos === null || nodePos === undefined) return;
|
||||||
|
|
||||||
// Adjust the nodePos to point to the start of the node, ensuring NodeSelection can be applied
|
// 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
|
// Use NodeSelection to select the node at the calculated position
|
||||||
const nodeSelection = NodeSelection.create(view.state.doc, nodePos);
|
const nodeSelection = NodeSelection.create(view.state.doc, nodePos);
|
||||||
@ -279,9 +319,11 @@ function DragHandle(options: DragHandleOptions) {
|
|||||||
|
|
||||||
// Li markers
|
// Li markers
|
||||||
if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
|
if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
|
||||||
rect.top += 4;
|
|
||||||
rect.left -= 18;
|
rect.left -= 18;
|
||||||
}
|
}
|
||||||
|
if (node.matches(".table-wrapper")) {
|
||||||
|
rect.top += 8;
|
||||||
|
}
|
||||||
|
|
||||||
rect.width = options.dragHandleWidth;
|
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