maptile/web/components/maplibre/code.vue

64 lines
1.4 KiB
Vue

<script setup lang="ts">
import { json } from "@codemirror/lang-json";
import {
defaultHighlightStyle,
syntaxHighlighting,
} from "@codemirror/language";
import { EditorState } from "@codemirror/state";
import { basicSetup, EditorView } from "codemirror";
const { codes } = defineProps<{ codes: object | undefined }>();
const emit = defineEmits(["update:codes"]);
const view = ref<EditorView>();
watchEffect(() => {
if (!view.value) return;
view.value.dispatch({
changes: {
from: 0,
to: view.value.state.doc.length,
insert: JSON.stringify(codes, null, 2),
},
});
});
onMounted(() => {
const state = EditorState.create({
doc: codes ? JSON.stringify(codes, null, 2) : "",
extensions: [
basicSetup,
syntaxHighlighting(defaultHighlightStyle),
json(),
EditorState.transactionFilter.of((tr) => {
if (tr.docChanged) {
// emit("update:codes", tr.newDoc.toJSON());
debouncedUpdate(JSON.parse(tr.newDoc.toString()));
}
return tr;
}),
],
});
view.value = new EditorView({
parent: document.getElementById("code") as HTMLElement,
state: state,
});
});
const debouncedUpdate = useDebounceFn((value: object) => {
emit("update:codes", value);
}, 1000 * 3);
</script>
<template>
<div id="code"></div>
</template>
<style scoped>
:global(.cm-editor) {
height: 100%;
}
</style>