diff --git a/docs/src/components/Demo/index.vue b/docs/src/components/Demo/index.vue
index b1c888c5..ce7aaf05 100644
--- a/docs/src/components/Demo/index.vue
+++ b/docs/src/components/Demo/index.vue
@@ -120,7 +120,7 @@ export default {
}
})
.filter(item => {
- return ['vue', 'jsx', 'scss'].includes(item.extension)
+ return ['vue', 'ts', 'jsx', 'scss'].includes(item.extension)
})
.sortBy(item => item.path.split('/').length && !item.path.endsWith('index.vue'))
.toArray()
diff --git a/docs/src/demos/Examples/NodeView/Component.vue b/docs/src/demos/Examples/NodeView/Component.vue
new file mode 100644
index 00000000..0d99908c
--- /dev/null
+++ b/docs/src/demos/Examples/NodeView/Component.vue
@@ -0,0 +1,15 @@
+
+
+ node view
+
+
+
+
+
+
diff --git a/docs/src/demos/Examples/NodeView/Test.ts b/docs/src/demos/Examples/NodeView/Test.ts
new file mode 100644
index 00000000..13fae1f8
--- /dev/null
+++ b/docs/src/demos/Examples/NodeView/Test.ts
@@ -0,0 +1,29 @@
+import { Node } from '@tiptap/core'
+import { VueRenderer } from '@tiptap/vue'
+import Component from './Component.vue'
+
+export default Node.create({
+ name: 'test',
+
+ group: 'block',
+
+ draggable: true,
+
+ selectable: false,
+
+ parseHTML() {
+ return [
+ {
+ tag: 'div[data-type="test"]',
+ },
+ ]
+ },
+
+ renderHTML() {
+ return ['div', { 'data-type': 'test' }]
+ },
+
+ addNodeView() {
+ return VueRenderer(Component)
+ },
+})
diff --git a/docs/src/demos/Examples/NodeView/index.vue b/docs/src/demos/Examples/NodeView/index.vue
new file mode 100644
index 00000000..9103e856
--- /dev/null
+++ b/docs/src/demos/Examples/NodeView/index.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/docPages/examples/node-view.md b/docs/src/docPages/examples/node-view.md
new file mode 100644
index 00000000..1040abeb
--- /dev/null
+++ b/docs/src/docPages/examples/node-view.md
@@ -0,0 +1,3 @@
+# Node View
+
+
diff --git a/packages/core/src/ExtensionManager.ts b/packages/core/src/ExtensionManager.ts
index eb10635a..eccb2b37 100644
--- a/packages/core/src/ExtensionManager.ts
+++ b/packages/core/src/ExtensionManager.ts
@@ -130,6 +130,7 @@ export default class ExtensionManager {
getPos,
decorations,
HTMLAttributes,
+ extension,
})
}
diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts
index d2a8727a..a8ed6fee 100644
--- a/packages/core/src/types.ts
+++ b/packages/core/src/types.ts
@@ -90,6 +90,7 @@ export type NodeViewRendererProps = {
getPos: (() => number) | boolean,
decorations: Decoration[],
HTMLAttributes: { [key: string]: any },
+ extension: Node,
}
export type NodeViewRenderer = (props: NodeViewRendererProps) => NodeView
diff --git a/packages/vue/src/VueRenderer.ts b/packages/vue/src/VueRenderer.ts
index 60ba426c..e4e489ce 100644
--- a/packages/vue/src/VueRenderer.ts
+++ b/packages/vue/src/VueRenderer.ts
@@ -1,5 +1,9 @@
-import { NodeViewRendererProps } from '@tiptap/core'
+import { Node, NodeViewRendererProps } from '@tiptap/core'
import { NodeView } from 'prosemirror-view'
+
+import {
+ Node as ProseMirrorNode,
+} from 'prosemirror-model'
import Vue from 'vue'
import { VueConstructor } from 'vue/types/umd'
@@ -7,12 +11,19 @@ class VueNodeView implements NodeView {
vm!: Vue
+ extension!: Node
+
+ node!: ProseMirrorNode
+
constructor(component: Vue | VueConstructor, props: NodeViewRendererProps) {
// eslint-disable-next-line
const { node, editor, getPos } = props
// eslint-disable-next-line
const { view } = editor
+ this.extension = props.extension
+ this.node = props.node
+
this.mount(component)
}
@@ -33,7 +44,17 @@ class VueNodeView implements NodeView {
return this.vm.$refs.content as Element
}
- stopEvent() {
+ stopEvent(event: Event): boolean {
+ const isDraggable = this.node.type.spec.draggable
+ const isCopy = event.type === 'copy'
+ const isPaste = event.type === 'paste'
+ const isCut = event.type === 'cut'
+ const isDrag = event.type.startsWith('drag') || event.type === 'drop'
+
+ if ((isDraggable && isDrag) || isCopy || isPaste || isCut) {
+ return false
+ }
+
return true
}