add more advance composer feature
This commit is contained in:
@@ -1,27 +1,29 @@
|
||||
<script setup>
|
||||
import { inject, ref } from "vue";
|
||||
import store from "@/store/store";
|
||||
import { BubbleMenu, useEditor, EditorContent, FloatingMenu } from "@tiptap/vue-3";
|
||||
import imapAPI from "@/services/imapAPI";
|
||||
import Underline from "@tiptap/extension-underline";
|
||||
import Bold from "@tiptap/extension-bold";
|
||||
import Document from "@tiptap/extension-document";
|
||||
import Paragraph from "@tiptap/extension-paragraph";
|
||||
import Text from "@tiptap/extension-text";
|
||||
import Highlight from "@tiptap/extension-highlight";
|
||||
import Italic from "@tiptap/extension-italic";
|
||||
import Link from "@tiptap/extension-link";
|
||||
import Strike from "@tiptap/extension-strike";
|
||||
import History from "@tiptap/extension-history";
|
||||
import TextAlign from "@tiptap/extension-text-align";
|
||||
import OrderedList from "@tiptap/extension-ordered-list";
|
||||
import bulletList from "@tiptap/extension-bullet-list";
|
||||
import HardBreak from "@tiptap/extension-hard-break";
|
||||
import heading from "@tiptap/extension-heading";
|
||||
import Image from "@tiptap/extension-image";
|
||||
import TaskList from "@tiptap/extension-task-list";
|
||||
import SvgLoader from "@/components/utils/SvgLoader.vue";
|
||||
|
||||
import { BubbleMenu, useEditor, EditorContent } from "@tiptap/vue-3";
|
||||
import Document from "@tiptap/extension-document";
|
||||
import Text from "@tiptap/extension-text";
|
||||
import Paragraph from "@tiptap/extension-paragraph";
|
||||
import HardBreak from "@tiptap/extension-hard-break";
|
||||
import History from "@tiptap/extension-history";
|
||||
import Bold from "@tiptap/extension-bold";
|
||||
import Italic from "@tiptap/extension-italic";
|
||||
import Strike from "@tiptap/extension-strike";
|
||||
import Underline from "@tiptap/extension-underline";
|
||||
import Highlight from "@tiptap/extension-highlight";
|
||||
import Link from "@tiptap/extension-link";
|
||||
import Heading from "@tiptap/extension-heading";
|
||||
import Image from "@tiptap/extension-image";
|
||||
import TextAlign from "@tiptap/extension-text-align";
|
||||
import ListItem from "@tiptap/extension-list-item";
|
||||
import OrderedList from "@tiptap/extension-ordered-list";
|
||||
import BulletList from "@tiptap/extension-bullet-list";
|
||||
|
||||
// todo task list
|
||||
// todo style link
|
||||
// todo link and drop cursor
|
||||
// todo mentions
|
||||
@@ -37,18 +39,25 @@ const editor = useEditor({
|
||||
depth: 10,
|
||||
}),
|
||||
// marks
|
||||
Bold,
|
||||
Italic,
|
||||
Strike,
|
||||
Underline,
|
||||
Link,
|
||||
Bold,
|
||||
Strike,
|
||||
Italic,
|
||||
// nodes
|
||||
Highlight.configure({
|
||||
multicolor: true,
|
||||
}),
|
||||
Heading.configure({
|
||||
level: [2, 3, 4],
|
||||
}),
|
||||
Image,
|
||||
TextAlign.configure({
|
||||
types: ["heading", "paragraph"],
|
||||
}),
|
||||
ListItem,
|
||||
OrderedList,
|
||||
BulletList,
|
||||
],
|
||||
content: `
|
||||
<p>
|
||||
@@ -84,63 +93,126 @@ function sendMessage() {
|
||||
</script>
|
||||
<!-- todo tooltip -->
|
||||
<template>
|
||||
<div class="main">
|
||||
<div v-if="editor">
|
||||
<bubble-menu class="bubble-menu" :tippy-options="{ duration: 100 }" :editor="editor">
|
||||
<div v-if="editor">
|
||||
<div id="options" v-if="showOptions">
|
||||
<span class="category">
|
||||
<SvgLoader
|
||||
svg="bold"
|
||||
@click="editor.chain().focus().toggleBold().run()"
|
||||
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="italic"
|
||||
@click="editor.chain().focus().toggleItalic().run()"
|
||||
:class="[{ 'is-active': editor.isActive('italic') }, 'editorOption']"
|
||||
v-tooltip="'Italic'"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="strikethrough"
|
||||
@click="editor.chain().focus().toggleStrike().run()"
|
||||
:class="[{ 'is-active': editor.isActive('strike') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="underline"
|
||||
@click="editor.chain().focus().toggleUnderline().run()"
|
||||
:class="[{ 'is-active': editor.isActive('underline') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="font-color"
|
||||
@click="editor.commands.toggleHighlight({ color: '#ffcc00' })"
|
||||
:class="[{ 'is-active': editor.isActive('highlight') }, 'editorOption']"
|
||||
/>
|
||||
</bubble-menu>
|
||||
|
||||
<floating-menu class="floating-menu" :tippy-options="{ duration: 100 }" :editor="editor">
|
||||
<button
|
||||
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
|
||||
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
|
||||
>
|
||||
H1
|
||||
</button>
|
||||
<button
|
||||
svg="h-2"
|
||||
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
|
||||
:class="{ 'is-active': editor.isActive('heading', { level: 2 }) }"
|
||||
>
|
||||
H2
|
||||
</button>
|
||||
<button
|
||||
:class="[{ 'is-active': editor.isActive({ level: 2 }) }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="h-3"
|
||||
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
|
||||
:class="[{ 'is-active': editor.isActive({ level: 3 }) }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="h-4"
|
||||
@click="editor.chain().focus().toggleHeading({ level: 4 }).run()"
|
||||
:class="[{ 'is-active': editor.isActive({ level: 4 }) }, 'editorOption']"
|
||||
/>
|
||||
</span>
|
||||
<!-- <SvgLoader
|
||||
svg="link"
|
||||
@click="editor.chain().focus().toggleBold().run()"
|
||||
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
|
||||
/> -->
|
||||
<span class="category">
|
||||
<SvgLoader
|
||||
svg="list-ordered"
|
||||
@click="editor.chain().focus().toggleOrderedList().run()"
|
||||
:class="[{ 'is-active': editor.isActive('orderedList') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="list-unordered"
|
||||
@click="editor.chain().focus().toggleBulletList().run()"
|
||||
:class="{ 'is-active': editor.isActive('bulletList') }"
|
||||
>
|
||||
Bullet List
|
||||
</button>
|
||||
</floating-menu>
|
||||
</div>
|
||||
:class="[{ 'is-active': editor.isActive('bulletList') }, 'editorOption']"
|
||||
/>
|
||||
</span>
|
||||
<span class="category">
|
||||
<SvgLoader
|
||||
svg="align-left"
|
||||
@click="editor.chain().focus().setTextAlign('left').run()"
|
||||
:class="[{ 'is-active': editor.isActive({ textAlign: 'left' }) }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="align-center"
|
||||
@click="editor.chain().focus().setTextAlign('center').run()"
|
||||
:class="[{ 'is-active': editor.isActive({ textAlign: 'center' }) }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="align-right"
|
||||
@click="editor.chain().focus().setTextAlign('right').run()"
|
||||
:class="[{ 'is-active': editor.isActive({ textAlign: 'right' }) }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="align-justify"
|
||||
@click="editor.chain().focus().setTextAlign('justify').run()"
|
||||
:class="[{ 'is-active': editor.isActive({ textAlign: 'justify' }) }, 'editorOption']"
|
||||
/>
|
||||
</span>
|
||||
|
||||
<div class="editor">
|
||||
<div class="options" v-if="showOptions">heruipaghruie</div>
|
||||
<editor-content class="editorContent" :editor="editor" aria-expanded="false" />
|
||||
<!-- <SvgLoader
|
||||
svg="font-color"
|
||||
@click="editor.chain().focus().toggleBold().run()"
|
||||
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="paint-fill"
|
||||
@click="editor.chain().focus().toggleBold().run()"
|
||||
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
|
||||
/> -->
|
||||
<span class="category">
|
||||
<SvgLoader
|
||||
svg="indent-increase"
|
||||
@click="!$event.disabled ? editor.chain().focus().sinkListItem('listItem').run() : ''"
|
||||
:class="[{ disabled: !editor.can().sinkListItem('listItem') }, 'editorOption']"
|
||||
:isDisabled="!editor.can().sinkListItem('listItem')"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="indent-decrease"
|
||||
@click="!$event.disabled ? editor.chain().focus().liftListItem('listItem').run() : ''"
|
||||
:class="[{ disabled: !editor.can().liftListItem('listItem') }, 'editorOption']"
|
||||
:isDisabled="!editor.can().liftListItem('listItem')"
|
||||
/>
|
||||
</span>
|
||||
<!-- <SvgLoader
|
||||
svg="image-add-line"
|
||||
@click="editor.chain().focus().toggleBold().run()"
|
||||
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
|
||||
/> -->
|
||||
</div>
|
||||
<bubble-menu class="bubble-menu" :tippy-options="{ duration: 100 }" :editor="editor">
|
||||
<SvgLoader
|
||||
svg="bold"
|
||||
@click="editor.chain().focus().toggleBold().run()"
|
||||
:class="[{ 'is-active': editor.isActive('bold') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="italic"
|
||||
@click="editor.chain().focus().toggleItalic().run()"
|
||||
:class="[{ 'is-active': editor.isActive('italic') }, 'editorOption']"
|
||||
v-tooltip="'Italic'"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="strikethrough"
|
||||
@click="editor.chain().focus().toggleStrike().run()"
|
||||
:class="[{ 'is-active': editor.isActive('strike') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="underline"
|
||||
@click="editor.chain().focus().toggleUnderline().run()"
|
||||
:class="[{ 'is-active': editor.isActive('underline') }, 'editorOption']"
|
||||
/>
|
||||
<SvgLoader
|
||||
svg="font-color"
|
||||
@click="editor.commands.toggleHighlight({ color: '#ffcc00' })"
|
||||
:class="[{ 'is-active': editor.isActive('highlight') }, 'editorOption']"
|
||||
/>
|
||||
</bubble-menu>
|
||||
</div>
|
||||
<div class="main">
|
||||
<editor-content class="editor" :editor="editor" aria-expanded="false" />
|
||||
<div class="actions">
|
||||
<SvgLoader class="sendMessage" svg="send-plane-line" @click="sendMessage()" />
|
||||
<SvgLoader
|
||||
@@ -152,15 +224,9 @@ function sendMessage() {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.ProseMirror {
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
<style>
|
||||
.ProseMirror:focus {
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -168,52 +234,54 @@ function sendMessage() {
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
padding: 0 10px 10px 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--secondary-background);
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.options {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
.editorContent {
|
||||
flex: 1;
|
||||
background-color: var(--secondary-background);
|
||||
border-radius: 10px;
|
||||
padding: 0 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.bubble-menu {
|
||||
.bubble-menu,
|
||||
#options,
|
||||
.category {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 2px;
|
||||
background-color: var(--primary-background);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
#options {
|
||||
margin: 2px 0 4px 11px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.bubble-menu,
|
||||
.category {
|
||||
outline: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.editorOption {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
.editorOption {
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover,
|
||||
&.is-active {
|
||||
background-color: var(--selected);
|
||||
}
|
||||
|
||||
::v-deep img {
|
||||
filter: var(--svg-primary-text);
|
||||
padding: 1px;
|
||||
}
|
||||
&:hover,
|
||||
&.is-active {
|
||||
background-color: var(--selected);
|
||||
}
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -225,7 +293,6 @@ function sendMessage() {
|
||||
border-radius: 6px;
|
||||
|
||||
::v-deep img {
|
||||
filter: var(--svg-primary-text);
|
||||
padding: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,22 @@ import { defineProps } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
svg: { type: String, required: true },
|
||||
isDisabled: Boolean,
|
||||
});
|
||||
|
||||
const pathSvg = () => require(`@/assets/svg/${props.svg}.svg`);
|
||||
console.log(props.isDisabled);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<img class="it-has-a-tooltip" :src="pathSvg()" />
|
||||
<img :disabled="props.isDisabled" :src="pathSvg()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
img {
|
||||
filter: var(--svg-primary-text);
|
||||
padding: 1px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user