Regarding the bug in deleting text caused by customizable drag and drop paragraphs through NodeView

I have customized drag and drop paragraphs through NodeView, but there is a bug. If there are two paragraphs, the mouse selects from the end of the last paragraph of text to any position in the previous paragraph of text, presses Ctrl+X, or deletes it, it will fail. But selecting from the previous paragraph to the next paragraph will not be a problem

I haven’t managed to reproduce this. Could you try to show the minimal code that sets up an editor that has this problem? And does it happen on all browsers or just some?

Okay, I need some time to organize the minimum code

I found that this issue only occurs when using the addNodeView of tiptab, and it does not occur when using the prosemirror native interface. But if I use prosemirror for implementation, I also need to implement additional functions for cursor movement and selection. For example, selecting multiple paragraphs, moving the cursor between paragraphs through the keyboard, and selecting multiple paragraphs through shift+arrow keys. I suspect that Tibtab implements the cursor function mentioned above, so I tried to read the code of Tibtab to find out what the problem was, but due to my limited skills, I couldn’t find its handling of the cursor and selection. Here is my drag and drop paragraph based on tiptab:


  <div class="height-full" style="padding: 20px 200px;">
    <editor-content class="height-full" :editor="editor"></editor-content>

<script setup lang="ts">
import {useEditor, EditorContent} from '@tiptap/vue-3';
import {Document} from '@tiptap/extension-document';
import {Text} from '@tiptap/extension-text';
import {Dropcursor} from '@tiptap/extension-dropcursor';
import {DraggableParagraph} from './draggableParagraph';

const editor = window.CONFIG.editor = useEditor({
  extensions: [
  content: '<p>This is a first paragraph.</p>' +
      '<p>New paragraph.</p>'


import {VueNodeViewRenderer} from '@tiptap/vue-3';
import {Paragraph} from '@tiptap/extension-paragraph';
import Component from './index.vue';

export const DraggableParagraph = Paragraph.extend({
  draggable: true,
  addNodeView() {
// I went to see the source code from here, but I didn't get any results
    return VueNodeViewRenderer(Component);


  <node-view-wrapper style="display: flex;">
    <div contenteditable="false" data-drag-handle style="width: 20px;height: 20px;border: 1px solid #000;">
    <node-view-content class="drag-content"></node-view-content>

<script setup lang="ts">
import {NodeViewContent, nodeViewProps, NodeViewWrapper} from '@tiptap/vue-3';

const props = defineProps(nodeViewProps);

I found out where the problem lies. Tiptab has a NodeView.ts file that implements the stopEvent method.

stopEvent(event: Event) {
    if (!this.dom) {
      return false

    if (typeof this.options.stopEvent === 'function') {
      return this.options.stopEvent({ event })

    const target = as HTMLElement
    const isInElement = this.dom.contains(target) && !this.contentDOM?.contains(target)

    // any event from child nodes should be handled by ProseMirror
    if (!isInElement) {
      return false

    const isDragEvent = event.type.startsWith('drag')
    const isDropEvent = event.type === 'drop'
    const isInput = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA'].includes(target.tagName) || target.isContentEditable

    // any input event within node views should be ignored by ProseMirror
    if (isInput && !isDropEvent && !isDragEvent) {
      return true

    const { isEditable } = this.editor
    const { isDragging } = this
    const isDraggable = !!this.node.type.spec.draggable
    const isSelectable = NodeSelection.isSelectable(this.node)
    const isCopyEvent = event.type === 'copy'
    const isPasteEvent = event.type === 'paste'
    const isCutEvent = event.type === 'cut'
    const isClickEvent = event.type === 'mousedown'

    // ProseMirror tries to drag selectable nodes
    // even if `draggable` is set to `false`
    // this fix prevents that
    if (!isDraggable && isSelectable && isDragEvent) {

    if (isDraggable && isDragEvent && !isDragging) {
      return false
//Omitted below...

The problem lies in

if (isDraggable && isDragEvent && !isDragging) {
      return false

The event is blocked here. This avoids triggering drag and drop behavior when the cursor is at the end of the text. But it seems to have also led to the problem of selecting multiple paragraphs and deleting them from the end.

May I ask if there is any way to solve this problem? Can I not use event. preventDefault. But rather to determine whether the current cursor position is at the end, and if it is at the end, make the paragraph non draggable

If Tiptap is doing something problematic, you’d want to report that on their bug tracker. This forum isn’t really Tiptap-related.

Oh, thank you. I understand.