dashboard/components/CodeMirror.vue

135 lines
2.6 KiB
Vue

<script>
import $ from 'jquery';
import { THEME, KEYMAP } from '@/store/prefs';
export default {
props: {
value: {
type: String,
required: true,
},
options: {
type: Object,
default: () => {}
},
autoResize: {
type: Boolean,
default: true,
},
footerSpace: {
type: Number,
default: 0,
},
minHeight: {
type: Number,
default: 200,
}
},
data() {
return { loaded: false };
},
computed: {
codemirror() {
return this.$refs.cm.codemirror;
},
combinedOptions() {
const theme = this.$store.getters['prefs/get'](THEME);
const keymap = this.$store.getters['prefs/get'](KEYMAP);
const out = {
// codemirror options
tabSize: 2,
indentWithTabs: false,
mode: 'yaml',
keyMap: keymap,
theme: `base16-${ theme }`,
lineNumbers: true,
line: true,
viewportMargin: Infinity,
styleActiveLine: true,
lineWrapping: true,
foldGutter: true,
styleSelectedText: true,
showCursorWhenSelecting: true,
...this.options
};
return out;
},
},
mounted() {
import('@/plugins/codemirror').then(() => {
this.loaded = true;
});
},
methods: {
onReady(cm) {
this.fit();
this.$emit('onReady', cm);
},
onInput(newCode) {
this.$emit('onInput', newCode);
},
onChanges(cm, changes) {
this.$emit('onChanges', cm, changes);
},
fit() {
if ( !this.autoResize ) {
return;
}
const container = $(this.$refs.cm.$el);
if ( !container || !container.length ) {
return;
}
const offset = container.offset();
if ( !offset ) {
return;
}
const desired = $(window).innerHeight() - offset.top - this.footerSpace;
container.css('height', `${ Math.max(this.minHeight, desired) }px`);
},
}
};
</script>
<template>
<client-only v-if="autoResize" placeholder=" Loading...">
<div v-if="loaded">
<resize-observer @notify="fit" />
<codemirror
ref="cm"
:value="value"
:options="combinedOptions"
@ready="onReady"
@input="onInput"
@changes="onChanges"
/>
</div>
<div v-else>
Loading...
</div>
</client-only>
</template>
<style lang="scss">
.CodeMirror {
height: 100% !important;
}
</style>