Merge branch 'fix/drag-handles' into chore/page-transactions

This commit is contained in:
Palanikannan1437 2024-03-28 12:15:29 +05:30
commit c5814acb09
4 changed files with 60 additions and 55 deletions

View File

@ -1,9 +1,13 @@
import { Extension } from "@tiptap/core"; import { Extension } from "@tiptap/core";
import { PluginKey, NodeSelection, Plugin } from "@tiptap/pm/state"; import { NodeSelection, Plugin, PluginKey } from "@tiptap/pm/state";
// @ts-ignore // @ts-expect-error __serializeForClipboard's is not exported
import { __serializeForClipboard, EditorView } from "@tiptap/pm/view"; import { __serializeForClipboard, EditorView } from "@tiptap/pm/view";
import React from "react";
export interface DragHandleOptions {
dragHandleWidth: number;
setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void;
}
function createDragHandleElement(): HTMLElement { function createDragHandleElement(): HTMLElement {
const dragHandleElement = document.createElement("div"); const dragHandleElement = document.createElement("div");
@ -29,13 +33,8 @@ function createDragHandleElement(): HTMLElement {
return dragHandleElement; return dragHandleElement;
} }
export interface DragHandleOptions {
dragHandleWidth: number;
setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void;
}
function absoluteRect(node: Element) { function absoluteRect(node: Element) {
const data = node?.getBoundingClientRect(); const data = node.getBoundingClientRect();
return { return {
top: data.top, top: data.top,
@ -51,40 +50,18 @@ function nodeDOMAtCoords(coords: { x: number; y: number }) {
(elem: Element) => (elem: Element) =>
elem.parentElement?.matches?.(".ProseMirror") || elem.parentElement?.matches?.(".ProseMirror") ||
elem.matches( elem.matches(
[ ["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3", "table", "[data-type=horizontalRule]"].join(
"li", ", "
"p:not(:first-child)", )
"pre",
"blockquote",
"h1, h2, h3",
"[data-type=horizontalRule]",
".tableWrapper",
].join(", ")
) )
); );
} }
function nodePosAtDOM(node: Element, view: EditorView) { function nodePosAtDOM(node: Element, view: EditorView, options: DragHandleOptions) {
const boundingRect = node?.getBoundingClientRect(); const boundingRect = node.getBoundingClientRect();
if (node.nodeName === "IMG") {
return view.posAtCoords({
left: boundingRect.left + 1,
top: boundingRect.top + 1,
})?.pos;
}
if (node.nodeName === "PRE") {
return (
view.posAtCoords({
left: boundingRect.left + 1,
top: boundingRect.top + 1,
})?.pos! - 1
);
}
return view.posAtCoords({ return view.posAtCoords({
left: boundingRect.left + 1, left: boundingRect.left + 50 + options.dragHandleWidth,
top: boundingRect.top + 1, top: boundingRect.top + 1,
})?.inside; })?.inside;
} }
@ -96,14 +73,14 @@ function DragHandle(options: DragHandleOptions) {
if (!event.dataTransfer) return; if (!event.dataTransfer) return;
const node = nodeDOMAtCoords({ const node = nodeDOMAtCoords({
x: event.clientX + options.dragHandleWidth + 50, x: event.clientX + 50 + options.dragHandleWidth,
y: event.clientY, y: event.clientY,
}); });
if (!(node instanceof Element)) return; if (!(node instanceof Element)) return;
const nodePos = nodePosAtDOM(node, view); const nodePos = nodePosAtDOM(node, view, options);
if (nodePos === null || nodePos === undefined || nodePos < 0) return; if (nodePos == null || nodePos < 0) return;
view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos))); view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));
@ -132,9 +109,8 @@ function DragHandle(options: DragHandleOptions) {
if (!(node instanceof Element)) return; if (!(node instanceof Element)) return;
const nodePos = nodePosAtDOM(node, view); const nodePos = nodePosAtDOM(node, view, options);
if (!nodePos) return;
if (nodePos === null || nodePos === undefined || nodePos < 0) return;
view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos))); view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));
} }
@ -192,11 +168,11 @@ function DragHandle(options: DragHandleOptions) {
} }
const node = nodeDOMAtCoords({ const node = nodeDOMAtCoords({
x: event.clientX + options.dragHandleWidth, x: event.clientX + 50 + options.dragHandleWidth,
y: event.clientY, y: event.clientY,
}); });
if (!(node instanceof Element)) { if (!(node instanceof Element) || node.matches("ul, ol")) {
hideDragHandle(); hideDragHandle();
return; return;
} }
@ -207,7 +183,7 @@ function DragHandle(options: DragHandleOptions) {
const rect = absoluteRect(node); const rect = absoluteRect(node);
rect.top += (lineHeight - 24) / 2; rect.top += (lineHeight - 20) / 2;
rect.top += paddingTop; rect.top += paddingTop;
// 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")) {
@ -218,21 +194,22 @@ function DragHandle(options: DragHandleOptions) {
if (!dragHandleElement) return; if (!dragHandleElement) return;
dragHandleElement.style.left = `${rect.left - rect.width}px`; dragHandleElement.style.left = `${rect.left - rect.width}px`;
dragHandleElement.style.top = `${rect.top + 3}px`; dragHandleElement.style.top = `${rect.top}px`;
showDragHandle(); showDragHandle();
}, },
keydown: () => { keydown: () => {
hideDragHandle(); hideDragHandle();
}, },
wheel: () => { mousewheel: () => {
hideDragHandle(); hideDragHandle();
}, },
// dragging className is used for CSS dragenter: (view) => {
dragstart: (view) => {
view.dom.classList.add("dragging"); view.dom.classList.add("dragging");
hideDragHandle();
}, },
drop: (view) => { drop: (view) => {
view.dom.classList.remove("dragging"); view.dom.classList.remove("dragging");
hideDragHandle();
}, },
dragend: (view) => { dragend: (view) => {
view.dom.classList.remove("dragging"); view.dom.classList.remove("dragging");

View File

@ -54,7 +54,20 @@ const Command = Extension.create<SlashCommandOptions>({
props.command({ editor, range }); props.command({ editor, range });
}, },
allow({ editor }: { editor: Editor }) { allow({ editor }: { editor: Editor }) {
return !editor.isActive("table"); const { selection } = editor.state;
const parentNode = selection.$from.node(selection.$from.depth);
const blockType = parentNode.type.name;
if (blockType === "codeBlock") {
return false;
}
if (editor.isActive("table")) {
return false;
}
return true;
}, },
allowSpaces: true, allowSpaces: true,
}, },

View File

@ -2,7 +2,7 @@
position: fixed; position: fixed;
opacity: 1; opacity: 1;
transition: opacity ease-in 0.2s; transition: opacity ease-in 0.2s;
height: 18px; height: 20px;
width: 15px; width: 15px;
display: grid; display: grid;
place-items: center; place-items: center;
@ -12,9 +12,24 @@
background-color: rgb(var(--color-background-90)); background-color: rgb(var(--color-background-90));
} }
.drag-handle:hover { .ProseMirror:not(.dragging) .ProseMirror-selectednode {
background-color: rgb(var(--color-background-80)); outline: none !important;
cursor: grab;
background-color: #1f2937;
transition: background-color 0.2s; transition: background-color 0.2s;
box-shadow: none;
}
.drag-handle:hover {
background-color: #4d4d4d;
cursor: grab;
transition: background-color 0.2s;
}
.drag-handle:active {
background-color: #4d4d4d;
transition: background-color 0.2s;
cursor: grabbing;
} }
.drag-handle.hidden { .drag-handle.hidden {

View File

@ -2733,7 +2733,7 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react@*", "@types/react@^18.2.42": "@types/react@*", "@types/react@18.2.42", "@types/react@^18.2.42":
version "18.2.42" version "18.2.42"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.42.tgz#6f6b11a904f6d96dda3c2920328a97011a00aba7" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.42.tgz#6f6b11a904f6d96dda3c2920328a97011a00aba7"
integrity sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA== integrity sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA==