1import { indentWithTab } from "@codemirror/commands";
2import { json, jsonParseLinter } from "@codemirror/lang-json";
3import { linter } from "@codemirror/lint";
4import { Compartment } from "@codemirror/state";
5import { keymap } from "@codemirror/view";
6import { basicDark } from "@fsegurai/codemirror-theme-basic-dark";
7import { basicLight } from "@fsegurai/codemirror-theme-basic-light";
8import { basicSetup, EditorView } from "codemirror";
9import { onCleanup, onMount } from "solid-js";
10
11export let editorView: EditorView;
12
13const Editor = (props: { content: string }) => {
14 let editorDiv!: HTMLDivElement;
15 let themeColor = new Compartment();
16
17 const themeEvent = () => {
18 editorView.dispatch({
19 effects: themeColor.reconfigure(
20 window.matchMedia("(prefers-color-scheme: dark)").matches ? basicDark : basicLight,
21 ),
22 });
23 };
24
25 onMount(() => {
26 const theme = EditorView.theme({
27 ".cm-content": {
28 fontFamily: "'Roboto Mono', monospace",
29 fontSize: "12px",
30 },
31 ".cm-scroller": {
32 overflow: "auto",
33 },
34 "&": {
35 height: "100%",
36 },
37 });
38
39 window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", themeEvent);
40
41 editorView = new EditorView({
42 doc: props.content,
43 parent: editorDiv,
44 extensions: [
45 basicSetup,
46 theme,
47 json(),
48 keymap.of([indentWithTab]),
49 linter(jsonParseLinter()),
50 themeColor.of(document.documentElement.classList.contains("dark") ? basicDark : basicLight),
51 ],
52 });
53 });
54
55 onCleanup(() =>
56 window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change", themeEvent),
57 );
58
59 return (
60 <div
61 ref={editorDiv}
62 id="editor"
63 class="dark:shadow-dark-700 h-full cursor-auto border-[0.5px] border-neutral-300 shadow-xs dark:border-neutral-700"
64 ></div>
65 );
66};
67
68export { Editor };