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 maxHeight: "20rem",
34 },
35 });
36
37 window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", themeEvent);
38
39 editorView = new EditorView({
40 doc: props.content,
41 parent: editorDiv,
42 extensions: [
43 basicSetup,
44 theme,
45 json(),
46 keymap.of([indentWithTab]),
47 linter(jsonParseLinter()),
48 themeColor.of(document.documentElement.classList.contains("dark") ? basicDark : basicLight),
49 ],
50 });
51 });
52
53 onCleanup(() =>
54 window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change", themeEvent),
55 );
56
57 return (
58 <div
59 ref={editorDiv}
60 id="editor"
61 class="dark:shadow-dark-700 cursor-auto border-[0.5px] border-neutral-300 shadow-xs dark:border-neutral-700"
62 ></div>
63 );
64};
65
66export { Editor };