@@ -2,13 +2,103 @@ import { useRef, useEffect } from "react";
22import Editor , { type OnMount } from "@monaco-editor/react" ;
33import { emmetHTML , emmetCSS } from "emmet-monaco-es" ;
44import type * as Monaco from "monaco-editor" ;
5+ import type { EditorTheme } from "../SettingsModal/SettingsModal" ;
6+
7+ // Custom theme definitions for Monaco
8+ const CUSTOM_THEMES : Record < string , Monaco . editor . IStandaloneThemeData > = {
9+ dracula : {
10+ base : "vs-dark" ,
11+ inherit : true ,
12+ rules : [
13+ { token : "" , foreground : "f8f8f2" , background : "282a36" } ,
14+ { token : "comment" , foreground : "6272a4" , fontStyle : "italic" } ,
15+ { token : "string" , foreground : "f1fa8c" } ,
16+ { token : "keyword" , foreground : "ff79c6" } ,
17+ { token : "number" , foreground : "bd93f9" } ,
18+ { token : "type" , foreground : "8be9fd" , fontStyle : "italic" } ,
19+ { token : "function" , foreground : "50fa7b" } ,
20+ { token : "variable" , foreground : "f8f8f2" } ,
21+ { token : "constant" , foreground : "bd93f9" } ,
22+ { token : "tag" , foreground : "ff79c6" } ,
23+ { token : "attribute.name" , foreground : "50fa7b" } ,
24+ { token : "attribute.value" , foreground : "f1fa8c" } ,
25+ ] ,
26+ colors : {
27+ "editor.background" : "#282a36" ,
28+ "editor.foreground" : "#f8f8f2" ,
29+ "editor.lineHighlightBackground" : "#44475a" ,
30+ "editor.selectionBackground" : "#44475a" ,
31+ "editorCursor.foreground" : "#f8f8f2" ,
32+ "editorWhitespace.foreground" : "#3B3A32" ,
33+ "editorIndentGuide.activeBackground" : "#9D550FB0" ,
34+ "editor.selectionHighlightBorder" : "#222218" ,
35+ } ,
36+ } ,
37+ monokai : {
38+ base : "vs-dark" ,
39+ inherit : true ,
40+ rules : [
41+ { token : "" , foreground : "f8f8f2" , background : "272822" } ,
42+ { token : "comment" , foreground : "75715e" , fontStyle : "italic" } ,
43+ { token : "string" , foreground : "e6db74" } ,
44+ { token : "keyword" , foreground : "f92672" } ,
45+ { token : "number" , foreground : "ae81ff" } ,
46+ { token : "type" , foreground : "66d9ef" , fontStyle : "italic" } ,
47+ { token : "function" , foreground : "a6e22e" } ,
48+ { token : "variable" , foreground : "f8f8f2" } ,
49+ { token : "constant" , foreground : "ae81ff" } ,
50+ { token : "tag" , foreground : "f92672" } ,
51+ { token : "attribute.name" , foreground : "a6e22e" } ,
52+ { token : "attribute.value" , foreground : "e6db74" } ,
53+ ] ,
54+ colors : {
55+ "editor.background" : "#272822" ,
56+ "editor.foreground" : "#f8f8f2" ,
57+ "editor.lineHighlightBackground" : "#3e3d32" ,
58+ "editor.selectionBackground" : "#49483e" ,
59+ "editorCursor.foreground" : "#f8f8f0" ,
60+ "editorWhitespace.foreground" : "#3B3A32" ,
61+ "editorIndentGuide.activeBackground" : "#9D550FB0" ,
62+ "editor.selectionHighlightBorder" : "#222218" ,
63+ } ,
64+ } ,
65+ "github-dark" : {
66+ base : "vs-dark" ,
67+ inherit : true ,
68+ rules : [
69+ { token : "" , foreground : "c9d1d9" , background : "0d1117" } ,
70+ { token : "comment" , foreground : "8b949e" , fontStyle : "italic" } ,
71+ { token : "string" , foreground : "a5d6ff" } ,
72+ { token : "keyword" , foreground : "ff7b72" } ,
73+ { token : "number" , foreground : "79c0ff" } ,
74+ { token : "type" , foreground : "ffa657" } ,
75+ { token : "function" , foreground : "d2a8ff" } ,
76+ { token : "variable" , foreground : "c9d1d9" } ,
77+ { token : "constant" , foreground : "79c0ff" } ,
78+ { token : "tag" , foreground : "7ee787" } ,
79+ { token : "attribute.name" , foreground : "79c0ff" } ,
80+ { token : "attribute.value" , foreground : "a5d6ff" } ,
81+ ] ,
82+ colors : {
83+ "editor.background" : "#0d1117" ,
84+ "editor.foreground" : "#c9d1d9" ,
85+ "editor.lineHighlightBackground" : "#161b22" ,
86+ "editor.selectionBackground" : "#264f78" ,
87+ "editorCursor.foreground" : "#c9d1d9" ,
88+ "editorWhitespace.foreground" : "#484f58" ,
89+ "editorIndentGuide.activeBackground" : "#30363d" ,
90+ "editor.selectionHighlightBorder" : "#17191e" ,
91+ } ,
92+ } ,
93+ } ;
594
695interface CodeEditorProps {
796 value : string ;
897 language : string ;
998 onChange : ( value : string | undefined ) => void ;
1099 showMinimap ?: boolean ;
11100 wordWrap ?: boolean ;
101+ theme ?: EditorTheme ;
12102 onSave ?: ( ) => void ;
13103}
14104
@@ -18,10 +108,13 @@ function CodeEditor({
18108 onChange,
19109 showMinimap = true ,
20110 wordWrap = true ,
111+ theme = "vs-dark" ,
21112 onSave
22113} : CodeEditorProps ) {
23114 const editorRef = useRef < Monaco . editor . IStandaloneCodeEditor | null > ( null ) ;
115+ const monacoRef = useRef < typeof Monaco | null > ( null ) ;
24116 const disposeEmmetRef = useRef < ( ( ) => void ) | null > ( null ) ;
117+ const themesRegistered = useRef ( false ) ;
25118
26119 // Map our language names to Monaco language IDs
27120 const getMonacoLanguage = ( lang : string ) => {
@@ -35,7 +128,20 @@ function CodeEditor({
35128
36129 const handleEditorMount : OnMount = ( editor , monaco ) => {
37130 editorRef . current = editor ;
131+ monacoRef . current = monaco ;
132+
133+ // Register custom themes only once
134+ if ( ! themesRegistered . current ) {
135+ Object . entries ( CUSTOM_THEMES ) . forEach ( ( [ themeName , themeData ] ) => {
136+ monaco . editor . defineTheme ( themeName , themeData ) ;
137+ } ) ;
138+ themesRegistered . current = true ;
139+ }
38140
141+ // Apply initial theme (for custom themes that need registration first)
142+ if ( CUSTOM_THEMES [ theme ] ) {
143+ monaco . editor . setTheme ( theme ) ;
144+ }
39145 // Enable Emmet for HTML and CSS
40146 try {
41147 const disposeHtml = emmetHTML ( monaco ) ;
@@ -79,6 +185,13 @@ function CodeEditor({
79185 }
80186 } , [ showMinimap , wordWrap ] ) ;
81187
188+ // Update theme dynamically
189+ useEffect ( ( ) => {
190+ if ( monacoRef . current ) {
191+ monacoRef . current . editor . setTheme ( theme ) ;
192+ }
193+ } , [ theme ] ) ;
194+
82195 // Cleanup on unmount
83196 useEffect ( ( ) => {
84197 return ( ) => {
@@ -92,7 +205,7 @@ function CodeEditor({
92205 < Editor
93206 height = "100%"
94207 language = { getMonacoLanguage ( language ) }
95- theme = "vs-dark"
208+ theme = { theme }
96209 value = { value }
97210 onChange = { onChange }
98211 onMount = { handleEditorMount }
0 commit comments