xLog/src/hooks/useCodemirrorTheme.ts

82 lines
2.1 KiB
TypeScript

import { useEffect, useRef } from "react"
import type { Extension } from "@codemirror/state"
import { Compartment } from "@codemirror/state"
import { oneDark } from "@codemirror/theme-one-dark"
import { EditorView } from "@codemirror/view"
import { githubLight } from "@ddietr/codemirror-themes/theme/github-light"
import { useIsUnmounted } from "./useLifecycle"
export const monospaceFonts = `"OperatorMonoSSmLig Nerd Font","Cascadia Code PL","FantasqueSansMono Nerd Font","operator mono","Fira code Retina","Fira code","Consolas", Monaco, "Hannotate SC", monospace, -apple-system`
const extensionMap = {
theme: new Compartment(),
style: new Compartment(),
}
export const codemirrorReconfigureExtension: Extension[] = [
extensionMap.theme.of([]),
extensionMap.style.of([]),
]
export const useCodeMirrorAutoToggleTheme = (
view: EditorView | null,
isDark: boolean,
) => {
useEffect(() => {
if (!view) return
if (isDark) {
view.dispatch({
effects: [extensionMap.theme.reconfigure(oneDark)],
})
} else {
view.dispatch({
effects: [extensionMap.theme.reconfigure(githubLight)],
})
}
}, [view, isDark])
}
export const useCodeMirrorStyle = (view: EditorView | null) => {
const isUnmounted = useIsUnmounted()
const once = useRef(false)
const getStyle = () => {
return {
".cm-scroller": {
fontFamily: monospaceFonts,
fontSize: "1rem",
overflow: "auto",
height: "100%",
padding: "0 1.25rem",
},
".cm-content": {
paddingBottom: "600px",
},
"&.cm-editor.cm-focused": {
outline: "none",
},
"&.cm-editor": {
height: "100%",
backgroundColor: "transparent",
},
}
}
useEffect(() => {
if (!view) return
view.dispatch({
effects: [extensionMap.style.reconfigure(EditorView.theme(getStyle()))],
})
}, [view])
if (isUnmounted()) return
if (!once.current) {
if (!view) return
view.dispatch({
effects: [extensionMap.style.reconfigure(EditorView.theme(getStyle()))],
})
once.current = true
}
}