tiptap/packages/vue-3/src/EditorContent.ts
Nick Perez 704f4620b3
feat(core): add ability to run editor without a browser + mount API (#6050)
When editor options is provided `element: null`, then the editor view will not be created, allowing use of the editor & it's commands without a browser in pure JS.
2025-01-24 13:53:33 +01:00

88 lines
1.9 KiB
TypeScript

import {
defineComponent,
getCurrentInstance,
h,
nextTick,
onBeforeUnmount,
PropType,
Ref,
ref,
unref,
watchEffect,
} from 'vue'
import { Editor } from './Editor.js'
export const EditorContent = defineComponent({
name: 'EditorContent',
props: {
editor: {
default: null,
type: Object as PropType<Editor>,
},
},
setup(props) {
const rootEl: Ref<Element | undefined> = ref()
const instance = getCurrentInstance()
watchEffect(() => {
const editor = props.editor
if (editor && editor.options.element && rootEl.value) {
nextTick(() => {
if (!rootEl.value || !editor.options.element?.firstChild) {
return
}
// TODO using the new editor.mount method might allow us to remove this
const element = unref(rootEl.value)
rootEl.value.append(...editor.options.element.childNodes)
// @ts-ignore
editor.contentComponent = instance.ctx._
if (instance) {
editor.appContext = {
...instance.appContext,
// Vue internally uses prototype chain to forward/shadow injects across the entire component chain
// so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext
// @ts-expect-error forward instance's 'provides' into appContext
provides: instance.provides,
}
}
editor.setOptions({
element,
})
editor.createNodeViews()
})
}
})
onBeforeUnmount(() => {
const editor = props.editor
if (!editor) {
return
}
editor.contentComponent = null
editor.appContext = null
})
return { rootEl }
},
render() {
return h('div', {
ref: (el: any) => {
this.rootEl = el
},
})
},
})