feat: add draggable block

This commit is contained in:
Seviche CC 2023-04-01 19:11:42 +08:00
parent 5d1cf237b7
commit f24038cb2d
Signed by: SevicheCC
GPG key ID: C577000000000000
4 changed files with 108 additions and 17 deletions

2
components.d.ts vendored
View file

@ -11,6 +11,8 @@ declare module '@vue/runtime-core' {
export interface GlobalComponents {
BubbleMenu: typeof import('./src/components/Tiptap/BubbleMenu.vue')['default']
CommandsList: typeof import('./src/components/Tiptap/CommandsList.vue')['default']
DragableHandle: typeof import('./src/components/Tiptap/DragableHandle.vue')['default']
DragableNode: typeof import('./src/components/Tiptap/DragableNode.vue')['default']
Editor: typeof import('./src/components/Tiptap/Editor.vue')['default']
}
}

View file

@ -0,0 +1,56 @@
<script>
import { NodeViewContent, NodeViewWrapper, nodeViewProps } from '@tiptap/vue-3'
export default {
components: {
NodeViewWrapper,
NodeViewContent,
},
props: nodeViewProps,
}
</script>
<template>
<NodeViewWrapper class="draggable-item">
<div
class="drag-handle"
contenteditable="false"
draggable="true"
data-drag-handle
/>
<NodeViewContent class="content" />
</NodeViewWrapper>
</template>
<style lang="scss">
.draggable-item {
display: flex;
padding: 0.5rem;
margin: 0.5rem 0;
border-radius: 0.5rem;
background: white;
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.05),
0px 10px 20px rgba(0, 0, 0, 0.1),
;
.drag-handle {
flex: 0 0 auto;
position: relative;
width: 1rem;
height: 1rem;
top: 0.3rem;
margin-right: 0.5rem;
cursor: grab;
background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16"><path fill-opacity="0.2" d="M4 14c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zM2 6C.9 6 0 6.9 0 8s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6C.9 0 0 .9 0 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /></svg>');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.content {
flex: 1 1 auto;
}
}
</style>

View file

@ -0,0 +1,34 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'
import DragableHandle from './DragableHandle.vue'
export default Node.create({
name: 'draggableItem',
group: 'block',
content: 'block+',
draggable: true,
parseHTML() {
return [
{
tag: 'div[data-type="draggable-item"]',
},
]
},
renderHTML({ HTMLAttributes }) {
return [
'div',
mergeAttributes(HTMLAttributes, { 'data-type': 'draggable-item' }),
0,
]
},
addNodeView() {
return VueNodeViewRenderer(DragableHandle)
},
})

View file

@ -22,6 +22,7 @@ import rust from 'highlight.js/lib/languages/rust'
import suggestion from './suggestion'
import Commands from './commands'
import DraggableItem from './DraggableItem'
lowlight.registerLanguage('html', html)
lowlight.registerLanguage('css', css)
@ -36,26 +37,24 @@ lowlight.registerLanguage('go', go)
lowlight.registerLanguage('rs', rust)
const editor = useEditor({
content: `<p>
Thats a boring paragraph followed by a fenced code block:
</p>
<pre><code>for (var i=1; i <= 20; i++)
{
if (i % 15 == 0)
console.log("FizzBuzz");
else if (i % 3 == 0)
console.log("Fizz");
else if (i % 5 == 0)
console.log("Buzz");
else
console.log(i);
}</code></pre>
<p>
Press Command/Ctrl + Enter to leave the fenced code block and continue typing in boring paragraphs.
</p>`,
content: `<p>This is a boring paragraph.</p>
<div data-type="draggable-item">
<p>Followed by a fancy draggable item.</p>
</div>
<div data-type="draggable-item">
<p>And another draggable item.</p>
<div data-type="draggable-item">
<p>And a nested one.</p>
<div data-type="draggable-item">
<p>But can we go deeper?</p>
</div>
</div>
</div>
<p>Lets finish with a boring paragraph.</p>`,
extensions: [
StarterKit,
Typography,
DraggableItem,
Link.configure({
openOnClick: false,
}),