diff --git a/packages/editor/core/src/lib/editor-commands.ts b/packages/editor/core/src/lib/editor-commands.ts index ce2cf3ad6..b82b1f354 100644 --- a/packages/editor/core/src/lib/editor-commands.ts +++ b/packages/editor/core/src/lib/editor-commands.ts @@ -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; } diff --git a/packages/editor/core/src/ui/extensions/table/table/table.ts b/packages/editor/core/src/ui/extensions/table/table/table.ts index 5fd06caf6..c1f65feec 100644 --- a/packages/editor/core/src/ui/extensions/table/table/table.ts +++ b/packages/editor/core/src/ui/extensions/table/table/table.ts @@ -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, diff --git a/packages/editor/core/src/ui/props.tsx b/packages/editor/core/src/ui/props.tsx index 3d46b5840..32d1510c7 100644 --- a/packages/editor/core/src/ui/props.tsx +++ b/packages/editor/core/src/ui/props.tsx @@ -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; } } diff --git a/packages/editor/extensions/src/extensions/drag-drop.tsx b/packages/editor/extensions/src/extensions/drag-drop.tsx index ab2df31ad..32867a5f1 100644 --- a/packages/editor/extensions/src/extensions/drag-drop.tsx +++ b/packages/editor/extensions/src/extensions/drag-drop.tsx @@ -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
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, - }), - ]; - }, - });