I needed a in-browser editor for editing SQL. Initially, I used used @monaco-editor/react which sits on top of monaco-editor and it's a beast.
The problem was that monaco
is very large. And I don't know why, but it dynamically loads other files from a CDN, as demonstrated by this Network panel for JS files:
I needed something more lightweight and found prism-react-editor which looks very promising.
Now, the network chart looks like this:
When I make PRs against this project, I have a GitHub Action that posts a comment about the change in size of the total static asset bundle. It looked like this:
Yay! More than 4MB smaller. Admittedly, it's comparing apples to pineapples but good to know.
Keyboard shortcut
One important feature that took me some figuring out was how to make Cmd-Enter trigger a form submission.
This is/was how you do it with @monaco-editor/react
:
import type { editor } from "monaco-editor"
import { KeyCode, KeyMod } from "monaco-editor"
// ...
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)
const monacoEditor = editorRef.current
const editorRef = useRef<PrismEditor | null>(null)
if (monacoEditor) {
monacoEditor.addCommand(KeyCode.Enter | KeyMod.CtrlCmd, () => {
// Your code to execute when Ctrl/Cmd + Enter is pressed
}
}
And this is how you accomplish the same with prism-react-editor
:
import { type PrismEditor } from "prism-react-editor"
// ...
const editorRef = useRef<PrismEditor | null>(null)
useEffect(() => {
const editor = editorRef.current
if (editor) {
const oldEnterCallback = editor.keyCommandMap.Enter
editor.keyCommandMap.Enter = (e, selection, value) => {
if (e.metaKey) {
// Your code to execute when Ctrl/Cmd + Enter is pressed
return true
}
return oldEnterCallback?.(e, selection, value)
}
}
})
Theming
I didn't use AI to make this migration, but I do admit that since it is a side-project I didn't send a whole lot of time reading the manual. After a bit of hacking I figured out how I can get the editor correctly themed in my Mantine app:
import "prism-react-editor/themes/vs-code-light.css" // default
function injectStylesheet(cssText: string): void {
const existing = document.getElementById("prism-theme")
if (existing) {
existing.textContent = cssText
} else {
const style = document.createElement("style")
style.id = "prism-theme"
style.textContent = cssText
document.head.appendChild(style)
}
}
export function Component() {
const { colorScheme } = useMantineColorScheme()
useEffect(() => {
loadTheme(colorScheme === "light" ? "vs-code-light" : "vs-code-dark").then(
(theme) => {
if (theme) injectStylesheet(theme)
},
)
}, [colorScheme])
// ...
That seems to work.
Comments