mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-11-23 19:19:03 +08:00
fix(vue-3): on editor destruction, transition smoothly (#5772)
This commit is contained in:
parent
8a2e548c5b
commit
94a8d258f8
5
.changeset/five-flowers-eat.md
Normal file
5
.changeset/five-flowers-eat.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/vue-3": patch
|
||||
---
|
||||
|
||||
Fix editor destruction before transition end if editor is nested
|
@ -36,7 +36,7 @@ Before submitting a pull request:
|
||||
- Check the codebase to ensure that your feature doesn't already exist.
|
||||
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
|
||||
|
||||
Before commiting:
|
||||
Before committing:
|
||||
|
||||
- Make sure to run the tests and linter before committing your changes.
|
||||
- If you are making changes to one of the packages, make sure to **always** include a [changeset](https://github.com/changesets/changesets) in your PR describing **what changed** with a **description** of the change. Those are responsible for changelog creation
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { mergeAttributes, Node } from '@tiptap/core'
|
||||
import { VueNodeViewRenderer } from '@tiptap/vue-3'
|
||||
|
||||
import Component from './Component.vue'
|
||||
import Component from './VueComponent.vue'
|
||||
|
||||
export default Node.create({
|
||||
name: 'vueComponent',
|
||||
|
36
demos/src/Examples/Transition/Vue/ParentComponent.vue
Normal file
36
demos/src/Examples/Transition/Vue/ParentComponent.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div>
|
||||
<EditorContent :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import { EditorContent, useEditor } from '@tiptap/vue-3'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import VueComponent from './Extension.js'
|
||||
import type { TNote } from './types.js'
|
||||
|
||||
const note = ref<TNote>({
|
||||
id: 'note-1',
|
||||
content: `
|
||||
<p>Some random note text</p>
|
||||
<vue-component count="0"></vue-component>
|
||||
`,
|
||||
})
|
||||
|
||||
const editor = useEditor({
|
||||
content: note.value.content,
|
||||
editorProps: {
|
||||
attributes: {
|
||||
class: 'textarea',
|
||||
},
|
||||
},
|
||||
extensions: [
|
||||
StarterKit,
|
||||
VueComponent,
|
||||
],
|
||||
})
|
||||
|
||||
</script>
|
@ -3,26 +3,30 @@ context('/src/Examples/Transition/Vue/', () => {
|
||||
cy.visit('/src/Examples/Transition/Vue/')
|
||||
})
|
||||
|
||||
it('should not have an active tiptap instance but a button', () => {
|
||||
it('should have two buttons and no active tiptap instance', () => {
|
||||
cy.get('.tiptap').should('not.exist')
|
||||
|
||||
cy.get('#toggle-editor').should('exist')
|
||||
cy.get('#toggle-direct-editor').should('exist')
|
||||
cy.get('#toggle-nested-editor').should('exist')
|
||||
})
|
||||
|
||||
it('clicking the button should show the editor', () => {
|
||||
cy.get('#toggle-editor').click()
|
||||
it('clicking the buttons should show two editors', () => {
|
||||
cy.get('#toggle-direct-editor').click()
|
||||
cy.get('#toggle-nested-editor').click()
|
||||
|
||||
cy.get('.tiptap').should('exist')
|
||||
cy.get('.tiptap').should('be.visible')
|
||||
})
|
||||
|
||||
it('clicking the button again should hide the editor', () => {
|
||||
cy.get('#toggle-editor').click()
|
||||
it('clicking the buttons again should hide the editors', () => {
|
||||
cy.get('#toggle-direct-editor').click()
|
||||
cy.get('#toggle-nested-editor').click()
|
||||
|
||||
cy.get('.tiptap').should('exist')
|
||||
cy.get('.tiptap').should('be.visible')
|
||||
|
||||
cy.get('#toggle-editor').click()
|
||||
cy.get('#toggle-direct-editor').click()
|
||||
cy.get('#toggle-nested-editor').click()
|
||||
|
||||
cy.get('.tiptap').should('not.exist')
|
||||
})
|
||||
|
@ -1,12 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import { EditorContent, useEditor } from '@tiptap/vue-3'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import VueComponent from './Extension.js'
|
||||
import ParentComponent from './ParentComponent.vue'
|
||||
import type { TNote } from './types.js'
|
||||
|
||||
/** Display editor in the same component */
|
||||
const showDirectEditor = ref(false)
|
||||
|
||||
/** Display editor in a child component */
|
||||
const showNestedEditor = ref(false)
|
||||
|
||||
const note = ref<TNote>({
|
||||
id: 'note-1',
|
||||
content: `
|
||||
@ -28,24 +34,43 @@ const editor = useEditor({
|
||||
],
|
||||
})
|
||||
|
||||
const showEditor = ref(false)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Transition with editor in the same component -->
|
||||
<div>
|
||||
<button
|
||||
id="toggle-direct-editor"
|
||||
type="button"
|
||||
@click="showEditor = !showEditor"
|
||||
style="margin-bottom: 1rem;"
|
||||
id="toggle-editor"
|
||||
@click="showDirectEditor = !showDirectEditor"
|
||||
>
|
||||
{{ showEditor ? 'Hide editor' : 'Show editor' }}
|
||||
{{ showDirectEditor ? 'Hide direct editor' : 'Show direct editor' }}
|
||||
</button>
|
||||
|
||||
<transition name="fade">
|
||||
<div v-if="showEditor" class="tiptap-wrapper">
|
||||
<editor-content :editor="editor" />
|
||||
<div v-if="showDirectEditor" class="tiptap-wrapper">
|
||||
<EditorContent :editor="editor" />
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- Transition with editor in a child component -->
|
||||
<div>
|
||||
<button
|
||||
id="toggle-nested-editor"
|
||||
type="button"
|
||||
style="margin-bottom: 1rem;"
|
||||
@click="showNestedEditor = !showNestedEditor"
|
||||
>
|
||||
{{ showNestedEditor ? 'Hide nested editor' : 'Show nested editor' }}
|
||||
</button>
|
||||
|
||||
<transition name="fade">
|
||||
<div v-if="showNestedEditor" class="tiptap-wrapper">
|
||||
<ParentComponent />
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
@ -62,6 +87,11 @@ const showEditor = ref(false)
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.tiptap-wrapper {
|
||||
background-color: var(--purple-light);
|
||||
border: 2px solid var(--purple);
|
||||
|
@ -59,7 +59,6 @@ export const EditorContent = defineComponent({
|
||||
|
||||
editor.createNodeViews()
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -11,6 +11,12 @@ export const useEditor = (options: Partial<EditorOptions> = {}) => {
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// Cloning root node (and its children) to avoid content being lost by destroy
|
||||
const nodes = editor.value?.options.element
|
||||
const newEl = nodes?.cloneNode(true) as HTMLElement
|
||||
|
||||
nodes?.parentNode?.replaceChild(newEl, nodes)
|
||||
|
||||
editor.value?.destroy()
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user