(minHeight);
28 | const { theme } = useTheme();
29 | const [effectiveTheme, setEffectiveTheme] = useState<'light' | 'dark'>(
30 | theme === 'system'
31 | ? window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
32 | : theme
33 | );
34 |
35 | useEffect(() => {
36 | const updateEffectiveTheme = () => {
37 | if (theme === 'system') {
38 | setEffectiveTheme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
39 | } else {
40 | setEffectiveTheme(theme);
41 | }
42 | };
43 |
44 | updateEffectiveTheme();
45 |
46 | if (theme === 'system') {
47 | const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
48 | mediaQuery.addEventListener('change', updateEffectiveTheme);
49 | return () => mediaQuery.removeEventListener('change', updateEffectiveTheme);
50 | }
51 | }, [theme]);
52 |
53 | const isDark = effectiveTheme === 'dark';
54 |
55 | useEffect(() => {
56 | if (editorRef.current) {
57 | const currentValue = editorRef.current.getValue();
58 | if (currentValue !== code) {
59 | editorRef.current.setValue(code);
60 | }
61 | }
62 | }, [code]);
63 |
64 | const updateEditorHeight = () => {
65 | if (!editorRef.current) return;
66 |
67 | const editor = editorRef.current;
68 | const contentHeight = editor.getContentHeight();
69 | const minHeightPx = parseInt(minHeight);
70 | const maxHeightPx = parseInt(maxHeight);
71 |
72 | const newHeight = Math.min(maxHeightPx, Math.max(minHeightPx, contentHeight));
73 |
74 | setEditorHeight(`${newHeight}px`);
75 |
76 | const shouldShowScrollbar = contentHeight > maxHeightPx;
77 | editor.updateOptions({
78 | scrollbar: {
79 | vertical: shouldShowScrollbar ? 'visible' : 'hidden',
80 | horizontal: 'visible',
81 | verticalScrollbarSize: 12,
82 | horizontalScrollbarSize: 12,
83 | }
84 | });
85 |
86 | editor.layout();
87 | };
88 |
89 | const handleEditorDidMount: OnMount = (editor) => {
90 | editorRef.current = editor;
91 |
92 | editor.onDidContentSizeChange(() => {
93 | window.requestAnimationFrame(updateEditorHeight);
94 | });
95 |
96 | updateEditorHeight();
97 | };
98 |
99 | useEffect(() => {
100 | if (editorRef.current) {
101 | const model = editorRef.current.getModel();
102 | if (model) {
103 | Monaco.editor.setModelLanguage(model, monacoLanguage);
104 | updateEditorHeight();
105 | }
106 | }
107 | }, [monacoLanguage]);
108 |
109 | return (
110 |
111 | {
116 | onValueChange?.(value);
117 | setTimeout(updateEditorHeight, 10);
118 | }}
119 | onMount={handleEditorDidMount}
120 | theme={isDark ? "vs-dark" : "light"}
121 | options={{
122 | minimap: { enabled: false },
123 | scrollBeyondLastLine: false,
124 | fontSize: 13,
125 | lineNumbers: showLineNumbers ? 'on' : 'off',
126 | renderLineHighlight: 'all',
127 | wordWrap: 'on',
128 | wrappingIndent: 'indent',
129 | automaticLayout: true,
130 | folding: false,
131 | tabSize: 4,
132 | formatOnPaste: true,
133 | formatOnType: true,
134 | padding: { top: 12, bottom: 12 },
135 | lineDecorationsWidth: showLineNumbers ? 24 : 50,
136 | overviewRulerBorder: false,
137 | scrollbar: {
138 | alwaysConsumeMouseWheel: false, // Fixes an issue where scrolling to end of code block did not allow further scrolling
139 | vertical: 'visible',
140 | horizontal: 'visible',
141 | verticalScrollbarSize: 12,
142 | horizontalScrollbarSize: 12,
143 | useShadows: false
144 | }
145 | }}
146 | />
147 |
148 | );
149 | };
150 |
--------------------------------------------------------------------------------