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";
10import { editorInstance } from "./create/state";
11
12const Editor = (props: { content: string }) => {
13 let editorDiv!: HTMLDivElement;
14 let themeColor = new Compartment();
15 let view: EditorView;
16
17 const themeEvent = () => {
18 view.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 view = 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 EditorView.lineWrapping,
52 ],
53 });
54 editorInstance.view = view;
55 });
56
57 onCleanup(() =>
58 window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change", themeEvent),
59 );
60
61 return (
62 <div
63 ref={editorDiv}
64 id="editor"
65 class="h-full cursor-auto border-[0.5px] border-neutral-300 dark:border-neutral-700"
66 ></div>
67 );
68};
69
70export { Editor };