auto imports
This commit is contained in:
147
src/components/Note/NoteEditor.vue
Normal file
147
src/components/Note/NoteEditor.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<script setup lang="ts">
|
||||
import CKEditor from '@/ckeditor/CKEditor'
|
||||
import BalloonEditor from '@ckeditor/ckeditor5-editor-balloon/src/ballooneditor'
|
||||
import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials'
|
||||
import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold'
|
||||
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic'
|
||||
import UnderlinePlugin from '@ckeditor/ckeditor5-basic-styles/src/underline'
|
||||
import StrikethroughPlugin from '@ckeditor/ckeditor5-basic-styles/src/strikethrough'
|
||||
import LinkPlugin from '@ckeditor/ckeditor5-link/src/link'
|
||||
import HeadingPlugin from '@ckeditor/ckeditor5-heading/src/heading'
|
||||
import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph'
|
||||
import ListPlugin from '@ckeditor/ckeditor5-list/src/list'
|
||||
import AutoformatPlugin from '@ckeditor/ckeditor5-autoformat/src/autoformat'
|
||||
import ContextedPlugin from '@/ckeditor/ContextedPlugin'
|
||||
import { mdToHtml } from '@/utils/markdown'
|
||||
import { activeNote, getNoteByTitle } from '@/composables/useNotes'
|
||||
import Autocomplete from '@/components/Autocomplete.vue'
|
||||
|
||||
const props = defineProps<{ note: Note }>()
|
||||
|
||||
const html = mdToHtml(props.note.content)
|
||||
|
||||
const editor = BalloonEditor
|
||||
const editorData = html
|
||||
const editorConfig = {
|
||||
plugins: [
|
||||
EssentialsPlugin,
|
||||
BoldPlugin,
|
||||
ItalicPlugin,
|
||||
UnderlinePlugin,
|
||||
StrikethroughPlugin,
|
||||
LinkPlugin,
|
||||
HeadingPlugin,
|
||||
ParagraphPlugin,
|
||||
ListPlugin,
|
||||
AutoformatPlugin,
|
||||
ContextedPlugin,
|
||||
],
|
||||
|
||||
toolbar: {
|
||||
items: [
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'strikethrough',
|
||||
'link',
|
||||
'undo',
|
||||
'redo',
|
||||
'heading',
|
||||
'bulletedList',
|
||||
'numberedList',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const editorElement = ref<HTMLInputElement | null>(null)
|
||||
|
||||
const handleClick = ({ data }: { data: any }) => {
|
||||
const noteTitle = data.domTarget.textContent as string
|
||||
const note = getNoteByTitle(noteTitle)
|
||||
if (note) activeNote.value = note
|
||||
}
|
||||
|
||||
const autocompleteRef = ref<InstanceType<typeof Autocomplete> | null>(null)
|
||||
const showAutocomplete = ref(false)
|
||||
const autocompleteStyle = ref({})
|
||||
const autocompleteText = ref('')
|
||||
const autocompleteReverse = ref(false)
|
||||
|
||||
const handleAutocomplete = async (event: AutocompleteEvent) => {
|
||||
const position = event.position
|
||||
if (position && editorElement.value) {
|
||||
const rect: any = editorElement.value?.getBoundingClientRect()
|
||||
const lineHeight = parseFloat(
|
||||
window.getComputedStyle(event.domElement || editorElement.value).lineHeight
|
||||
)
|
||||
autocompleteStyle.value = {
|
||||
top: `${position.top - rect.top + lineHeight}px`,
|
||||
left: `${position.left - rect.left}px`,
|
||||
}
|
||||
}
|
||||
autocompleteText.value = event.autocompleteText || ''
|
||||
showAutocomplete.value = event.show
|
||||
await nextTick()
|
||||
const autocompleteElem = autocompleteRef.value?.$el
|
||||
const autocompleteRect = autocompleteRef.value?.$el.getBoundingClientRect()
|
||||
const editorRect = editorElement.value?.getBoundingClientRect()
|
||||
if (
|
||||
autocompleteElem &&
|
||||
autocompleteRect &&
|
||||
editorRect &&
|
||||
autocompleteRect.bottom > editorRect.bottom
|
||||
) {
|
||||
const autocompleteHeight = parseFloat(
|
||||
window.getComputedStyle(autocompleteElem).height
|
||||
)
|
||||
autocompleteStyle.value = {
|
||||
...autocompleteStyle.value,
|
||||
top: `${position.top - editorRect.top - autocompleteHeight}px`,
|
||||
}
|
||||
autocompleteReverse.value = true
|
||||
} else {
|
||||
autocompleteReverse.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleContextedKeypress = (event: any) => {
|
||||
if (autocompleteRef.value) autocompleteRef.value.handleKeypress(event)
|
||||
}
|
||||
|
||||
const createLink = (link: string) => {
|
||||
console.log(link)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="relative" ref="editorElement">
|
||||
<CKEditor
|
||||
class="h-full text-[110%] font-light"
|
||||
:editor="editor"
|
||||
v-model="editorData"
|
||||
:config="editorConfig"
|
||||
@click="handleClick"
|
||||
@contexted-link-autocomplete="handleAutocomplete"
|
||||
@contexted-keypress="handleContextedKeypress"
|
||||
></CKEditor>
|
||||
<Autocomplete
|
||||
v-if="showAutocomplete"
|
||||
ref="autocompleteRef"
|
||||
:autocomplete-text="autocompleteText"
|
||||
:style="autocompleteStyle"
|
||||
@create-link="createLink"
|
||||
class="absolute w-[250px]"
|
||||
:class="autocompleteReverse && 'flex-col-reverse'"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.ck-content {
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.ck-content a[data-contexted-link='true'] {
|
||||
@apply cursor-pointer font-semibold text-primary hover:bg-gray-200;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user