@@ -31,7 +31,7 @@ const getWorkerURL = (url) => {
3131 return URL . createObjectURL ( blob ) ;
3232} ;
3333
34- const PyodideRunner = ( { active } ) => {
34+ const PyodideRunner = ( { active, outputPanels = [ "text" , "visual" ] } ) => {
3535 const [ pyodideWorker , setPyodideWorker ] = useState ( null ) ;
3636
3737 useEffect ( ( ) => {
@@ -65,6 +65,9 @@ const PyodideRunner = ({ active }) => {
6565 const isMobile = useMediaQuery ( { query : MOBILE_MEDIA_QUERY } ) ;
6666 const senseHatAlways = useSelector ( ( s ) => s . editor . senseHatAlwaysEnabled ) ;
6767 const queryParams = new URLSearchParams ( window . location . search ) ;
68+ const singleOutputPanel = outputPanels . length === 1 ;
69+ const showVisualOutputPanel = outputPanels . includes ( "visual" ) ;
70+ const showTextOutputPanel = outputPanels . includes ( "text" ) ;
6871 const showVisualTab = queryParams . get ( "show_visual_tab" ) === "true" ;
6972 const [ hasVisual , setHasVisual ] = useState ( showVisualTab || senseHatAlways ) ;
7073 const [ visuals , setVisuals ] = useState ( [ ] ) ;
@@ -195,8 +198,10 @@ const PyodideRunner = ({ active }) => {
195198 } ;
196199
197200 const handleVisual = ( origin , content ) => {
198- setHasVisual ( true ) ;
199- setVisuals ( ( array ) => [ ...array , { origin, content } ] ) ;
201+ if ( showVisualOutputPanel ) {
202+ setHasVisual ( true ) ;
203+ setVisuals ( ( array ) => [ ...array , { origin, content } ] ) ;
204+ }
200205 } ;
201206
202207 const handleSenseHatEvent = ( type ) => {
@@ -326,12 +331,16 @@ const PyodideRunner = ({ active }) => {
326331 "pyodiderunner--active" : active ,
327332 } ) }
328333 >
329- { isSplitView ? (
334+ { isSplitView || singleOutputPanel ? (
330335 < >
331- { hasVisual && (
336+ { hasVisual && showVisualOutputPanel && (
332337 < div className = "output-panel output-panel--visual" >
333338 < Tabs forceRenderTabPanel = { true } >
334- < div className = "react-tabs__tab-container" >
339+ < div
340+ className = { classNames ( "react-tabs__tab-container" , {
341+ "react-tabs__tab-container--hidden" : singleOutputPanel ,
342+ } ) }
343+ >
335344 < TabList >
336345 < Tab key = { 0 } >
337346 < span className = "react-tabs__tab-text" >
@@ -348,30 +357,36 @@ const PyodideRunner = ({ active }) => {
348357 </ Tabs >
349358 </ div >
350359 ) }
351- < div className = "output-panel output-panel--text" >
352- < Tabs forceRenderTabPanel = { true } >
353- < div className = "react-tabs__tab-container" >
354- < TabList >
355- < Tab key = { 0 } >
356- < span className = "react-tabs__tab-text" >
357- { t ( "output.textOutput" ) }
358- </ span >
359- </ Tab >
360- </ TabList >
361- { ! hasVisual && ! isEmbedded && isMobile && (
362- < RunnerControls skinny />
363- ) }
364- </ div >
365- < ErrorMessage />
366- < TabPanel key = { 0 } >
367- < pre
368- className = { `pythonrunner-console pythonrunner-console--${ settings . fontSize } ` }
369- onClick = { shiftFocusToInput }
370- ref = { output }
371- > </ pre >
372- </ TabPanel >
373- </ Tabs >
374- </ div >
360+ { showTextOutputPanel && (
361+ < div className = "output-panel output-panel--text" >
362+ < Tabs forceRenderTabPanel = { true } >
363+ < div
364+ className = { classNames ( "react-tabs__tab-container" , {
365+ "react-tabs__tab-container--hidden" : singleOutputPanel ,
366+ } ) }
367+ >
368+ < TabList >
369+ < Tab key = { 0 } >
370+ < span className = "react-tabs__tab-text" >
371+ { t ( "output.textOutput" ) }
372+ </ span >
373+ </ Tab >
374+ </ TabList >
375+ { ! hasVisual && ! isEmbedded && isMobile && (
376+ < RunnerControls skinny />
377+ ) }
378+ </ div >
379+ < ErrorMessage />
380+ < TabPanel key = { 0 } >
381+ < pre
382+ className = { `pythonrunner-console pythonrunner-console--${ settings . fontSize } ` }
383+ onClick = { shiftFocusToInput }
384+ ref = { output }
385+ > </ pre >
386+ </ TabPanel >
387+ </ Tabs >
388+ </ div >
389+ ) }
375390 </ >
376391 ) : (
377392 < Tabs forceRenderTabPanel = { true } defaultIndex = { hasVisual ? 0 : 1 } >
0 commit comments