@tiptap/vue-3 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +5 -1
- package/dist/index.cjs +577 -455
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +228 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.js +541 -443
- package/dist/index.js.map +1 -1
- package/dist/menus/index.cjs +693 -0
- package/dist/menus/index.cjs.map +1 -0
- package/dist/menus/index.d.cts +279 -0
- package/dist/menus/index.d.ts +279 -0
- package/dist/menus/index.js +685 -0
- package/dist/menus/index.js.map +1 -0
- package/package.json +28 -17
- package/src/Editor.ts +23 -17
- package/src/EditorContent.ts +14 -44
- package/src/VueMarkViewRenderer.ts +130 -0
- package/src/VueNodeViewRenderer.ts +99 -36
- package/src/VueRenderer.ts +27 -18
- package/src/index.ts +1 -2
- package/src/menus/BubbleMenu.ts +78 -0
- package/src/menus/FloatingMenu.ts +68 -0
- package/src/menus/index.ts +2 -0
- package/src/useEditor.ts +7 -1
- package/dist/index.umd.js +0 -495
- package/dist/index.umd.js.map +0 -1
- package/dist/packages/core/src/CommandManager.d.ts +0 -20
- package/dist/packages/core/src/Editor.d.ts +0 -161
- package/dist/packages/core/src/EventEmitter.d.ts +0 -11
- package/dist/packages/core/src/Extension.d.ts +0 -343
- package/dist/packages/core/src/ExtensionManager.d.ts +0 -55
- package/dist/packages/core/src/InputRule.d.ts +0 -42
- package/dist/packages/core/src/Mark.d.ts +0 -451
- package/dist/packages/core/src/Node.d.ts +0 -611
- package/dist/packages/core/src/NodePos.d.ts +0 -44
- package/dist/packages/core/src/NodeView.d.ts +0 -31
- package/dist/packages/core/src/PasteRule.d.ts +0 -50
- package/dist/packages/core/src/Tracker.d.ts +0 -11
- package/dist/packages/core/src/commands/blur.d.ts +0 -13
- package/dist/packages/core/src/commands/clearContent.d.ts +0 -14
- package/dist/packages/core/src/commands/clearNodes.d.ts +0 -13
- package/dist/packages/core/src/commands/command.d.ts +0 -18
- package/dist/packages/core/src/commands/createParagraphNear.d.ts +0 -13
- package/dist/packages/core/src/commands/cut.d.ts +0 -20
- package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +0 -13
- package/dist/packages/core/src/commands/deleteNode.d.ts +0 -15
- package/dist/packages/core/src/commands/deleteRange.d.ts +0 -14
- package/dist/packages/core/src/commands/deleteSelection.d.ts +0 -13
- package/dist/packages/core/src/commands/enter.d.ts +0 -13
- package/dist/packages/core/src/commands/exitCode.d.ts +0 -13
- package/dist/packages/core/src/commands/extendMarkRange.d.ts +0 -25
- package/dist/packages/core/src/commands/first.d.ts +0 -14
- package/dist/packages/core/src/commands/focus.d.ts +0 -27
- package/dist/packages/core/src/commands/forEach.d.ts +0 -14
- package/dist/packages/core/src/commands/index.d.ts +0 -55
- package/dist/packages/core/src/commands/insertContent.d.ts +0 -34
- package/dist/packages/core/src/commands/insertContentAt.d.ts +0 -47
- package/dist/packages/core/src/commands/join.d.ts +0 -41
- package/dist/packages/core/src/commands/joinItemBackward.d.ts +0 -13
- package/dist/packages/core/src/commands/joinItemForward.d.ts +0 -13
- package/dist/packages/core/src/commands/joinTextblockBackward.d.ts +0 -12
- package/dist/packages/core/src/commands/joinTextblockForward.d.ts +0 -12
- package/dist/packages/core/src/commands/keyboardShortcut.d.ts +0 -14
- package/dist/packages/core/src/commands/lift.d.ts +0 -17
- package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +0 -13
- package/dist/packages/core/src/commands/liftListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/newlineInCode.d.ts +0 -13
- package/dist/packages/core/src/commands/resetAttributes.d.ts +0 -16
- package/dist/packages/core/src/commands/scrollIntoView.d.ts +0 -13
- package/dist/packages/core/src/commands/selectAll.d.ts +0 -13
- package/dist/packages/core/src/commands/selectNodeBackward.d.ts +0 -13
- package/dist/packages/core/src/commands/selectNodeForward.d.ts +0 -13
- package/dist/packages/core/src/commands/selectParentNode.d.ts +0 -13
- package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +0 -13
- package/dist/packages/core/src/commands/selectTextblockStart.d.ts +0 -13
- package/dist/packages/core/src/commands/setContent.d.ts +0 -40
- package/dist/packages/core/src/commands/setMark.d.ts +0 -15
- package/dist/packages/core/src/commands/setMeta.d.ts +0 -15
- package/dist/packages/core/src/commands/setNode.d.ts +0 -16
- package/dist/packages/core/src/commands/setNodeSelection.d.ts +0 -14
- package/dist/packages/core/src/commands/setTextSelection.d.ts +0 -14
- package/dist/packages/core/src/commands/sinkListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/splitBlock.d.ts +0 -17
- package/dist/packages/core/src/commands/splitListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/toggleList.d.ts +0 -18
- package/dist/packages/core/src/commands/toggleMark.d.ts +0 -30
- package/dist/packages/core/src/commands/toggleNode.d.ts +0 -17
- package/dist/packages/core/src/commands/toggleWrap.d.ts +0 -16
- package/dist/packages/core/src/commands/undoInputRule.d.ts +0 -13
- package/dist/packages/core/src/commands/unsetAllMarks.d.ts +0 -13
- package/dist/packages/core/src/commands/unsetMark.d.ts +0 -25
- package/dist/packages/core/src/commands/updateAttributes.d.ts +0 -24
- package/dist/packages/core/src/commands/wrapIn.d.ts +0 -16
- package/dist/packages/core/src/commands/wrapInList.d.ts +0 -16
- package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +0 -5
- package/dist/packages/core/src/extensions/commands.d.ts +0 -3
- package/dist/packages/core/src/extensions/editable.d.ts +0 -2
- package/dist/packages/core/src/extensions/focusEvents.d.ts +0 -2
- package/dist/packages/core/src/extensions/index.d.ts +0 -6
- package/dist/packages/core/src/extensions/keymap.d.ts +0 -2
- package/dist/packages/core/src/extensions/tabindex.d.ts +0 -2
- package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +0 -10
- package/dist/packages/core/src/helpers/createChainableState.d.ts +0 -10
- package/dist/packages/core/src/helpers/createDocument.d.ts +0 -12
- package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +0 -15
- package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +0 -7
- package/dist/packages/core/src/helpers/findChildren.d.ts +0 -9
- package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +0 -10
- package/dist/packages/core/src/helpers/findParentNode.d.ts +0 -16
- package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +0 -17
- package/dist/packages/core/src/helpers/generateHTML.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateJSON.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateText.d.ts +0 -12
- package/dist/packages/core/src/helpers/getAttributes.d.ts +0 -9
- package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +0 -6
- package/dist/packages/core/src/helpers/getChangedRanges.d.ts +0 -11
- package/dist/packages/core/src/helpers/getDebugJSON.d.ts +0 -8
- package/dist/packages/core/src/helpers/getExtensionField.d.ts +0 -9
- package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkRange.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarksBetween.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeAtPosition.d.ts +0 -11
- package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getSchema.d.ts +0 -4
- package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +0 -10
- package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +0 -8
- package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +0 -8
- package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +0 -9
- package/dist/packages/core/src/helpers/getText.d.ts +0 -15
- package/dist/packages/core/src/helpers/getTextBetween.d.ts +0 -14
- package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +0 -8
- package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +0 -8
- package/dist/packages/core/src/helpers/index.d.ts +0 -50
- package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +0 -9
- package/dist/packages/core/src/helpers/isActive.d.ts +0 -2
- package/dist/packages/core/src/helpers/isAtEndOfNode.d.ts +0 -2
- package/dist/packages/core/src/helpers/isAtStartOfNode.d.ts +0 -2
- package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +0 -2
- package/dist/packages/core/src/helpers/isList.d.ts +0 -2
- package/dist/packages/core/src/helpers/isMarkActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isNodeActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +0 -2
- package/dist/packages/core/src/helpers/isNodeSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/isTextSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/posToDOMRect.d.ts +0 -2
- package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +0 -4
- package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +0 -2
- package/dist/packages/core/src/helpers/splitExtensions.d.ts +0 -9
- package/dist/packages/core/src/index.d.ts +0 -24
- package/dist/packages/core/src/inputRules/index.d.ts +0 -5
- package/dist/packages/core/src/inputRules/markInputRule.d.ts +0 -13
- package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +0 -23
- package/dist/packages/core/src/inputRules/textInputRule.d.ts +0 -10
- package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +0 -15
- package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +0 -28
- package/dist/packages/core/src/pasteRules/index.d.ts +0 -3
- package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +0 -13
- package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +0 -13
- package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +0 -10
- package/dist/packages/core/src/style.d.ts +0 -1
- package/dist/packages/core/src/types.d.ts +0 -255
- package/dist/packages/core/src/utilities/callOrReturn.d.ts +0 -9
- package/dist/packages/core/src/utilities/createStyleTag.d.ts +0 -1
- package/dist/packages/core/src/utilities/deleteProps.d.ts +0 -6
- package/dist/packages/core/src/utilities/elementFromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +0 -1
- package/dist/packages/core/src/utilities/findDuplicates.d.ts +0 -1
- package/dist/packages/core/src/utilities/fromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/index.d.ts +0 -20
- package/dist/packages/core/src/utilities/isAndroid.d.ts +0 -1
- package/dist/packages/core/src/utilities/isEmptyObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isFunction.d.ts +0 -1
- package/dist/packages/core/src/utilities/isMacOS.d.ts +0 -1
- package/dist/packages/core/src/utilities/isNumber.d.ts +0 -1
- package/dist/packages/core/src/utilities/isPlainObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isRegExp.d.ts +0 -1
- package/dist/packages/core/src/utilities/isString.d.ts +0 -1
- package/dist/packages/core/src/utilities/isiOS.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeAttributes.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeDeep.d.ts +0 -1
- package/dist/packages/core/src/utilities/minMax.d.ts +0 -1
- package/dist/packages/core/src/utilities/objectIncludes.d.ts +0 -8
- package/dist/packages/core/src/utilities/removeDuplicates.d.ts +0 -8
- package/dist/packages/extension-bubble-menu/src/bubble-menu-plugin.d.ts +0 -76
- package/dist/packages/extension-bubble-menu/src/bubble-menu.d.ts +0 -15
- package/dist/packages/extension-bubble-menu/src/index.d.ts +0 -4
- package/dist/packages/extension-floating-menu/src/floating-menu-plugin.d.ts +0 -66
- package/dist/packages/extension-floating-menu/src/floating-menu.d.ts +0 -15
- package/dist/packages/extension-floating-menu/src/index.d.ts +0 -4
- package/dist/packages/vue-3/src/BubbleMenu.d.ts +0 -59
- package/dist/packages/vue-3/src/Editor.d.ts +0 -23
- package/dist/packages/vue-3/src/EditorContent.d.ts +0 -17
- package/dist/packages/vue-3/src/FloatingMenu.d.ts +0 -48
- package/dist/packages/vue-3/src/NodeViewContent.d.ts +0 -13
- package/dist/packages/vue-3/src/NodeViewWrapper.d.ts +0 -13
- package/dist/packages/vue-3/src/VueNodeViewRenderer.d.ts +0 -48
- package/dist/packages/vue-3/src/VueRenderer.d.ts +0 -36
- package/dist/packages/vue-3/src/index.d.ts +0 -10
- package/dist/packages/vue-3/src/useEditor.d.ts +0 -3
- package/src/BubbleMenu.ts +0 -71
- package/src/FloatingMenu.ts +0 -66
|
@@ -1,23 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import { Decoration, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'
|
|
11
|
-
import {
|
|
12
|
-
Component,
|
|
13
|
-
defineComponent,
|
|
14
|
-
PropType,
|
|
15
|
-
provide,
|
|
16
|
-
Ref,
|
|
17
|
-
ref,
|
|
18
|
-
} from 'vue'
|
|
19
|
-
|
|
20
|
-
import { Editor } from './Editor.js'
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
import type { DecorationWithType, NodeViewProps, NodeViewRenderer, NodeViewRendererOptions } from '@tiptap/core'
|
|
3
|
+
import { NodeView } from '@tiptap/core'
|
|
4
|
+
import type { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
|
5
|
+
import type { Decoration, DecorationSource, NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'
|
|
6
|
+
import type { Component, PropType, Ref } from 'vue'
|
|
7
|
+
import { defineComponent, provide, ref } from 'vue'
|
|
8
|
+
|
|
9
|
+
import type { Editor } from './Editor.js'
|
|
21
10
|
import { VueRenderer } from './VueRenderer.js'
|
|
22
11
|
|
|
23
12
|
export const nodeViewProps = {
|
|
@@ -53,15 +42,29 @@ export const nodeViewProps = {
|
|
|
53
42
|
type: Function as PropType<NodeViewProps['deleteNode']>,
|
|
54
43
|
required: true as const,
|
|
55
44
|
},
|
|
45
|
+
view: {
|
|
46
|
+
type: Object as PropType<NodeViewProps['view']>,
|
|
47
|
+
required: true as const,
|
|
48
|
+
},
|
|
49
|
+
innerDecorations: {
|
|
50
|
+
type: Object as PropType<NodeViewProps['innerDecorations']>,
|
|
51
|
+
required: true as const,
|
|
52
|
+
},
|
|
53
|
+
HTMLAttributes: {
|
|
54
|
+
type: Object as PropType<NodeViewProps['HTMLAttributes']>,
|
|
55
|
+
required: true as const,
|
|
56
|
+
},
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export interface VueNodeViewRendererOptions extends NodeViewRendererOptions {
|
|
59
60
|
update:
|
|
60
61
|
| ((props: {
|
|
61
62
|
oldNode: ProseMirrorNode
|
|
62
|
-
oldDecorations: Decoration[]
|
|
63
|
+
oldDecorations: readonly Decoration[]
|
|
64
|
+
oldInnerDecorations: DecorationSource
|
|
63
65
|
newNode: ProseMirrorNode
|
|
64
|
-
newDecorations: Decoration[]
|
|
66
|
+
newDecorations: readonly Decoration[]
|
|
67
|
+
innerDecorations: DecorationSource
|
|
65
68
|
updateProps: () => void
|
|
66
69
|
}) => boolean)
|
|
67
70
|
| null
|
|
@@ -73,16 +76,19 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
73
76
|
decorationClasses!: Ref<string>
|
|
74
77
|
|
|
75
78
|
mount() {
|
|
76
|
-
const props
|
|
79
|
+
const props = {
|
|
77
80
|
editor: this.editor,
|
|
78
81
|
node: this.node,
|
|
79
|
-
decorations: this.decorations,
|
|
82
|
+
decorations: this.decorations as DecorationWithType[],
|
|
83
|
+
innerDecorations: this.innerDecorations,
|
|
84
|
+
view: this.view,
|
|
80
85
|
selected: false,
|
|
81
86
|
extension: this.extension,
|
|
87
|
+
HTMLAttributes: this.HTMLAttributes,
|
|
82
88
|
getPos: () => this.getPos(),
|
|
83
89
|
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
84
90
|
deleteNode: () => this.deleteNode(),
|
|
85
|
-
}
|
|
91
|
+
} satisfies NodeViewProps
|
|
86
92
|
|
|
87
93
|
const onDragStart = this.onDragStart.bind(this)
|
|
88
94
|
|
|
@@ -117,12 +123,19 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
117
123
|
__file: this.component.__file,
|
|
118
124
|
})
|
|
119
125
|
|
|
126
|
+
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this)
|
|
127
|
+
this.editor.on('selectionUpdate', this.handleSelectionUpdate)
|
|
128
|
+
|
|
120
129
|
this.renderer = new VueRenderer(extendedComponent, {
|
|
121
130
|
editor: this.editor,
|
|
122
131
|
props,
|
|
123
132
|
})
|
|
124
133
|
}
|
|
125
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Return the DOM element.
|
|
137
|
+
* This is the element that will be used to display the node view.
|
|
138
|
+
*/
|
|
126
139
|
get dom() {
|
|
127
140
|
if (!this.renderer.element || !this.renderer.element.hasAttribute('data-node-view-wrapper')) {
|
|
128
141
|
throw Error('Please use the NodeViewWrapper component for your node view.')
|
|
@@ -131,18 +144,51 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
131
144
|
return this.renderer.element as HTMLElement
|
|
132
145
|
}
|
|
133
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Return the content DOM element.
|
|
149
|
+
* This is the element that will be used to display the rich-text content of the node.
|
|
150
|
+
*/
|
|
134
151
|
get contentDOM() {
|
|
135
152
|
if (this.node.isLeaf) {
|
|
136
153
|
return null
|
|
137
154
|
}
|
|
138
155
|
|
|
139
|
-
|
|
156
|
+
return this.dom.querySelector('[data-node-view-content]') as HTMLElement | null
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* On editor selection update, check if the node is selected.
|
|
161
|
+
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
162
|
+
*/
|
|
163
|
+
handleSelectionUpdate() {
|
|
164
|
+
const { from, to } = this.editor.state.selection
|
|
165
|
+
const pos = this.getPos()
|
|
166
|
+
|
|
167
|
+
if (typeof pos !== 'number') {
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
172
|
+
if (this.renderer.props.selected) {
|
|
173
|
+
return
|
|
174
|
+
}
|
|
140
175
|
|
|
141
|
-
|
|
176
|
+
this.selectNode()
|
|
177
|
+
} else {
|
|
178
|
+
if (!this.renderer.props.selected) {
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.deselectNode()
|
|
183
|
+
}
|
|
142
184
|
}
|
|
143
185
|
|
|
144
|
-
|
|
145
|
-
|
|
186
|
+
/**
|
|
187
|
+
* On update, update the React component.
|
|
188
|
+
* To prevent unnecessary updates, the `update` option can be used.
|
|
189
|
+
*/
|
|
190
|
+
update(node: ProseMirrorNode, decorations: readonly Decoration[], innerDecorations: DecorationSource): boolean {
|
|
191
|
+
const rerenderComponent = (props?: Record<string, any>) => {
|
|
146
192
|
this.decorationClasses.value = this.getDecorationClasses()
|
|
147
193
|
this.renderer.updateProps(props)
|
|
148
194
|
}
|
|
@@ -150,16 +196,20 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
150
196
|
if (typeof this.options.update === 'function') {
|
|
151
197
|
const oldNode = this.node
|
|
152
198
|
const oldDecorations = this.decorations
|
|
199
|
+
const oldInnerDecorations = this.innerDecorations
|
|
153
200
|
|
|
154
201
|
this.node = node
|
|
155
202
|
this.decorations = decorations
|
|
203
|
+
this.innerDecorations = innerDecorations
|
|
156
204
|
|
|
157
205
|
return this.options.update({
|
|
158
206
|
oldNode,
|
|
159
207
|
oldDecorations,
|
|
160
208
|
newNode: node,
|
|
161
209
|
newDecorations: decorations,
|
|
162
|
-
|
|
210
|
+
oldInnerDecorations,
|
|
211
|
+
innerDecorations,
|
|
212
|
+
updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),
|
|
163
213
|
})
|
|
164
214
|
}
|
|
165
215
|
|
|
@@ -167,18 +217,23 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
167
217
|
return false
|
|
168
218
|
}
|
|
169
219
|
|
|
170
|
-
if (node === this.node && this.decorations === decorations) {
|
|
220
|
+
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
171
221
|
return true
|
|
172
222
|
}
|
|
173
223
|
|
|
174
224
|
this.node = node
|
|
175
225
|
this.decorations = decorations
|
|
226
|
+
this.innerDecorations = innerDecorations
|
|
176
227
|
|
|
177
|
-
|
|
228
|
+
rerenderComponent({ node, decorations, innerDecorations })
|
|
178
229
|
|
|
179
230
|
return true
|
|
180
231
|
}
|
|
181
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Select the node.
|
|
235
|
+
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
236
|
+
*/
|
|
182
237
|
selectNode() {
|
|
183
238
|
this.renderer.updateProps({
|
|
184
239
|
selected: true,
|
|
@@ -188,6 +243,10 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
188
243
|
}
|
|
189
244
|
}
|
|
190
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Deselect the node.
|
|
248
|
+
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
249
|
+
*/
|
|
191
250
|
deselectNode() {
|
|
192
251
|
this.renderer.updateProps({
|
|
193
252
|
selected: false,
|
|
@@ -209,21 +268,25 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|
|
209
268
|
|
|
210
269
|
destroy() {
|
|
211
270
|
this.renderer.destroy()
|
|
271
|
+
this.editor.off('selectionUpdate', this.handleSelectionUpdate)
|
|
212
272
|
}
|
|
213
273
|
}
|
|
214
274
|
|
|
215
275
|
export function VueNodeViewRenderer(
|
|
216
|
-
component: Component
|
|
276
|
+
component: Component<NodeViewProps>,
|
|
217
277
|
options?: Partial<VueNodeViewRendererOptions>,
|
|
218
278
|
): NodeViewRenderer {
|
|
219
|
-
return
|
|
279
|
+
return props => {
|
|
220
280
|
// try to get the parent component
|
|
221
281
|
// this is important for vue devtools to show the component hierarchy correctly
|
|
222
282
|
// maybe it’s `undefined` because <editor-content> isn’t rendered yet
|
|
223
283
|
if (!(props.editor as Editor).contentComponent) {
|
|
224
|
-
return {}
|
|
284
|
+
return {} as unknown as ProseMirrorNodeView
|
|
225
285
|
}
|
|
286
|
+
// check for class-component and normalize if neccessary
|
|
287
|
+
const normalizedComponent =
|
|
288
|
+
typeof component === 'function' && '__vccOpts' in component ? (component.__vccOpts as Component) : component
|
|
226
289
|
|
|
227
|
-
return new VueNodeView(
|
|
290
|
+
return new VueNodeView(normalizedComponent, props, options)
|
|
228
291
|
}
|
|
229
292
|
}
|
package/src/VueRenderer.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { Editor } from '@tiptap/core'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
} from 'vue'
|
|
1
|
+
import type { Editor } from '@tiptap/core'
|
|
2
|
+
import type { Component, DefineComponent } from 'vue'
|
|
3
|
+
import { h, markRaw, reactive, render } from 'vue'
|
|
5
4
|
|
|
6
|
-
import { Editor as ExtendedEditor } from './Editor.js'
|
|
5
|
+
import type { Editor as ExtendedEditor } from './Editor.js'
|
|
7
6
|
|
|
8
7
|
export interface VueRendererOptions {
|
|
9
|
-
editor: Editor
|
|
10
|
-
props?: Record<string, any
|
|
8
|
+
editor: Editor
|
|
9
|
+
props?: Record<string, any>
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
type ExtendedVNode = ReturnType<typeof h> | null
|
|
@@ -22,8 +21,6 @@ interface RenderedComponent {
|
|
|
22
21
|
* This class is used to render Vue components inside the editor.
|
|
23
22
|
*/
|
|
24
23
|
export class VueRenderer {
|
|
25
|
-
id: string
|
|
26
|
-
|
|
27
24
|
renderedComponent!: RenderedComponent
|
|
28
25
|
|
|
29
26
|
editor: ExtendedEditor
|
|
@@ -35,7 +32,6 @@ export class VueRenderer {
|
|
|
35
32
|
props: Record<string, any>
|
|
36
33
|
|
|
37
34
|
constructor(component: Component, { props = {}, editor }: VueRendererOptions) {
|
|
38
|
-
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
|
|
39
35
|
this.editor = editor as ExtendedEditor
|
|
40
36
|
this.component = markRaw(component)
|
|
41
37
|
this.el = document.createElement('div')
|
|
@@ -47,13 +43,29 @@ export class VueRenderer {
|
|
|
47
43
|
return this.renderedComponent.el
|
|
48
44
|
}
|
|
49
45
|
|
|
46
|
+
get ref(): any {
|
|
47
|
+
// Composition API
|
|
48
|
+
if (this.renderedComponent.vNode?.component?.exposed) {
|
|
49
|
+
return this.renderedComponent.vNode.component.exposed
|
|
50
|
+
}
|
|
51
|
+
// Option API
|
|
52
|
+
return this.renderedComponent.vNode?.component?.proxy
|
|
53
|
+
}
|
|
54
|
+
|
|
50
55
|
renderComponent() {
|
|
51
56
|
let vNode: ExtendedVNode = h(this.component as DefineComponent, this.props)
|
|
52
57
|
|
|
53
|
-
if (
|
|
58
|
+
if (this.editor.appContext) {
|
|
59
|
+
vNode.appContext = this.editor.appContext
|
|
60
|
+
}
|
|
61
|
+
if (typeof document !== 'undefined' && this.el) {
|
|
62
|
+
render(vNode, this.el)
|
|
63
|
+
}
|
|
54
64
|
|
|
55
65
|
const destroy = () => {
|
|
56
|
-
if (this.el) {
|
|
66
|
+
if (this.el) {
|
|
67
|
+
render(null, this.el)
|
|
68
|
+
}
|
|
57
69
|
this.el = null
|
|
58
70
|
vNode = null
|
|
59
71
|
}
|
|
@@ -62,12 +74,9 @@ export class VueRenderer {
|
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
updateProps(props: Record<string, any> = {}): void {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.forEach(([key, value]) => {
|
|
69
|
-
this.props[key] = value
|
|
70
|
-
})
|
|
77
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
78
|
+
this.props[key] = value
|
|
79
|
+
})
|
|
71
80
|
this.renderComponent()
|
|
72
81
|
}
|
|
73
82
|
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
export * from './BubbleMenu.js'
|
|
2
1
|
export { Editor } from './Editor.js'
|
|
3
2
|
export * from './EditorContent.js'
|
|
4
|
-
export * from './FloatingMenu.js'
|
|
5
3
|
export * from './NodeViewContent.js'
|
|
6
4
|
export * from './NodeViewWrapper.js'
|
|
7
5
|
export * from './useEditor.js'
|
|
6
|
+
export * from './VueMarkViewRenderer.js'
|
|
8
7
|
export * from './VueNodeViewRenderer.js'
|
|
9
8
|
export * from './VueRenderer.js'
|
|
10
9
|
export * from '@tiptap/core'
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { BubbleMenuPluginProps } from '@tiptap/extension-bubble-menu'
|
|
2
|
+
import { BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'
|
|
3
|
+
import type { PropType } from 'vue'
|
|
4
|
+
import { defineComponent, h, onBeforeUnmount, onMounted, ref, Teleport } from 'vue'
|
|
5
|
+
|
|
6
|
+
export const BubbleMenu = defineComponent({
|
|
7
|
+
name: 'BubbleMenu',
|
|
8
|
+
|
|
9
|
+
props: {
|
|
10
|
+
pluginKey: {
|
|
11
|
+
type: [String, Object] as PropType<BubbleMenuPluginProps['pluginKey']>,
|
|
12
|
+
default: 'bubbleMenu',
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
editor: {
|
|
16
|
+
type: Object as PropType<BubbleMenuPluginProps['editor']>,
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
updateDelay: {
|
|
21
|
+
type: Number as PropType<BubbleMenuPluginProps['updateDelay']>,
|
|
22
|
+
default: undefined,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
resizeDelay: {
|
|
26
|
+
type: Number as PropType<BubbleMenuPluginProps['resizeDelay']>,
|
|
27
|
+
default: undefined,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
options: {
|
|
31
|
+
type: Object as PropType<BubbleMenuPluginProps['options']>,
|
|
32
|
+
default: () => ({}),
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
shouldShow: {
|
|
36
|
+
type: Function as PropType<Exclude<Required<BubbleMenuPluginProps>['shouldShow'], null>>,
|
|
37
|
+
default: null,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
setup(props, { slots }) {
|
|
42
|
+
const root = ref<HTMLElement | null>(null)
|
|
43
|
+
|
|
44
|
+
onMounted(() => {
|
|
45
|
+
const { editor, options, pluginKey, resizeDelay, shouldShow, updateDelay } = props
|
|
46
|
+
|
|
47
|
+
if (!root.value) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
root.value.style.visibility = 'hidden'
|
|
52
|
+
root.value.style.position = 'absolute'
|
|
53
|
+
|
|
54
|
+
// remove the element from the DOM
|
|
55
|
+
root.value.remove()
|
|
56
|
+
|
|
57
|
+
editor.registerPlugin(
|
|
58
|
+
BubbleMenuPlugin({
|
|
59
|
+
editor,
|
|
60
|
+
element: root.value as HTMLElement,
|
|
61
|
+
options,
|
|
62
|
+
pluginKey,
|
|
63
|
+
resizeDelay,
|
|
64
|
+
shouldShow,
|
|
65
|
+
updateDelay,
|
|
66
|
+
}),
|
|
67
|
+
)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
onBeforeUnmount(() => {
|
|
71
|
+
const { pluginKey, editor } = props
|
|
72
|
+
|
|
73
|
+
editor.unregisterPlugin(pluginKey)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
return () => h(Teleport, { to: 'body' }, h('div', { ref: root }, slots.default?.()))
|
|
77
|
+
},
|
|
78
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'
|
|
2
|
+
import { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'
|
|
3
|
+
import type { PropType } from 'vue'
|
|
4
|
+
import { defineComponent, h, onBeforeUnmount, onMounted, ref, Teleport } from 'vue'
|
|
5
|
+
|
|
6
|
+
export const FloatingMenu = defineComponent({
|
|
7
|
+
name: 'FloatingMenu',
|
|
8
|
+
|
|
9
|
+
props: {
|
|
10
|
+
pluginKey: {
|
|
11
|
+
// TODO: TypeScript breaks :(
|
|
12
|
+
// type: [String, Object as PropType<Exclude<FloatingMenuPluginProps['pluginKey'], string>>],
|
|
13
|
+
type: null,
|
|
14
|
+
default: 'floatingMenu',
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
editor: {
|
|
18
|
+
type: Object as PropType<FloatingMenuPluginProps['editor']>,
|
|
19
|
+
required: true,
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
options: {
|
|
23
|
+
type: Object as PropType<FloatingMenuPluginProps['options']>,
|
|
24
|
+
default: () => ({}),
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
shouldShow: {
|
|
28
|
+
type: Function as PropType<Exclude<Required<FloatingMenuPluginProps>['shouldShow'], null>>,
|
|
29
|
+
default: null,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
setup(props, { slots }) {
|
|
34
|
+
const root = ref<HTMLElement | null>(null)
|
|
35
|
+
|
|
36
|
+
onMounted(() => {
|
|
37
|
+
const { pluginKey, editor, options, shouldShow } = props
|
|
38
|
+
|
|
39
|
+
if (!root.value) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
root.value.style.visibility = 'hidden'
|
|
44
|
+
root.value.style.position = 'absolute'
|
|
45
|
+
|
|
46
|
+
// remove the element from the DOM
|
|
47
|
+
root.value.remove()
|
|
48
|
+
|
|
49
|
+
editor.registerPlugin(
|
|
50
|
+
FloatingMenuPlugin({
|
|
51
|
+
pluginKey,
|
|
52
|
+
editor,
|
|
53
|
+
element: root.value as HTMLElement,
|
|
54
|
+
options,
|
|
55
|
+
shouldShow,
|
|
56
|
+
}),
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
onBeforeUnmount(() => {
|
|
61
|
+
const { pluginKey, editor } = props
|
|
62
|
+
|
|
63
|
+
editor.unregisterPlugin(pluginKey)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return () => h(Teleport, { to: 'body' }, h('div', { ref: root }, slots.default?.()))
|
|
67
|
+
},
|
|
68
|
+
})
|
package/src/useEditor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EditorOptions } from '@tiptap/core'
|
|
1
|
+
import type { EditorOptions } from '@tiptap/core'
|
|
2
2
|
import { onBeforeUnmount, onMounted, shallowRef } from 'vue'
|
|
3
3
|
|
|
4
4
|
import { Editor } from './Editor.js'
|
|
@@ -11,6 +11,12 @@ export const useEditor = (options: Partial<EditorOptions> = {}) => {
|
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
onBeforeUnmount(() => {
|
|
14
|
+
// Cloning root node (and its children) to avoid content being lost by destroy
|
|
15
|
+
const nodes = editor.value?.options.element
|
|
16
|
+
const newEl = nodes?.cloneNode(true) as HTMLElement
|
|
17
|
+
|
|
18
|
+
nodes?.parentNode?.replaceChild(newEl, nodes)
|
|
19
|
+
|
|
14
20
|
editor.value?.destroy()
|
|
15
21
|
})
|
|
16
22
|
|