diff --git a/client/components/forms/components/QuillyEditor.vue b/client/components/forms/components/QuillyEditor.vue index c0cdb084..3d0e0b40 100644 --- a/client/components/forms/components/QuillyEditor.vue +++ b/client/components/forms/components/QuillyEditor.vue @@ -5,94 +5,107 @@ /> - \ No newline at end of file +) + +// Watch model and update modelValue if has changes +watch(model, (newValue, oldValue) => { + if (!quillInstance) return + if (newValue && newValue !== oldValue) { + emit('update:modelValue', newValue) + } else if (!newValue) { + quillInstance.setContents([]) + } +}) + +onBeforeUnmount(() => { + if (quillInstance) { + quillInstance.off('selection-change') + quillInstance.off('text-change') + quillInstance.off('editor-change') + } + quillInstance = null +}) + \ No newline at end of file diff --git a/client/lib/quill/quillMentionExtension.js b/client/lib/quill/quillMentionExtension.js index a3381295..875b207d 100644 --- a/client/lib/quill/quillMentionExtension.js +++ b/client/lib/quill/quillMentionExtension.js @@ -1,7 +1,6 @@ import { reactive } from 'vue' import Quill from 'quill' const Inline = Quill.import('blots/inline') -const Delta = Quill.import('delta') const Clipboard = Quill.import('modules/clipboard') export default function registerMentionExtension(Quill) { @@ -9,17 +8,42 @@ export default function registerMentionExtension(Quill) { class MentionClipboard extends Clipboard { convert(html) { const delta = super.convert(html) - // Remove any mention formatting from pasted content - return delta.reduce((newDelta, op) => { + const processedDelta = delta.ops.reduce((newDelta, op) => { if (op.attributes && op.attributes.mention) { - // Only keep mentions that have valid field IDs - if (!op.attributes.mention['mention-field-id']) { + const mentionData = op.attributes.mention + let isValid = false + // Check for nested structure + if ( + mentionData && + typeof mentionData === 'object' && + mentionData.field && + typeof mentionData.field === 'object' && + mentionData.field.id + ) { + isValid = true + } else if ( + mentionData && + typeof mentionData === 'object' && + mentionData['mention-field-id'] + ) { + // Transform flat structure to nested structure + op.attributes.mention = { + field: { + id: mentionData['mention-field-id'], + name: mentionData['mention-field-name'] || '', + }, + fallback: mentionData['mention-fallback'] || '', + } + isValid = true + } + if (!isValid) { delete op.attributes.mention } } newDelta.push(op) return newDelta - }, new Delta()) + }, []) + return processedDelta } } Quill.register('modules/clipboard', MentionClipboard, true) @@ -43,7 +67,6 @@ export default function registerMentionExtension(Quill) { if (!data || !data.field || !data.field.id) { return } - node.setAttribute('contenteditable', 'false') node.setAttribute('mention', 'true') node.setAttribute('mention-field-id', data.field.id || '') @@ -70,7 +93,7 @@ export default function registerMentionExtension(Quill) { formats() { let formats = super.formats() - formats['mention'] = MentionBlot.formats(this.domNode) + formats['mention'] = MentionBlot.value(this.domNode) return formats } diff --git a/client/scss/app.scss b/client/scss/app.scss index 5efa0604..044a142f 100644 --- a/client/scss/app.scss +++ b/client/scss/app.scss @@ -52,9 +52,17 @@ body.dark * { } .field-help { - p { + p, ol, ul, li { @apply text-gray-400 dark:text-gray-500; } + + ol { + @apply list-decimal list-inside; + } + + ul { + @apply list-disc list-inside; + } } .public-page {