Change where/when Theme <style> Element is Injected

import { useEffect, useRef, useState } from "react";
import type { IUseCodeMirrorProps } from "./useCodeMirror.types";
import { EditorState } from "@codemirror/state";
import { EditorView } from "@codemirror/view";
import { javascript } from "@codemirror/lang-javascript";
import { basicSetup } from "codemirror";

export const useCodeMirror = <T extends Element>(props: IUseCodeMirrorProps) => {
  const { initialDoc, editorClassName = "editor" } = props;
  const containerRef = useRef<T>(null);

  const [editorView, setEditorView] = useState<EditorView>();

  useEffect(() => {
    if (!containerRef.current) {
      return;
    }

    const container = containerRef.current;
    let shadowRoot = container.shadowRoot || undefined;

    if (!shadowRoot) {
      shadowRoot = container.attachShadow({ mode: "open" });
    }

    const div = document.createElement("div");
    div.className = editorClassName;
    shadowRoot.append(div);

    const editorState = EditorState.create({
      doc: initialDoc,
      extensions: [basicSetup, javascript(), EditorView.editable.of(false)],
    });

    const editorView = new EditorView({
      state: editorState,
      parent: shadowRoot.querySelector(`.${editorClassName}`) || undefined,
      root: shadowRoot,
    });

    setEditorView(editorView);

    return () => {
      editorView.destroy();
    };
  }, [editorClassName, initialDoc]);

  return [containerRef, editorView] as const;
};

shadowRoot work too

1 Like