You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
 
 
 
 

213 lines
7.2 KiB

<script setup>
import { ref, onMounted, onBeforeUnmount, defineProps, defineEmits } from 'vue'
import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import TextAlign from '@tiptap/extension-text-align'
import Underline from '@tiptap/extension-underline'
import Highlight from '@tiptap/extension-highlight'
import TextStyle from '@tiptap/extension-text-style'
import Mention from '@tiptap/extension-mention'
import Color from '@tiptap/extension-color'
import Link from '@tiptap/extension-link'
import Placeholder from '@tiptap/extension-placeholder'
import Typography from '@tiptap/extension-typography'
import CharacterCount from '@tiptap/extension-character-count'
import Image from '@tiptap/extension-image'
import TaskList from '@tiptap/extension-task-list'
import TaskItem from '@tiptap/extension-task-item'
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import Tabs from './Tabs.vue'
import TextTab from './Tabs/TextTab.vue'
import BlockTab from './Tabs/BlockTab.vue'
import ListTab from './Tabs/ListTab.vue'
import MediaTab from './Tabs/MediaTab.vue'
import TableTab from './Tabs/TableTab.vue'
import HistoryTab from './Tabs/HistoryTab.vue'
import BubbleMenu from './BubbleMenu.vue'
import FloatingMenu from './FloatingMenu.vue'
const props = defineProps({
content: {
type: Object || String,
default: `
<h2>
Présentation du groupe
</h2>
<p>
Notre groupe compte aujourd’hui près de 40 membres. Ils et elles sont réparti·es répartis dans quatre différentes branches :
</p>
<ul>
<li>
<b>Branche Louveteaux (7 – 11 ans) :</b>
<p>
Dès 7 ans, un enfant peut participer à nos activités en tant que louveteaux ou louvette.Réparti·es en sizaines formant ainsi une meute, les louveteaux et les louvettes découvrent le scoutisme à travers l’histoire du livre de la jungle et réalisent des jeux, bricolages ou autres activités adaptées à leur âge.
</p>
</li>
<li>
<b>Branche Eclais (11 – 15 ans) :</b>
<p>
A partir de 11 ans, les jeunes de notre groupe font partie de la branche éclais. Ils et elles sont séparé·es en patrouilles qui forment une troupe. Durant les activités préparées et encadrées par les responsables, ils et elles apprennent à devenir autonome en approfondissant certains domaines comme les techniques de corde, topographie, cuisine, etc.
Les plus grand·es éclais ont également la possibilité d’organiser eux·elles-mêmes des activités ou même des petits camps pour leurs patrouilles. Les responsables sont là pour leur expliquer comment planifier ces activités et encadrer des enfants plus jeunes.
</p>
</li>
</ul>
<p>
Envie de faire découvrir le scoutisme à votre enfant ? Pas de problème! Il est possible de rejoindre notre groupe à n’importe quel moment de l’année.
Il suffit de venir à nos locaux durant l’une de nos activités. Nous recommandons aux enfants de venir essayer nos activités pendant plusieurs séances avant de décider s’il souhaite s’inscrire au groupe ou non.
N’hésitez pas à nous contacter si vous souhaitez avoir plus d’informations concernant notre groupe ou nos séances.
</p>
`
},
editable: {
type: Boolean,
default: true,
}
})
const emit = defineEmits(['update'])
const editor = ref(null)
const edit = ref(props.editable);
const activeTab = ref('text')
defineExpose({
editable: (flag) => {
edit.value = flag;
editor.value.setEditable(flag)
}
});
const ImageAlign = Image.extend({
addAttributes() {
return {
...this.parent?.(),
alignment: {
default: 'left',
renderHTML: attributes => {
return {
class: `image-align-${attributes.alignment}`,
}
},
},
}
},
})
// Initialize editor
onMounted(() => {
editor.value = new Editor({
content: props.content,
editorProps: {
attributes: {
class: 'tiptap-editor',
},
},
extensions: [
StarterKit.configure({
heading: { levels: [1, 2, 3, 4] }
}),
Underline,
Mention.configure({
HTMLAttributes: {
class: 'mention',
},
suggestion: {
items: ({ query }) => {
return [
"Tax", "Padda", "Example"
]
}
},
}),
Highlight.configure({
multicolor: true
}),
TextStyle,
TextAlign.configure({
types: ['heading', 'paragraph'],
alignments: ['left', 'center', 'right', 'justify'],
defaultAlignment: 'left',
}),
Color,
CharacterCount,
//Gapcursor,
Link.configure({
openOnClick: false,
autolink: true
}),
Placeholder.configure({
placeholder: 'Texte...'
}),
Typography,
ImageAlign.configure({
inline: true,
allowBase64: true
}),
TaskList,
TaskItem.configure({
nested: true
}),
Table.configure({
resizable: true
}),
TableRow,
TableCell,
TableHeader
],
onUpdate: ({ editor }) => {
emit('update', {
html: editor.getHTML(),
json: editor.getJSON()
})
}
});
editor.value.setEditable(edit);
emit('update', {
html: editor.value.getHTML(),
json: editor.value.getJSON()
})
})
// Clean up
onBeforeUnmount(() => {
if (editor.value) {
editor.value.destroy()
}
})
</script>
<template>
<div v-if="editor" class="notion-editor-container">
<!-- Toolbar based on active tab -->
<div v-if="edit" class="sticky top-16 right-0 left-0 z-10 bg-white border-b border-gray-200 py-2 flex space-x-2 flex-wrap">
<Tabs @active="(tab) => activeTab = tab"/>
<TextTab v-show="activeTab == 'text'" :editor="editor" />
<BlockTab v-show="activeTab == 'blocks'" :editor="editor"/>
<ListTab v-show="activeTab == 'lists'" :editor="editor"/>
<MediaTab v-show="activeTab == 'media'" :editor="editor"/>
<TableTab v-show="activeTab == 'tables'" :editor="editor"/>
<HistoryTab v-show="activeTab == 'history'" :editor="editor"/>
</div>
<BubbleMenu v-if="edit" :editor="editor" />
<!-- Floating Menu for Block Types -->
<FloatingMenu v-if="edit" :editor="editor" />
<!-- Editor Content -->
<editor-content
:editor="editor"
:class="'tiptap-editor min-h-[500px] h-full bg-white shadow-md'"
/>
<div class="sticky bottom-0 right-0 left-0 z-10
bg-white border-t border-gray-200 p-2 flex space-x-2
text-sm text-gray-700">
<p>{{ editor.storage.characterCount.words() }} words</p>
<p>|</p>
<p>{{ editor.storage.characterCount.characters() }} characters</p>
</div>
</div>
</template>
<style>
</style>