import { type Component, computed, ref, onMounted, onBeforeUnmount, toRef, watch } from 'vue'
-import { EditorState } from '@codemirror/state'
+import { Compartment, EditorState } from '@codemirror/state'
import { EditorView, keymap, placeholder as cm_placeholder } from '@codemirror/view'
import { markdown } from '@codemirror/lang-markdown'
import { indentWithTab, historyKeymap, history } from '@codemirror/commands'
@@ -327,6 +327,7 @@ const props = withDefaults(
const editorRef = ref()
let editor: EditorView | null = null
+let isDisabledCompartment: Compartment | null = null
const emit = defineEmits(['update:modelValue'])
@@ -338,7 +339,7 @@ onMounted(() => {
})
const theme = EditorView.theme({
- // in defualts.scss there's references to .cm-content and such to inherit global styles
+ // in defaults.scss there's references to .cm-content and such to inherit global styles
'.cm-content': {
marginBlockEnd: '0.5rem',
padding: '0.5rem',
@@ -355,6 +356,10 @@ onMounted(() => {
},
})
+ isDisabledCompartment = new Compartment()
+
+ const disabledCompartment = EditorState.readOnly.of(props.disabled)
+
const eventHandlers = EditorView.domEventHandlers({
paste: (ev, view) => {
const { clipboardData } = ev
@@ -437,13 +442,23 @@ onMounted(() => {
keymap.of(historyKeymap),
cm_placeholder(props.placeholder || ''),
inputFilter,
+ isDisabledCompartment.of(disabledCompartment),
],
})
editor = new EditorView({
state: editorState,
parent: editorRef.value,
- doc: props.modelValue,
+ doc: props.modelValue ?? '', // This doesn't work for some reason
+ })
+
+ // set editor content to props.modelValue
+ editor?.dispatch({
+ changes: {
+ from: 0,
+ to: editor.state.doc.length,
+ insert: props.modelValue,
+ },
})
})
@@ -541,18 +556,35 @@ const BUTTONS: ButtonGroupMap = {
},
}
+watch(
+ () => props.disabled,
+ (newValue) => {
+ if (editor && isDisabledCompartment) {
+ editor.dispatch({
+ effects: isDisabledCompartment.reconfigure(EditorState.readOnly.of(newValue)),
+ })
+ }
+ }
+)
+
const currentValue = toRef(props, 'modelValue')
-watch(currentValue, (newValue) => {
- if (editor) {
- editor.dispatch({
- changes: {
- from: 0,
- to: editor.state.doc.length,
- insert: newValue,
- },
- })
+watch(
+ currentValue,
+ (newValue) => {
+ if (editor && newValue !== editor.state.doc.toString()) {
+ editor.dispatch({
+ changes: {
+ from: 0,
+ to: editor.state.doc.length,
+ insert: newValue,
+ },
+ })
+ }
+ },
+ {
+ immediate: true,
}
-})
+)
const updateCurrentValue = (newValue: string) => {
emit('update:modelValue', newValue)