diff --git a/docs/src/demos/Guide/NodeViews/VueComponent/Component.vue b/docs/src/demos/Guide/NodeViews/VueComponent/Component.vue new file mode 100644 index 00000000..391fd8d4 --- /dev/null +++ b/docs/src/demos/Guide/NodeViews/VueComponent/Component.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/docs/src/demos/Guide/NodeViews/VueComponent/index.js b/docs/src/demos/Guide/NodeViews/VueComponent/index.js new file mode 100644 index 00000000..6dac246e --- /dev/null +++ b/docs/src/demos/Guide/NodeViews/VueComponent/index.js @@ -0,0 +1,35 @@ +import { Node, mergeAttributes } from '@tiptap/core' +import { VueNodeViewRenderer } from '@tiptap/vue-2' +import Component from './Component.vue' + +export default Node.create({ + name: 'vueComponent', + + group: 'block', + + atom: true, + + addAttributes() { + return { + count: { + default: 0, + }, + } + }, + + parseHTML() { + return [ + { + tag: 'vue-component', + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['vue-component', mergeAttributes(HTMLAttributes)] + }, + + addNodeView() { + return VueNodeViewRenderer(Component) + }, +}) diff --git a/docs/src/demos/Guide/NodeViews/VueComponent/index.vue b/docs/src/demos/Guide/NodeViews/VueComponent/index.vue new file mode 100644 index 00000000..2fcafcd9 --- /dev/null +++ b/docs/src/demos/Guide/NodeViews/VueComponent/index.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/docs/src/demos/Guide/NodeViews/VueComponentContent/Component.vue b/docs/src/demos/Guide/NodeViews/VueComponentContent/Component.vue new file mode 100644 index 00000000..14d3e302 --- /dev/null +++ b/docs/src/demos/Guide/NodeViews/VueComponentContent/Component.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/docs/src/demos/Guide/NodeViews/VueComponentContent/index.js b/docs/src/demos/Guide/NodeViews/VueComponentContent/index.js new file mode 100644 index 00000000..4db1c458 --- /dev/null +++ b/docs/src/demos/Guide/NodeViews/VueComponentContent/index.js @@ -0,0 +1,35 @@ +import { Node, mergeAttributes } from '@tiptap/core' +import { VueNodeViewRenderer } from '@tiptap/vue-2' +import Component from './Component.vue' + +export default Node.create({ + name: 'vueComponent', + + group: 'block', + + content: 'inline*', + + addAttributes() { + return { + count: { + default: 0, + }, + } + }, + + parseHTML() { + return [ + { + tag: 'vue-component', + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['vue-component', mergeAttributes(HTMLAttributes)] + }, + + addNodeView() { + return VueNodeViewRenderer(Component) + }, +}) diff --git a/docs/src/demos/Guide/NodeViews/VueComponentContent/index.vue b/docs/src/demos/Guide/NodeViews/VueComponentContent/index.vue new file mode 100644 index 00000000..c8d2e072 --- /dev/null +++ b/docs/src/demos/Guide/NodeViews/VueComponentContent/index.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/docs/src/docPages/guide/node-views.md b/docs/src/docPages/guide/node-views.md index 076bce4e..a71a4be7 100644 --- a/docs/src/docPages/guide/node-views.md +++ b/docs/src/docPages/guide/node-views.md @@ -1,34 +1,14 @@ -# Complex node views +# Interactive node views ## toc ## Introduction -Node views are the best thing since sliced bread, at least if you’re a fan of customization (and bread). Node views enable you to add literally anything to a node. If you can write it in JavaScript, you can use it in your editor. - - +Node views are the best thing since sliced bread, at least if you are a fan of customization (and bread). With node views you can add interactive nodes to your editor content. That can literally be everything. If you can write it in JavaScript, you can use it in your editor. ## Different types of node views +TODO -### Simple - +### Editable content ```html

text

@@ -37,12 +17,7 @@ export default Node.create({
``` -#### Example: Task item - -https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-task-item/src/task-item.ts#L74 - -### Without content - +### Non-editable content ```html

text

@@ -51,14 +26,7 @@ https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-task-item
``` -#### Example: Table of contents - - -#### Example: Drawing in the editor - - -### Advanced node views with content - +### Mixed content ```html

text

@@ -74,12 +42,8 @@ https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-task-item
``` -#### Example: Drag handles - - -## Render Vue components - -### Node +## Node views with JavaScript +TODO ```js import { Node } from '@tiptap/core' @@ -87,13 +51,119 @@ import { VueNodeViewRenderer } from '@tiptap/vue-2' import Component from './Component.vue' export default Node.create({ + addNodeView() { + return ({ editor, node, getPos, HTMLAttributes, decorations, extension }) => { + const dom = document.createElement('div') + + dom.innerHTML = 'Hello, I’m a node view!' + + return { + dom, + } + }) + }, +}) +``` + +## Node views with Vue +Using Vanilla JavaScript can feel complex, if you are used to work in Vue. Good news: You can even use regular Vue components in your node views. There is just a little bit you need to know, but let’s go through this one by one. + +### Render a Vue component +Here is what you need to do to render Vue components inside your text editor: + +1. [Create a node extension](/guide/build-extensions) +2. Create a Vue component +3. Pass that component to the provided `VueNodeViewRenderer` +4. Register it with `addNodeView()` +5. [Configure tiptap to use your new node](/guide/configuration) + +This is how your node could look like: + +```js +import { Node } from '@tiptap/core' +import { VueNodeViewRenderer } from '@tiptap/vue-2' +import Component from './Component.vue' + +export default Node.create({ + // configuration … + addNodeView() { return VueNodeViewRenderer(Component) }, }) ``` -### Component +There is a little bit of magic required to make this work. But don’t worry, we provide a Vue component you can use to get started easily. Don’t forget to add it to your custom Vue component, like shown below: + +```html + +``` + +Got it? Let’s see that in action. Feel free to copy the example to get started. + + + +### Access node attributes + +```js +props: { + node: { + type: Object, + required: true, + }, +}, +``` + +```js +this.node.attrs.count +``` + +### Update node attributes + +```js +props: { + updateAttributes: { + type: Function, + required: true, + }, +}, +``` + +```js +this.updateAttributes({ + count: this.node.attrs.count + 1, +}) +``` + +### Adding a content editable + +```html + + + ``` -### Component with Content +## Node views with React +TODO -```html - +## Rendered content -