mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-07 17:43:49 +08:00
Merge branch 'next' of github.com:ueberdosis/tiptap into feature/resizable-node-views
This commit is contained in:
commit
4083d5194b
5
.changeset/cool-singers-call.md
Normal file
5
.changeset/cool-singers-call.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'@tiptap/core': major
|
||||
---
|
||||
|
||||
This resolves in issue with SSR where the isDestroyed property could not be read while in SSR
|
5
.changeset/lucky-bears-exercise.md
Normal file
5
.changeset/lucky-bears-exercise.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/core": patch
|
||||
---
|
||||
|
||||
Fixes a bug where you could not unregister multiple plugins.
|
@ -71,6 +71,7 @@
|
||||
"chilly-lemons-remember",
|
||||
"clever-bags-end",
|
||||
"cool-bananas-breathe",
|
||||
"cool-singers-call",
|
||||
"cuddly-impalas-heal",
|
||||
"curly-adults-move",
|
||||
"dirty-bats-look",
|
||||
@ -83,6 +84,7 @@
|
||||
"healthy-pigs-work",
|
||||
"large-kangaroos-battle",
|
||||
"lazy-needles-train",
|
||||
"lucky-bears-exercise",
|
||||
"many-laws-vanish",
|
||||
"moody-geckos-sort",
|
||||
"nervous-hairs-walk",
|
||||
@ -93,16 +95,18 @@
|
||||
"quick-days-matter",
|
||||
"red-ants-wonder",
|
||||
"red-rivers-exist",
|
||||
"selfish-rings-hang",
|
||||
"seven-llamas-love",
|
||||
"shaggy-hats-rescue",
|
||||
"shiny-days-rhyme",
|
||||
"sixty-news-ring",
|
||||
"smooth-carrots-beam",
|
||||
"spotty-cobras-shake",
|
||||
"tame-worms-applaud",
|
||||
"thirty-rockets-act",
|
||||
"tidy-fireants-hang",
|
||||
"twenty-moose-invent",
|
||||
"weak-books-eat",
|
||||
"wise-books-kiss",
|
||||
"wise-carpets-unite",
|
||||
"witty-eels-cheer"
|
||||
]
|
||||
|
6
.changeset/selfish-rings-hang.md
Normal file
6
.changeset/selfish-rings-hang.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
'@tiptap/extension-collaboration-caret': patch
|
||||
'@tiptap/extension-collaboration': patch
|
||||
---
|
||||
|
||||
Use newer y-prosemirror version to resolve dependency chaos
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
'@tiptap/react': patch
|
||||
---
|
||||
|
||||
Fixed a bug in the EditorContent component that caused a crash in Firefox based browsers because of the editor view not being available when an uninitialized editor is unmounted (for example via Strict mode)
|
5
.changeset/spotty-cobras-shake.md
Normal file
5
.changeset/spotty-cobras-shake.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/extension-text-align": patch
|
||||
---
|
||||
|
||||
Added new `toggleTextAlign` command to TextAlign extension to make toggling text alignments easier to handle
|
5
.changeset/wise-books-kiss.md
Normal file
5
.changeset/wise-books-kiss.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'@tiptap/extension-mention': minor
|
||||
---
|
||||
|
||||
Support multiple triggers in Mention extension
|
@ -15,7 +15,7 @@
|
||||
"@lexical/react": "^0.11.3",
|
||||
"@lifeomic/attempt": "3.1.0",
|
||||
"@shikijs/core": "1.10.3",
|
||||
"@tiptap/y-tiptap": "^2.0.0",
|
||||
"@tiptap/y-tiptap": "^3.0.0-beta.3",
|
||||
"d3": "^7.9.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"highlight.js": "^11.11.1",
|
||||
@ -63,7 +63,7 @@
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.7.2",
|
||||
"uuid": "^8.3.2",
|
||||
"vite": "^5.4.15",
|
||||
"vite": "^5.4.17",
|
||||
"vite-plugin-checker": "^0.6.4",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
|
@ -106,7 +106,7 @@ context('/src/Commands/SetContent/React/', () => {
|
||||
editor.commands.setContent('<p><span data-type="mention" data-id="1" data-label="John Doe">@John Doe</span></p>')
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span data-type="mention" data-id="1" data-label="John Doe" contenteditable="false">@John Doe</span>',
|
||||
'<span data-type="mention" data-id="1" data-label="John Doe" data-mention-suggestion-char="@" contenteditable="false">@John Doe</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
68
demos/src/Examples/MultiMention/React/MentionList.jsx
Normal file
68
demos/src/Examples/MultiMention/React/MentionList.jsx
Normal file
@ -0,0 +1,68 @@
|
||||
import './MentionList.scss'
|
||||
|
||||
import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
|
||||
export default forwardRef((props, ref) => {
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
|
||||
const selectItem = index => {
|
||||
const item = props.items[index]
|
||||
|
||||
if (item) {
|
||||
props.command({ id: item })
|
||||
}
|
||||
}
|
||||
|
||||
const upHandler = () => {
|
||||
setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length)
|
||||
}
|
||||
|
||||
const downHandler = () => {
|
||||
setSelectedIndex((selectedIndex + 1) % props.items.length)
|
||||
}
|
||||
|
||||
const enterHandler = () => {
|
||||
selectItem(selectedIndex)
|
||||
}
|
||||
|
||||
useEffect(() => setSelectedIndex(0), [props.items])
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
onKeyDown: ({ event }) => {
|
||||
if (event.key === 'ArrowUp') {
|
||||
upHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowDown') {
|
||||
downHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.key === 'Enter') {
|
||||
enterHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
}))
|
||||
|
||||
return (
|
||||
<div className="dropdown-menu">
|
||||
{props.items.length ? (
|
||||
props.items.map((item, index) => (
|
||||
<button
|
||||
className={index === selectedIndex ? 'is-selected' : ''}
|
||||
key={index}
|
||||
onClick={() => selectItem(index)}
|
||||
>
|
||||
{item}
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="item">No result</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
31
demos/src/Examples/MultiMention/React/MentionList.scss
Normal file
31
demos/src/Examples/MultiMention/React/MentionList.scss
Normal file
@ -0,0 +1,31 @@
|
||||
/* Dropdown menu */
|
||||
.dropdown-menu {
|
||||
background: var(--white);
|
||||
border: 1px solid var(--gray-1);
|
||||
border-radius: 0.7rem;
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
overflow: auto;
|
||||
padding: 0.4rem;
|
||||
position: relative;
|
||||
|
||||
button {
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
|
||||
&:hover,
|
||||
&:hover.is-selected {
|
||||
background-color: var(--gray-3);
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background-color: var(--gray-2);
|
||||
}
|
||||
}
|
||||
}
|
0
demos/src/Examples/MultiMention/React/index.html
Normal file
0
demos/src/Examples/MultiMention/React/index.html
Normal file
40
demos/src/Examples/MultiMention/React/index.jsx
Normal file
40
demos/src/Examples/MultiMention/React/index.jsx
Normal file
@ -0,0 +1,40 @@
|
||||
import './styles.scss'
|
||||
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Mention from '@tiptap/extension-mention'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import { EditorContent, useEditor } from '@tiptap/react'
|
||||
import React from 'react'
|
||||
|
||||
import suggestions from './suggestions.js'
|
||||
|
||||
export default () => {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
Mention.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'mention',
|
||||
},
|
||||
suggestions,
|
||||
}),
|
||||
],
|
||||
content: `
|
||||
<p>Hi everyone! Don’t forget the daily stand up at 8 AM.</p>
|
||||
<p>We will talk about the movies: <span data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#"></span>, <span data-type="mention" data-id="Pirates of the Caribbean" data-mention-suggestion-char="#"></span> and <span data-type="mention" data-id="The Matrix" data-mention-suggestion-char="#"></span>.</p>
|
||||
<p><span data-type="mention" data-id="Jennifer Grey"></span> Would you mind to share what you’ve been working on lately? We fear not much happened since <span data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#"></span>.</p>
|
||||
<p><span data-type="mention" data-id="Winona Ryder"></span> <span data-type="mention" data-id="Axl Rose"></span> Let’s go through your most important points quickly.</p>
|
||||
<p>I have a meeting with <span data-type="mention" data-id="Christina Applegate"></span> and don’t want to come late.</p>
|
||||
<p>– Thanks, your big boss</p>
|
||||
`,
|
||||
})
|
||||
|
||||
if (!editor) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <EditorContent editor={editor} />
|
||||
}
|
226
demos/src/Examples/MultiMention/React/index.spec.js
Normal file
226
demos/src/Examples/MultiMention/React/index.spec.js
Normal file
@ -0,0 +1,226 @@
|
||||
context('/src/Examples/MultiMention/React/', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/src/Examples/MultiMention/React/')
|
||||
})
|
||||
|
||||
describe('Person mentions (@)', () => {
|
||||
it('should insert a person mention', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.setContent('<p><span data-type="mention" data-id="Lea Thompson">@Lea Thompson</span></p>')
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Lea Thompson" data-mention-suggestion-char="@" contenteditable="false">@Lea Thompson</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should open a dropdown menu when I type '@'", () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
})
|
||||
|
||||
it('should display the correct person options in the dropdown menu', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button').should('have.length', 5)
|
||||
cy.get('.dropdown-menu button:nth-child(1)')
|
||||
.should('contain.text', 'Lea Thompson')
|
||||
.and('have.class', 'is-selected')
|
||||
cy.get('.dropdown-menu button:nth-child(2)').should('contain.text', 'Cyndi Lauper')
|
||||
cy.get('.dropdown-menu button:nth-child(3)').should('contain.text', 'Tom Cruise')
|
||||
cy.get('.dropdown-menu button:nth-child(4)').should('contain.text', 'Madonna')
|
||||
cy.get('.dropdown-menu button:nth-child(5)').should('contain.text', 'Jerry Hall')
|
||||
})
|
||||
|
||||
it('should insert Cyndi Lauper mention when clicking on her option', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button:nth-child(2)').contains('Cyndi Lauper').click()
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Cyndi Lauper" data-mention-suggestion-char="@" contenteditable="false">@Cyndi Lauper</span>',
|
||||
)
|
||||
})
|
||||
|
||||
it('should close the dropdown menu when I move the cursor outside the editor', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{moveToStart}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
})
|
||||
|
||||
it('should close the dropdown menu when I press the escape key', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{esc}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
})
|
||||
|
||||
it('should insert Tom Cruise when selecting his option with the arrow keys and pressing the enter key', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{downarrow}{downarrow}')
|
||||
cy.get('.dropdown-menu button:nth-child(3)').should('have.class', 'is-selected')
|
||||
cy.get('.tiptap').type('{enter}')
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Tom Cruise" data-mention-suggestion-char="@" contenteditable="false">@Tom Cruise</span>',
|
||||
)
|
||||
})
|
||||
|
||||
it('should show a "No result" message when I search for a person that is not in the list', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@nonexistent')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu').should('contain.text', 'No result')
|
||||
})
|
||||
|
||||
it('should only show the Madonna option in the dropdown when I type "@mado"', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@mado')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button').should('have.length', 1)
|
||||
cy.get('.dropdown-menu button:nth-child(1)').should('contain.text', 'Madonna')
|
||||
})
|
||||
|
||||
it('should insert Madonna when I type "@mado" and hit enter', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@mado{enter}')
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Madonna" data-mention-suggestion-char="@" contenteditable="false">@Madonna</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Movie mentions (#)', () => {
|
||||
it('should insert a movie mention', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.setContent(
|
||||
'<p><span data-type="mention" data-id="The Matrix" data-mention-suggestion-char="#">#The Matrix</span></p>',
|
||||
)
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="The Matrix" data-mention-suggestion-char="#" contenteditable="false">#The Matrix</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should open a dropdown menu when I type '#'", () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
})
|
||||
|
||||
it('should display the correct movie options in the dropdown menu', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button').should('have.length', 3)
|
||||
cy.get('.dropdown-menu button:nth-child(1)')
|
||||
.should('contain.text', 'Dirty Dancing')
|
||||
.and('have.class', 'is-selected')
|
||||
cy.get('.dropdown-menu button:nth-child(2)').should('contain.text', 'Pirates of the Caribbean')
|
||||
cy.get('.dropdown-menu button:nth-child(3)').should('contain.text', 'The Matrix')
|
||||
})
|
||||
|
||||
it('should insert Pirates of the Caribbean mention when clicking on its option', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button:nth-child(2)').contains('Pirates of the Caribbean').click()
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Pirates of the Caribbean" data-mention-suggestion-char="#" contenteditable="false">#Pirates of the Caribbean</span>',
|
||||
)
|
||||
})
|
||||
|
||||
it('should close the dropdown menu when I move the cursor outside the editor', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{moveToStart}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
})
|
||||
|
||||
it('should close the dropdown menu when I press the escape key', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{esc}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
})
|
||||
|
||||
it('should insert The Matrix when selecting its option with the arrow keys and pressing the enter key', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{downarrow}{downarrow}')
|
||||
cy.get('.dropdown-menu button:nth-child(3)').should('have.class', 'is-selected')
|
||||
cy.get('.tiptap').type('{enter}')
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="The Matrix" data-mention-suggestion-char="#" contenteditable="false">#The Matrix</span>',
|
||||
)
|
||||
})
|
||||
|
||||
it('should show a "No result" message when I search for a movie that is not in the list', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#nonexistent')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu').should('contain.text', 'No result')
|
||||
})
|
||||
|
||||
it('should only show the Dirty Dancing option in the dropdown when I type "#dir"', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#dir')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button').should('have.length', 1)
|
||||
cy.get('.dropdown-menu button:nth-child(1)').should('contain.text', 'Dirty Dancing')
|
||||
})
|
||||
|
||||
it('should insert Dirty Dancing when I type "#dir" and hit enter', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#dir{enter}')
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#" contenteditable="false">#Dirty Dancing</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Interaction between mention types', () => {
|
||||
it('should support both mention types in the same document', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.setContent(
|
||||
'<p><span data-type="mention" data-id="Madonna">@Madonna</span> starred in <span data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#">#Dirty Dancing</span></p>',
|
||||
)
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Madonna" data-mention-suggestion-char="@" contenteditable="false">@Madonna</span>',
|
||||
)
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#" contenteditable="false">#Dirty Dancing</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow switching between mention types', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button:nth-child(1)').should('contain.text', 'Lea Thompson')
|
||||
|
||||
// Close the dropdown by moving cursor
|
||||
cy.get('.tiptap').type('{moveToStart}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
|
||||
// Open a new dropdown with #
|
||||
cy.get('.tiptap').type('{selectall}{backspace}#')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button:nth-child(1)').should('contain.text', 'Dirty Dancing')
|
||||
})
|
||||
|
||||
it('should insert both types of mentions in sequence', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@mado{enter} likes #the{enter}')
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Madonna" data-mention-suggestion-char="@" contenteditable="false">@Madonna</span> likes <span class="mention" data-type="mention" data-id="The Matrix" data-mention-suggestion-char="#" contenteditable="false">#The Matrix</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
17
demos/src/Examples/MultiMention/React/styles.scss
Normal file
17
demos/src/Examples/MultiMention/React/styles.scss
Normal file
@ -0,0 +1,17 @@
|
||||
/* Basic editor styles */
|
||||
.tiptap {
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mention {
|
||||
background-color: var(--purple-light);
|
||||
border-radius: 0.4rem;
|
||||
box-decoration-break: clone;
|
||||
color: var(--purple);
|
||||
padding: 0.1rem 0.3rem;
|
||||
&::after {
|
||||
content: '\200B';
|
||||
}
|
||||
}
|
||||
}
|
159
demos/src/Examples/MultiMention/React/suggestions.js
Normal file
159
demos/src/Examples/MultiMention/React/suggestions.js
Normal file
@ -0,0 +1,159 @@
|
||||
import { computePosition, flip, shift } from '@floating-ui/dom'
|
||||
import { posToDOMRect, ReactRenderer } from '@tiptap/react'
|
||||
|
||||
import MentionList from './MentionList.jsx'
|
||||
|
||||
const updatePosition = (editor, element) => {
|
||||
const virtualElement = {
|
||||
getBoundingClientRect: () => posToDOMRect(editor.view, editor.state.selection.from, editor.state.selection.to),
|
||||
}
|
||||
|
||||
computePosition(virtualElement, element, {
|
||||
placement: 'bottom-start',
|
||||
strategy: 'absolute',
|
||||
middleware: [shift(), flip()],
|
||||
}).then(({ x, y, strategy }) => {
|
||||
element.style.width = 'max-content'
|
||||
element.style.position = strategy
|
||||
element.style.left = `${x}px`
|
||||
element.style.top = `${y}px`
|
||||
})
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
items: ({ query }) => {
|
||||
return [
|
||||
'Lea Thompson',
|
||||
'Cyndi Lauper',
|
||||
'Tom Cruise',
|
||||
'Madonna',
|
||||
'Jerry Hall',
|
||||
'Joan Collins',
|
||||
'Winona Ryder',
|
||||
'Christina Applegate',
|
||||
'Alyssa Milano',
|
||||
'Molly Ringwald',
|
||||
'Ally Sheedy',
|
||||
'Debbie Harry',
|
||||
'Olivia Newton-John',
|
||||
'Elton John',
|
||||
'Michael J. Fox',
|
||||
'Axl Rose',
|
||||
'Emilio Estevez',
|
||||
'Ralph Macchio',
|
||||
'Rob Lowe',
|
||||
'Jennifer Grey',
|
||||
'Mickey Rourke',
|
||||
'John Cusack',
|
||||
'Matthew Broderick',
|
||||
'Justine Bateman',
|
||||
'Lisa Bonet',
|
||||
]
|
||||
.filter(item => item.toLowerCase().startsWith(query.toLowerCase()))
|
||||
.slice(0, 5)
|
||||
},
|
||||
|
||||
render: () => {
|
||||
let component
|
||||
|
||||
return {
|
||||
onStart: props => {
|
||||
component = new ReactRenderer(MentionList, {
|
||||
props,
|
||||
editor: props.editor,
|
||||
})
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
component.element.style.position = 'absolute'
|
||||
|
||||
document.body.appendChild(component.element)
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onUpdate(props) {
|
||||
component.updateProps(props)
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onKeyDown(props) {
|
||||
if (props.event.key === 'Escape') {
|
||||
component.destroy()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return component.ref?.onKeyDown(props)
|
||||
},
|
||||
|
||||
onExit() {
|
||||
component.destroy()
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
char: '#',
|
||||
items: ({ query }) => {
|
||||
return ['Dirty Dancing', 'Pirates of the Caribbean', 'The Matrix']
|
||||
.filter(item => item.toLowerCase().startsWith(query.toLowerCase()))
|
||||
.slice(0, 5)
|
||||
},
|
||||
|
||||
render: () => {
|
||||
let component
|
||||
|
||||
return {
|
||||
onStart: props => {
|
||||
component = new ReactRenderer(MentionList, {
|
||||
props,
|
||||
editor: props.editor,
|
||||
})
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
component.element.style.position = 'absolute'
|
||||
|
||||
document.body.appendChild(component.element)
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onUpdate(props) {
|
||||
component.updateProps(props)
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onKeyDown(props) {
|
||||
if (props.event.key === 'Escape') {
|
||||
component.destroy()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return component.ref?.onKeyDown(props)
|
||||
},
|
||||
|
||||
onExit() {
|
||||
component.destroy()
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
118
demos/src/Examples/MultiMention/Vue/MentionList.vue
Normal file
118
demos/src/Examples/MultiMention/Vue/MentionList.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="dropdown-menu">
|
||||
<template v-if="items.length">
|
||||
<button
|
||||
:class="{ 'is-selected': index === selectedIndex }"
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
@click="selectItem(index)"
|
||||
>
|
||||
{{ item }}
|
||||
</button>
|
||||
</template>
|
||||
<div class="item" v-else>No result</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
|
||||
command: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
selectedIndex: 0,
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
items() {
|
||||
this.selectedIndex = 0
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onKeyDown({ event }) {
|
||||
if (event.key === 'ArrowUp') {
|
||||
this.upHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowDown') {
|
||||
this.downHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.key === 'Enter') {
|
||||
this.enterHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
upHandler() {
|
||||
this.selectedIndex = (this.selectedIndex + this.items.length - 1) % this.items.length
|
||||
},
|
||||
|
||||
downHandler() {
|
||||
this.selectedIndex = (this.selectedIndex + 1) % this.items.length
|
||||
},
|
||||
|
||||
enterHandler() {
|
||||
this.selectItem(this.selectedIndex)
|
||||
},
|
||||
|
||||
selectItem(index) {
|
||||
const item = this.items[index]
|
||||
|
||||
if (item) {
|
||||
this.command({ id: item })
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* Dropdown menu */
|
||||
.dropdown-menu {
|
||||
background: var(--white);
|
||||
border: 1px solid var(--gray-1);
|
||||
border-radius: 0.7rem;
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
overflow: auto;
|
||||
padding: 0.4rem;
|
||||
position: relative;
|
||||
|
||||
button {
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
|
||||
&:hover,
|
||||
&:hover.is-selected {
|
||||
background-color: var(--gray-3);
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background-color: var(--gray-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
0
demos/src/Examples/MultiMention/Vue/index.html
Normal file
0
demos/src/Examples/MultiMention/Vue/index.html
Normal file
7
demos/src/Examples/MultiMention/Vue/index.spec.js
Normal file
7
demos/src/Examples/MultiMention/Vue/index.spec.js
Normal file
@ -0,0 +1,7 @@
|
||||
context('/src/Nodes/Mention/Vue/', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/src/Nodes/Mention/Vue/')
|
||||
})
|
||||
|
||||
// TODO: Write tests
|
||||
})
|
72
demos/src/Examples/MultiMention/Vue/index.vue
Normal file
72
demos/src/Examples/MultiMention/Vue/index.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div v-if="editor">
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Mention from '@tiptap/extension-mention'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import { Editor, EditorContent } from '@tiptap/vue-3'
|
||||
|
||||
import suggestions from './suggestions.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
Mention.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'mention',
|
||||
},
|
||||
suggestions,
|
||||
}),
|
||||
],
|
||||
content: `
|
||||
<p>Hi everyone! Don’t forget the daily stand up at 8 AM.</p>
|
||||
<p>We will talk about the movies: <span data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#"></span>, <span data-type="mention" data-id="Pirates of the Caribbean" data-mention-suggestion-char="#"></span> and <span data-type="mention" data-id="The Matrix" data-mention-suggestion-char="#"></span>.</p>
|
||||
<p><span data-type="mention" data-id="Jennifer Grey"></span> Would you mind to share what you’ve been working on lately? We fear not much happened since <span data-type="mention" data-id="Dirty Dancing" data-mention-suggestion-char="#"></span>.</p>
|
||||
<p><span data-type="mention" data-id="Winona Ryder"></span> <span data-type="mention" data-id="Axl Rose"></span> Let’s go through your most important points quickly.</p>
|
||||
<p>I have a meeting with <span data-type="mention" data-id="Christina Applegate"></span> and don’t want to come late.</p>
|
||||
<p>– Thanks, your big boss</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* Basic editor styles */
|
||||
.tiptap {
|
||||
:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mention {
|
||||
background-color: var(--purple-light);
|
||||
border-radius: 0.4rem;
|
||||
box-decoration-break: clone;
|
||||
color: var(--purple);
|
||||
padding: 0.1rem 0.3rem;
|
||||
}
|
||||
}
|
||||
</style>
|
168
demos/src/Examples/MultiMention/Vue/suggestions.js
Normal file
168
demos/src/Examples/MultiMention/Vue/suggestions.js
Normal file
@ -0,0 +1,168 @@
|
||||
import { computePosition, flip, shift } from '@floating-ui/dom'
|
||||
import { posToDOMRect, VueRenderer } from '@tiptap/vue-3'
|
||||
|
||||
import MentionList from './MentionList.vue'
|
||||
|
||||
const updatePosition = (editor, element) => {
|
||||
const virtualElement = {
|
||||
getBoundingClientRect: () => posToDOMRect(editor.view, editor.state.selection.from, editor.state.selection.to),
|
||||
}
|
||||
|
||||
computePosition(virtualElement, element, {
|
||||
placement: 'bottom-start',
|
||||
strategy: 'absolute',
|
||||
middleware: [shift(), flip()],
|
||||
}).then(({ x, y, strategy }) => {
|
||||
element.style.width = 'max-content'
|
||||
element.style.position = strategy
|
||||
element.style.left = `${x}px`
|
||||
element.style.top = `${y}px`
|
||||
})
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
char: '@',
|
||||
items: ({ query }) => {
|
||||
return [
|
||||
'Lea Thompson',
|
||||
'Cyndi Lauper',
|
||||
'Tom Cruise',
|
||||
'Madonna',
|
||||
'Jerry Hall',
|
||||
'Joan Collins',
|
||||
'Winona Ryder',
|
||||
'Christina Applegate',
|
||||
'Alyssa Milano',
|
||||
'Molly Ringwald',
|
||||
'Ally Sheedy',
|
||||
'Debbie Harry',
|
||||
'Olivia Newton-John',
|
||||
'Elton John',
|
||||
'Michael J. Fox',
|
||||
'Axl Rose',
|
||||
'Emilio Estevez',
|
||||
'Ralph Macchio',
|
||||
'Rob Lowe',
|
||||
'Jennifer Grey',
|
||||
'Mickey Rourke',
|
||||
'John Cusack',
|
||||
'Matthew Broderick',
|
||||
'Justine Bateman',
|
||||
'Lisa Bonet',
|
||||
]
|
||||
.filter(item => item.toLowerCase().startsWith(query.toLowerCase()))
|
||||
.slice(0, 5)
|
||||
},
|
||||
|
||||
render: () => {
|
||||
let component
|
||||
|
||||
return {
|
||||
onStart: props => {
|
||||
component = new VueRenderer(MentionList, {
|
||||
// using vue 2:
|
||||
// parent: this,
|
||||
// propsData: props,
|
||||
// using vue 3:
|
||||
props,
|
||||
editor: props.editor,
|
||||
})
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
component.element.style.position = 'absolute'
|
||||
|
||||
document.body.appendChild(component.element)
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onUpdate(props) {
|
||||
component.updateProps(props)
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onKeyDown(props) {
|
||||
if (props.event.key === 'Escape') {
|
||||
component.destroy()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return component.ref?.onKeyDown(props)
|
||||
},
|
||||
|
||||
onExit() {
|
||||
component.destroy()
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
char: '#',
|
||||
items: ({ query }) => {
|
||||
return ['Dirty Dancing', 'Pirates of the Caribbean', 'The Matrix']
|
||||
.filter(item => item.toLowerCase().startsWith(query.toLowerCase()))
|
||||
.slice(0, 5)
|
||||
},
|
||||
|
||||
render: () => {
|
||||
let component
|
||||
|
||||
return {
|
||||
onStart: props => {
|
||||
component = new VueRenderer(MentionList, {
|
||||
// using vue 2:
|
||||
// parent: this,
|
||||
// propsData: props,
|
||||
// using vue 3:
|
||||
props,
|
||||
editor: props.editor,
|
||||
})
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
component.element.style.position = 'absolute'
|
||||
|
||||
document.body.appendChild(component.element)
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onUpdate(props) {
|
||||
component.updateProps(props)
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
updatePosition(props.editor, component.element)
|
||||
},
|
||||
|
||||
onKeyDown(props) {
|
||||
if (props.event.key === 'Escape') {
|
||||
component.destroy()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return component.ref?.onKeyDown(props)
|
||||
},
|
||||
|
||||
onExit() {
|
||||
component.destroy()
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
@ -1,6 +1,5 @@
|
||||
import { Extension } from '@tiptap/core'
|
||||
import { NodeSelection, Plugin } from '@tiptap/pm/state'
|
||||
import { EditorView } from '@tiptap/pm/view'
|
||||
|
||||
function removeNode(node) {
|
||||
node.parentNode.removeChild(node)
|
||||
@ -63,7 +62,7 @@ export default Extension.create({
|
||||
// from: view.nodeDOM(view.state.selection.from),
|
||||
// to: view.nodeDOM(view.state.selection.to),
|
||||
// })
|
||||
const { dom, text } = EditorView.serializeForClipboard(view, slice)
|
||||
const { dom, text } = view.serializeForClipboard(slice)
|
||||
|
||||
e.dataTransfer.clearData()
|
||||
e.dataTransfer.setData('text/html', dom.innerHTML)
|
||||
|
@ -59,6 +59,12 @@ export default () => {
|
||||
Justify
|
||||
</button>
|
||||
<button onClick={() => editor.chain().focus().unsetTextAlign().run()}>Unset text align</button>
|
||||
<button
|
||||
onClick={() => editor.chain().focus().toggleTextAlign('right').run()}
|
||||
className={editor.isActive({ textAlign: 'right' }) ? 'is-active' : ''}
|
||||
>
|
||||
Toggle Right
|
||||
</button>
|
||||
<button
|
||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||
className={editor.isActive({ level: 1 }) ? 'is-active' : ''}
|
||||
|
@ -89,6 +89,14 @@ context('/src/Extensions/TextAlign/React/', () => {
|
||||
cy.get('.tiptap').find('p').should('not.have.css', 'text-align', 'left')
|
||||
})
|
||||
|
||||
it('toggle the text to right on the 6rd button', () => {
|
||||
cy.get('button:nth-child(6)').click()
|
||||
cy.get('.tiptap').find('p').should('not.have.css', 'text-align', 'right')
|
||||
|
||||
cy.get('button:nth-child(6)').click()
|
||||
cy.get('.tiptap').find('p').should('not.have.css', 'text-align', 'left')
|
||||
})
|
||||
|
||||
it('aligns the text left when pressing the keyboard shortcut', () => {
|
||||
cy.get('.tiptap')
|
||||
.trigger('keydown', { modKey: true, shiftKey: true, key: 'l' })
|
||||
|
@ -89,6 +89,16 @@ context('/src/Extensions/TextAlign/Vue/', () => {
|
||||
cy.get('.tiptap').find('p').should('not.have.css', 'text-align', 'left')
|
||||
})
|
||||
|
||||
it('toggle the text to right on the 6rd button', () => {
|
||||
cy.get('button:nth-child(6)').click()
|
||||
|
||||
cy.get('.tiptap').find('p').should('have.css', 'text-align', 'right')
|
||||
|
||||
cy.get('button:nth-child(6)').click()
|
||||
|
||||
cy.get('.tiptap').find('p').should('have.css', 'text-align', 'left')
|
||||
})
|
||||
|
||||
it('aligns the text left when pressing the keyboard shortcut', () => {
|
||||
cy.get('.tiptap')
|
||||
.trigger('keydown', { modKey: true, shiftKey: true, key: 'l' })
|
||||
|
@ -27,6 +27,12 @@
|
||||
Justify
|
||||
</button>
|
||||
<button @click="editor.chain().focus().unsetTextAlign().run()">Unset text align</button>
|
||||
<button
|
||||
@click="editor.chain().focus().toggleTextAlign('right').run()"
|
||||
:class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }"
|
||||
>
|
||||
Toggle Right
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<editor-content :editor="editor" />
|
||||
|
@ -3,5 +3,110 @@ context('/src/Nodes/Mention/React/', () => {
|
||||
cy.visit('/src/Nodes/Mention/React/')
|
||||
})
|
||||
|
||||
// TODO: Write tests
|
||||
it('should insert a mention', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.setContent('<p><span data-type="mention" data-id="1" data-label="John Doe">@John Doe</span></p>')
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="1" data-label="John Doe" data-mention-suggestion-char="@" contenteditable="false">@John Doe</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('should insert multiple mentions', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.setContent(
|
||||
'<p><span data-type="mention" data-id="1" data-label="John Doe">@John Doe</span> and <span data-type="mention" data-id="2" data-label="Jane Smith">@Jane Smith</span></p>',
|
||||
)
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="1" data-label="John Doe" data-mention-suggestion-char="@" contenteditable="false">@John Doe</span> and <span class="mention" data-type="mention" data-id="2" data-label="Jane Smith" data-mention-suggestion-char="@" contenteditable="false">@Jane Smith</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("should open a dropdown menu when I type '@'", () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
})
|
||||
|
||||
it('should display the correct options in the dropdown menu', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button').should('have.length', 5)
|
||||
cy.get('.dropdown-menu button:nth-child(1)').should('contain.text', 'Lea Thompson').and('have.class', 'is-selected')
|
||||
cy.get('.dropdown-menu button:nth-child(2)').should('contain.text', 'Cyndi Lauper')
|
||||
cy.get('.dropdown-menu button:nth-child(3)').should('contain.text', 'Tom Cruise')
|
||||
cy.get('.dropdown-menu button:nth-child(4)').should('contain.text', 'Madonna')
|
||||
cy.get('.dropdown-menu button:nth-child(5)').should('contain.text', 'Jerry Hall')
|
||||
})
|
||||
|
||||
it('should insert Cyndi Lauper mention when clicking on her option', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button:nth-child(2)').contains('Cyndi Lauper').click()
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Cyndi Lauper" data-mention-suggestion-char="@" contenteditable="false">@Cyndi Lauper</span>',
|
||||
)
|
||||
})
|
||||
|
||||
it('should close the dropdown menu when I move the cursor outside the editor', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{moveToStart}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
})
|
||||
|
||||
it('should close the dropdown menu when I press the exit key', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{esc}')
|
||||
cy.get('.dropdown-menu').should('not.exist')
|
||||
})
|
||||
|
||||
it('should insert Tom Cruise when selecting his option with the arrow keys and pressing the enter key', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').type('{downarrow}{downarrow}')
|
||||
cy.get('.dropdown-menu button:nth-child(3)').should('have.class', 'is-selected')
|
||||
cy.get('.tiptap').type('{enter}')
|
||||
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Tom Cruise" data-mention-suggestion-char="@" contenteditable="false">@Tom Cruise</span>',
|
||||
)
|
||||
})
|
||||
|
||||
it('should show a "No result" message when I search for an option that is not in the list', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@nonexistent')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu').should('contain.text', 'No result')
|
||||
})
|
||||
|
||||
it('should not hide the dropdown or insert any mention if I search for an option that is not in the list and hit enter', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@nonexistent')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu').should('contain.text', 'No result')
|
||||
cy.get('.tiptap').type('{enter}')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.tiptap').should('have.text', '@nonexistent')
|
||||
cy.get('.tiptap span.mention').should('not.exist')
|
||||
})
|
||||
|
||||
it('should only show the Madonna option in the dropdown when I type "@mado"', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@mado')
|
||||
cy.get('.dropdown-menu').should('exist')
|
||||
cy.get('.dropdown-menu button').should('have.length', 1)
|
||||
cy.get('.dropdown-menu button:nth-child(1)').should('contain.text', 'Madonna')
|
||||
})
|
||||
|
||||
it('should insert Madonna when I type "@mado" and hit enter', () => {
|
||||
cy.get('.tiptap').type('{selectall}{backspace}@mado{enter}')
|
||||
cy.get('.tiptap').should(
|
||||
'contain.html',
|
||||
'<span class="mention" data-type="mention" data-id="Madonna" data-mention-suggestion-char="@" contenteditable="false">@Madonna</span>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extensions@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-character-count",
|
||||
"description": "font family extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extensions@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-dropcursor",
|
||||
"description": "dropcursor extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extensions@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-focus",
|
||||
"description": "focus extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
@ -31,10 +31,10 @@
|
||||
"dist"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@tiptap/extensions": "3.0.0-beta.3"
|
||||
"@tiptap/extensions": "3.0.0-beta.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tiptap/extensions": "3.0.0-beta.3"
|
||||
"@tiptap/extensions": "3.0.0-beta.4"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extensions@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-gapcursor",
|
||||
"description": "gapcursor extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extensions@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-history",
|
||||
"description": "history extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-list@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-list-item",
|
||||
"description": "list item extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-list@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-list-keymap",
|
||||
"description": "list keymap extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extensions@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-placeholder",
|
||||
"description": "placeholder extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-table@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-table-cell",
|
||||
"description": "table cell extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-table@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-table-header",
|
||||
"description": "table cell extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-table@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-table-row",
|
||||
"description": "table row extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-list@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-task-item",
|
||||
"description": "task item extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-list@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-task-list",
|
||||
"description": "task list extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,16 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Major Changes
|
||||
|
||||
- 5e957e5: This resolves in issue with SSR where the isDestroyed property could not be read while in SSR
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9f207a6: Fixes a bug where you could not unregister multiple plugins.
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/core",
|
||||
"description": "headless rich text editor",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -287,6 +287,7 @@ export class Editor extends EventEmitter<EditorEvents> {
|
||||
composing: false,
|
||||
dragging: null,
|
||||
editable: true,
|
||||
isDestroyed: false,
|
||||
} as EditorView,
|
||||
{
|
||||
get: (obj, key) => {
|
||||
@ -361,7 +362,7 @@ export class Editor extends EventEmitter<EditorEvents> {
|
||||
const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key
|
||||
|
||||
// @ts-ignore
|
||||
plugins = prevPlugins.filter(plugin => !plugin.key.startsWith(name))
|
||||
plugins = plugins.filter(plugin => !plugin.key.startsWith(name))
|
||||
})
|
||||
|
||||
if (prevPlugins.length === plugins.length) {
|
||||
@ -717,8 +718,7 @@ export class Editor extends EventEmitter<EditorEvents> {
|
||||
* Check if the editor is already destroyed.
|
||||
*/
|
||||
public get isDestroyed(): boolean {
|
||||
// @ts-ignore
|
||||
return !this.view?.docView
|
||||
return this.editorView?.isDestroyed ?? true
|
||||
}
|
||||
|
||||
public $node(selector: string, attributes?: { [key: string]: any }): NodePos | null {
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-blockquote",
|
||||
"description": "blockquote extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-bold",
|
||||
"description": "bold extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-bubble-menu",
|
||||
"description": "bubble-menu extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-list@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-bullet-list",
|
||||
"description": "bullet list extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,15 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/extension-code-block@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-code-block-lowlight",
|
||||
"description": "code block extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-code-block",
|
||||
"description": "code block extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-code",
|
||||
"description": "code extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,15 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f43b2e5: Use newer y-prosemirror version to resolve dependency chaos
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-collaboration-caret",
|
||||
"description": "collaboration caret extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
@ -33,12 +33,12 @@
|
||||
"devDependencies": {
|
||||
"@tiptap/core": "workspace:*",
|
||||
"@tiptap/pm": "workspace:*",
|
||||
"@tiptap/y-tiptap": "^2.0.0"
|
||||
"@tiptap/y-tiptap": "^3.0.0-beta.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tiptap/core": "workspace:*",
|
||||
"@tiptap/pm": "workspace:*",
|
||||
"@tiptap/y-tiptap": "^2.0.0"
|
||||
"@tiptap/y-tiptap": "^3.0.0-beta.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,5 +1,15 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f43b2e5: Use newer y-prosemirror version to resolve dependency chaos
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-collaboration",
|
||||
"description": "collaboration extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
@ -33,12 +33,12 @@
|
||||
"devDependencies": {
|
||||
"@tiptap/core": "workspace:*",
|
||||
"@tiptap/pm": "workspace:*",
|
||||
"@tiptap/y-tiptap": "^2.0.0"
|
||||
"@tiptap/y-tiptap": "^3.0.0-beta.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tiptap/core": "workspace:*",
|
||||
"@tiptap/pm": "workspace:*",
|
||||
"@tiptap/y-tiptap": "^2.0.0",
|
||||
"@tiptap/y-tiptap": "^3.0.0-beta.3",
|
||||
"yjs": "^13"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-text-style@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-color",
|
||||
"description": "text color extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-document",
|
||||
"description": "document extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-floating-menu",
|
||||
"description": "floating-menu extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @tiptap/extension-text-style@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-font-family",
|
||||
"description": "font family extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-hard-break",
|
||||
"description": "hard break extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-heading",
|
||||
"description": "heading extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-highlight",
|
||||
"description": "highlight extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-horizontal-rule",
|
||||
"description": "horizontal rule extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-image",
|
||||
"description": "image extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-italic",
|
||||
"description": "italic extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-link",
|
||||
"description": "link extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-list",
|
||||
"description": "List extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
@ -1,5 +1,19 @@
|
||||
# Change Log
|
||||
|
||||
## 3.0.0-beta.4
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 68034ab: Support multiple triggers in Mention extension
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e957e5]
|
||||
- Updated dependencies [9f207a6]
|
||||
- @tiptap/core@3.0.0-beta.4
|
||||
- @tiptap/suggestion@3.0.0-beta.4
|
||||
- @tiptap/pm@3.0.0-beta.4
|
||||
|
||||
## 3.0.0-beta.3
|
||||
|
||||
### Patch Changes
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@tiptap/extension-mention",
|
||||
"description": "mention extension for tiptap",
|
||||
"version": "3.0.0-beta.3",
|
||||
"version": "3.0.0-beta.4",
|
||||
"homepage": "https://tiptap.dev",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user