@@ -181,6 +181,30 @@ export default function PyTorchTritonExplorer() {
181181 } ) ;
182182 } , [ ] ) ;
183183
184+ const addSource = ( ) => {
185+ const newId = sources . length + 1 ;
186+ const template = {
187+ id : newId ,
188+ name : `Source ${ newId } ` ,
189+ selectedLanguage : "pytorch" ,
190+ code : defaultPyTorchCode ,
191+ irWindows : [
192+ {
193+ id : 1 ,
194+ selectedIR : "torch_script_graph_ir" ,
195+ output : "Select IR and Generate" ,
196+ collapsed : false ,
197+ loading : false ,
198+ pipeline : [ ] ,
199+ dumpAfterEachOpt : false ,
200+ } ,
201+ ] ,
202+ customToolCmd : { } ,
203+ } ;
204+ setSources ( ( prev ) => [ ...prev , template ] ) ;
205+ setActiveSourceId ( newId ) ;
206+ } ;
207+
184208 const handleAddPass = ( id , tool ) => {
185209 const flags = prompt ( `Enter flags for ${ tool } ` ) ;
186210 if ( flags !== null ) {
@@ -457,55 +481,56 @@ export default function PyTorchTritonExplorer() {
457481 } }
458482 >
459483 < h2 style = { { margin : 0 } } > Source code tabs</ h2 >
460- < button
461- onClick = { ( ) => {
462- const newId = sources . length + 1 ;
463- setSources ( [
464- ...sources ,
465- {
466- id : newId ,
467- name : `Source ${ newId } ` ,
468- selectedLanguage : "pytorch" ,
469- code : defaultPyTorchCode ,
470- irWindows : [
471- {
472- id : 1 ,
473- selectedIR : "torch_script_graph_ir" ,
474- output : "Select IR and Generate" ,
475- collapsed : false ,
476- loading : false ,
477- pipeline : [ ] ,
478- dumpAfterEachOpt : false ,
479- } ,
480- ] ,
481- customToolCmd : { } ,
482- } ,
483- ] ) ;
484- setActiveSourceId ( newId ) ;
484+ </ div >
485+ < div
486+ style = { {
487+ display : "flex" ,
488+ alignItems : "center" ,
489+ padding : "4px 10px" ,
490+ } }
491+ >
492+ < Tabs
493+ activeKey = { String ( activeSourceId ) }
494+ type = "editable-card"
495+ hideAdd
496+ onChange = { ( key ) => setActiveSourceId ( Number ( key ) ) }
497+ onEdit = { ( targetKey , action ) => {
498+ if ( action === "remove" ) {
499+ setSources ( ( prev ) => {
500+ const next = prev . filter (
501+ ( src ) => String ( src . id ) !== targetKey ,
502+ ) ;
503+ // if we just closed the active tab, switch to the first one
504+ if ( String ( activeSourceId ) === targetKey ) {
505+ setActiveSourceId ( next [ 0 ] ?. id ?? null ) ;
506+ }
507+ return next ;
508+ } ) ;
509+ }
485510 } }
511+ items = { sources . map ( ( src ) => ( {
512+ key : String ( src . id ) ,
513+ label : `${ src . name } (${ src . selectedLanguage } )` ,
514+ closable : sources . length > 1 ,
515+ } ) ) }
516+ />
517+ < button
518+ onClick = { addSource }
486519 style = { {
487520 display : "flex" ,
488- alignItems : "center" ,
489- justifyContent : "center" ,
490- padding : "2px" ,
491- fontSize : "0.7rem" ,
492- height : "30px" ,
521+ marginLeft : "auto" ,
493522 backgroundColor : "#5fa" ,
523+ fontSize : "0.8rem" ,
524+ color : "black" ,
494525 border : "none" ,
495- borderRadius : "5px " ,
496- fontWeight : "bold " ,
526+ borderRadius : "4px " ,
527+ padding : "4px 8px " ,
497528 cursor : "pointer" ,
498529 } }
499530 >
500531 Add Source
501532 </ button >
502533 </ div >
503- < Tabs
504- activeKey = { `${ activeSourceId } ` }
505- onChange = { ( key ) => setActiveSourceId ( Number ( key ) ) }
506- items = { sourceTabs }
507- style = { { marginLeft : 16 } }
508- />
509534
510535 < select
511536 value = { selectedLanguage }
0 commit comments