Merge branch 'main' of github.com:ueberdosis/tiptap-next into main

This commit is contained in:
Hans Pagel
2021-01-20 11:41:10 +01:00
38 changed files with 1309 additions and 365 deletions

View File

@@ -25,6 +25,7 @@
"remark-toc": "^7.0.0",
"remixicon": "^2.5.0",
"simplify-js": "^1.2.4",
"tippy.js": "^6.2.7",
"vue-github-button": "^1.1.2",
"vue-live": "^1.16.0",
"y-indexeddb": "^9.0.6",

View File

@@ -1,5 +1,5 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueRenderer } from '@tiptap/vue'
import { VueNodeViewRenderer } from '@tiptap/vue'
import Component from './Component.vue'
export default Node.create({
@@ -30,6 +30,6 @@ export default Node.create({
},
addNodeView() {
return VueRenderer(Component)
return VueNodeViewRenderer(Component)
},
})

View File

@@ -1,5 +1,5 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueRenderer } from '@tiptap/vue'
import { VueNodeViewRenderer } from '@tiptap/vue'
import Component from './Component.vue'
export default Node.create({
@@ -24,6 +24,6 @@ export default Node.create({
},
addNodeView() {
return VueRenderer(Component)
return VueNodeViewRenderer(Component)
},
})

View File

@@ -1,5 +1,5 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueRenderer } from '@tiptap/vue'
import { VueNodeViewRenderer } from '@tiptap/vue'
import Component from './Component.vue'
export default Node.create({
@@ -22,6 +22,6 @@ export default Node.create({
},
addNodeView() {
return VueRenderer(Component)
return VueNodeViewRenderer(Component)
},
})

View File

@@ -0,0 +1,112 @@
<template>
<div class="items">
<button
class="item"
:class="{ 'is-selected': index === selectedIndex }"
v-for="(item, index) in items"
:key="index"
@click="selectItem(index)"
>
{{ item }}
</button>
</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" scoped>
.items {
position: relative;
border-radius: 0.25rem;
background: white;
color: rgba(black, 0.8);
overflow: hidden;
font-size: 0.9rem;
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.1),
0px 10px 20px rgba(0, 0, 0, 0.1),
;
}
.item {
display: block;
width: 100%;
text-align: left;
background: transparent;
border: none;
padding: 0.2rem 0.5rem;
&.is-selected,
&:hover {
color: #A975FF;
background: rgba(#A975FF, 0.1);
}
}
</style>

View File

@@ -0,0 +1,5 @@
context('/api/nodes/mention', () => {
before(() => {
cy.visit('/api/nodes/mention')
})
})

View File

@@ -0,0 +1,100 @@
<template>
<div v-if="editor">
<editor-content :editor="editor" />
</div>
</template>
<script>
import tippy from 'tippy.js'
import { Editor, EditorContent, VueRenderer } from '@tiptap/vue'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import Mention from '@tiptap/extension-mention'
import MentionList from './MentionList'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
}
},
mounted() {
this.editor = new Editor({
extensions: [
Document,
Paragraph,
Text,
Mention.configure({
HTMLAttributes: {
class: 'mention',
},
suggestionOptions: {
items: query => {
return ['Hans', 'Philipp', 'Kris'].filter(item => item.startsWith(query))
},
render: () => {
let component
let popup
return {
onStart: props => {
component = new VueRenderer(MentionList, {
parent: this,
propsData: props,
})
popup = tippy('body', {
getReferenceClientRect: props.clientRect,
appendTo: () => document.body,
content: component.element,
showOnCreate: true,
interactive: true,
trigger: 'manual',
placement: 'top-start',
})
},
onUpdate(props) {
component.updateProps(props)
popup[0].setProps({
getReferenceClientRect: props.clientRect,
})
},
onKeyDown(props) {
return component.vm.onKeyDown(props)
},
onExit() {
popup[0].destroy()
component.destroy()
},
}
},
},
}),
],
content: `
<p>Hello <span data-mention="Hans"></span> and <span data-mention="Philipp"></span> and <span data-mention="Kris"></span>!</p>
`,
})
},
beforeDestroy() {
this.editor.destroy()
},
}
</script>
<style lang="scss">
.mention {
color: #A975FF;
background-color: rgba(#A975FF, 0.1);
border-radius: 0.3rem;
padding: 0.1rem 0.3rem;
}
</style>

View File

@@ -147,6 +147,7 @@ Have a look at all of the core commands listed below. They should give you a goo
| .lift() | Removes an existing wrap. |
| .liftEmptyBlock() | Lift block if empty. |
| .newlineInCode() | Add a newline character in code. |
| .replace() | Replaces text with a node within a range. |
| .resetNodeAttributes() | Resets all node attributes to the default value. |
| .selectParentNode() | Select the parent node. |
| .setMark() | Add a mark with new attributes. |

View File

@@ -1,14 +0,0 @@
# Suggestion
:::pro Fund the development 💖
We need your support to maintain, update, support and develop tiptap 2. If youre waiting for this extension, [become a sponsor and fund open source](/sponsor).
:::
TODO
- mentions (as text or as/with user ID)
- hashtags (as text)
- emojis (input rule with an autocomplete popup)
- commands (can only be triggered at the beginning of a line, should trigger custom commands)
- snippets (should be able to insert multiple paragraphs)
- variables (should replaced when copied to external sources)

View File

@@ -1,7 +1,16 @@
# Mention
:::pro Fund the development 💖
We need your support to maintain, update, support and develop tiptap 2. If youre waiting for this extension, [become a sponsor and fund open source](/sponsor).
:::
## Installation
```bash
# with npm
npm install @tiptap/extension-mention
TODO
# with Yarn
yarn add @tiptap/extension-mention
```
## Source code
[packages/extension-mention/](https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-mention/)
## Usage
<demo name="Nodes/Mention" />

View File

@@ -7,7 +7,7 @@ Node views are the best thing since sliced bread, at least if youre a fan of
<!-- ```js
import { Node } from '@tiptap/core'
import { VueRenderer } from '@tiptap/vue'
import { VueNodeViewRenderer } from '@tiptap/vue'
import Component from './Component.vue'
export default Node.create({
@@ -83,12 +83,12 @@ https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-task-item
```js
import { Node } from '@tiptap/core'
import { VueRenderer } from '@tiptap/vue'
import { VueNodeViewRenderer } from '@tiptap/vue'
import Component from './Component.vue'
export default Node.create({
addNodeView() {
return VueRenderer(Component)
return VueNodeViewRenderer(Component)
},
})
```

View File

@@ -174,9 +174,6 @@
link: /api/extensions/gapcursor
- title: History
link: /api/extensions/history
- title: Suggestion
link: /api/extensions/suggestion
type: draft
- title: TextAlign
link: /api/extensions/text-align
- title: Typography