1- import React , { useEffect , useRef , useState } from 'react' ;
1+ import React , { useState } from 'react' ;
2+ import Editor from '@monaco-editor/react' ;
23import './styles.css' ;
34
45declare global {
@@ -8,11 +9,13 @@ declare global {
89 }
910}
1011
11- const DEFAULT_CODE = `print("Hello from Pyodide!")\nfor i in range(3):\n print('Line', i+1)` ;
12+ const DEFAULT_CODE = `print("Hello from Pyodide!")
13+ for i in range(3):
14+ print('Line', i+1)` ;
1215
1316export default function InteractivePythonEditor ( {
1417 initialCode = DEFAULT_CODE ,
15- height = 260 ,
18+ height = 400 ,
1619} : {
1720 initialCode ?: string ;
1821 height ?: number | string ;
@@ -21,36 +24,6 @@ export default function InteractivePythonEditor({
2124 const [ output , setOutput ] = useState ( '' ) ;
2225 const [ loading , setLoading ] = useState ( false ) ;
2326 const [ pyodideReady , setPyodideReady ] = useState ( false ) ;
24- const preRef = useRef < HTMLPreElement | null > ( null ) ;
25-
26- useEffect ( ( ) => {
27- // Load Prism for highlighting (CSS + script)
28- if ( ! document . querySelector ( 'link[data-prism]' ) ) {
29- const link = document . createElement ( 'link' ) ;
30- link . setAttribute ( 'data-prism' , '' ) ;
31- link . rel = 'stylesheet' ;
32- link . href = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.css' ;
33- document . head . appendChild ( link ) ;
34- }
35- if ( ! ( window as any ) . Prism ) {
36- const s = document . createElement ( 'script' ) ;
37- s . src = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js' ;
38- s . async = true ;
39- document . head . appendChild ( s ) ;
40- }
41- } , [ ] ) ;
42-
43- useEffect ( ( ) => {
44- // Highlight when code or Prism loads
45- const highlight = ( ) => {
46- if ( ( window as any ) . Prism && preRef . current ) {
47- ( window as any ) . Prism . highlightElement ( preRef . current ) ;
48- }
49- } ;
50- highlight ( ) ;
51- const id = setTimeout ( highlight , 50 ) ;
52- return ( ) => clearTimeout ( id ) ;
53- } , [ code ] ) ;
5427
5528 async function ensurePyodide ( ) {
5629 if ( pyodideReady ) return window . pyodide ;
@@ -118,18 +91,22 @@ export default function InteractivePythonEditor({
11891 < div className = "ipe-status" > { pyodideReady ? 'Pyodide ready' : ( loading ? 'Loading...' : 'Pyodide not loaded' ) } </ div >
11992 </ div >
12093
121- < div className = "ipe-main" >
122- < textarea
123- className = "ipe-textarea"
94+ < div className = "ipe-editor" >
95+ < Editor
96+ height = { height }
97+ language = "python"
12498 value = { code }
125- onChange = { ( e ) => setCode ( e . target . value ) }
126- style = { { height} }
127- spellCheck = { false }
99+ onChange = { ( value ) => setCode ( value || '' ) }
100+ theme = "light"
101+ options = { {
102+ minimap : { enabled : false } ,
103+ fontSize : 14 ,
104+ lineNumbers : 'on' ,
105+ roundedSelection : false ,
106+ scrollBeyondLastLine : false ,
107+ automaticLayout : true ,
108+ } }
128109 />
129-
130- < div className = "ipe-preview" style = { { height} } >
131- < pre ref = { preRef } className = "language-python" > < code > { code } </ code > </ pre >
132- </ div >
133110 </ div >
134111
135112 < div className = "ipe-output" >
0 commit comments