hoodini-viz 0.2.11 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{3Dmol-B7Jn9keF.js → 3Dmol-Cbt2auYq.js} +1 -1
- package/dist/{data-grid-overlay-editor-B9dILUeR.js → data-grid-overlay-editor-B4lQDYkP.js} +1 -1
- package/dist/hoodini-viz.css +1 -1
- package/dist/hoodini-viz.js +1 -1
- package/dist/hoodini-viz.umd.js +1 -1
- package/dist/{index-ClbAi_Nj.js → index-DyxBxNIS.js} +686 -673
- package/dist/{number-overlay-editor-DElOzHLj.js → number-overlay-editor-DTkHoOvV.js} +1 -1
- package/package.json +1 -1
package/dist/hoodini-viz.umd.js
CHANGED
|
@@ -76,7 +76,7 @@ ${ln}`,format:"a3m"}}}}],recycling_steps:1,sampling_steps:50,diffusion_samples:1
|
|
|
76
76
|
<path class="st0" d="M61.5,58.4"/>\r
|
|
77
77
|
<line class="st1" x1="63.1" y1="59.8" x2="82" y2="59.8"/>\r
|
|
78
78
|
</svg>\r
|
|
79
|
-
`,hoodiniLogoUrl=(()=>{try{return typeof btoa=="function"?`data:image/svg+xml;base64,${btoa(hoodiniLogoRaw)}`:`data:image/svg+xml;utf8,${encodeURIComponent(hoodiniLogoRaw)}`}catch{return""}})(),getSemaphoreColor=yt=>{const Et=Number(yt)||0;return isFinite(Et)?Et>=90?"#006400":Et>=70?"#7CFC00":Et>=50?"#FFD700":Et>=30?"#FFA500":"#DC143C":"transparent"};function AppSidebar({variant:yt,ultrametric:Et,setUltrametric:xt,showConnectingLines:vt,setShowConnectingLines:bt,showScrollbar:At,setShowScrollbar:Ft,alignLabels:Ct,setAlignLabels:wt,alignCluster:St,setAlignCluster:Tt,useDefaultGeneAlignment:Rt,setUseDefaultGeneAlignment:Pt,defaultAlign:Lt,setDefaultAlign:kt,phyloLabelPosition:Ot,setPhyloLabelPosition:Mt,geneLabelPosition:It,setGeneLabelPosition:Nt,geneColorBy:Ut,setGeneColorBy:jt,treeColorBy:Vt,setTreeColorBy:zt,domainColorBy:Ht,setDomainColorBy:Wt,treeLabelBy:Gt,setTreeLabelBy:qt,geneLabelBy:Xt,setGeneLabelBy:Kt,genePalette:Jt,setGenePalette:tn,phyloPalette:sn,setPhyloPalette:Zt,domainPalette:nn,setDomainPalette:rn,domainSource:on,setDomainSource:ln,ncRNAPalette:Qt,setNcRNAPalette:fn,regionPalette:pn,setRegionPalette:mn,proteinLinkConfig:vn,setProteinLinkConfig:yn,nucleotideLinkConfig:xn,setNucleotideLinkConfig:Mn,treeXScale:$n,setTreeXScale:Rn,viewerLegend:Tn,setViewerLegend:ir,styleConfig:Jn,setStyleConfig:jn,phyloTreeViewerRef:Wn,geneMetadataColumns:br,setGeneMetadataColumns:Fr,treeMetadataColumns:Cr,setTreeMetadataColumns:dr,domainMetadataColumns:_r,setDomainMetadataColumns:pr,selectedGene:wr,handleTrackShiftMinus1kb:xr,handleTrackShiftPlus1kb:Dr,handleTrackFlip:ar,handleArrowheadHeightChange:Qn,handleGeneHeightChange:Cn,tipWidthMode:Bn,setTipWidthMode:In,tipWidthFactor:or,setTipWidthFactor:rr,tipWidthFixed:vr,setTipWidthFixed:cr,showTreeLayer:gn,setShowTreeLayer:wn,showGeneLayer:Xn,setShowGeneLayer:tr,showDomainLayer:Hn,setShowDomainLayer:Kn,showProteinLinkLayer:_n,setShowProteinLinkLayer:yr,showNucleotideLinkLayer:Or,setShowNucleotideLinkLayer:hn,showNcRNALayer:Ar,setShowNcRNALayer:hr,showRegionsLayer:An,setShowRegionsLayer:nr,showGeneTextLayer:gr,setShowGeneTextLayer:ii,showTreeTextLayer:ti,setShowTreeTextLayer:di,showBaselineLayer:Bi,setShowBaselineLayer:as,hasGeneData:ki,hasDomainData:Xi,hasProteinLinkData:_i,hasNucleotideLinkData:ci,hasNcRNAData:xi,hasRegionsData:mi,showFormatGuides:wi,setShowFormatGuides:vi,formatGuidePreset:qi,setFormatGuidePreset:ji,scaleExportToFormat:Ni,setScaleExportToFormat:ls,cropToGuides:xs,setCropToGuides:$s,scaleRulerWithCrop:Is,setScaleRulerWithCrop:Hs,ySpacing:ws,setYSpacing:Es,phyloLabelSize:Ds,setPhyloLabelSize:Fa,geneLabelSize:Ja,setGeneLabelSize:oa,strokeLineWidth:aa,setStrokeLineWidth:Mi,genomeXScale:Wa,setGenomeXScale:Wi,arrowheadHeight:Mo,geneHeight:ys,...Va}){const{resolvedTheme:io,getThemeColors:Fo}=useTheme(),_o=reactExports.useMemo(()=>Fo(io),[io]),[lo,Do]=reactExports.useState("info"),[Cl,ta]=reactExports.useState(!1),ma=typeof Et<"u"?Et:Cl,cs=typeof xt=="function"?xt:ta,[wa,la]=reactExports.useState(!1),Sa=typeof vt<"u"?vt:wa,Io=typeof bt=="function"?bt:la,[xo,Ga]=reactExports.useState(!1),wo=typeof At<"u"?At:xo,Fl=typeof Ft=="function"?Ft:Ga,[ca,za]=reactExports.useState(!1),Uo=typeof Ct<"u"?Ct:ca,Vi=typeof wt=="function"?wt:za,[Os,bs]=reactExports.useState(null),$o=typeof St<"u"?St:Os,al=typeof Tt=="function"?Tt:bs,[qo,Da]=reactExports.useState(!1),qa=typeof Rt<"u"?Rt:qo,Ta=typeof Pt=="function"?Pt:Da,[Zl,$l]=reactExports.useState("start"),Ts=typeof Lt<"u"?Lt:Zl,To=typeof kt=="function"?kt:$l,[Ea,Kr]=reactExports.useState("after-tree"),gs=typeof Ot<"u"?Ot:Ea,Ra=typeof Mt=="function"?Mt:Kr,[po,el]=reactExports.useState(DEFAULT_CONFIG$1.gene.arrowheadHeight),[tl,ll]=reactExports.useState(DEFAULT_CONFIG$1.gene.height),[us,si]=reactExports.useState(DEFAULT_CONFIG$1.gene.tipWidthMode),Un=Bn??us,pi=In??si,[zi,Zi]=reactExports.useState(or??DEFAULT_CONFIG$1.gene.tipWidthFactor),[bi,Fi]=reactExports.useState(vr??DEFAULT_CONFIG$1.gene.tipWidthFixed),[ts,Gi]=reactExports.useState("bottom"),hs=typeof It<"u"?It:ts,Rs=typeof Nt=="function"?Nt:Gi,[vo,go]=reactExports.useState(""),ms=typeof Ut<"u"?Ut:vo,Ii=typeof jt=="function"?jt:go,[Ui,Fs]=reactExports.useState(""),Ws=typeof Vt<"u"?Vt:Ui,Ba=typeof zt=="function"?zt:Fs,[ua,Oo]=reactExports.useState("domainName"),jo=typeof Ht<"u"?Ht:ua,qs=typeof Wt=="function"?Wt:Oo,[Ya,Yo]=reactExports.useState(""),wl=typeof Gt<"u"?Gt:Ya,cl=typeof qt=="function"?qt:Yo,[As,Po]=reactExports.useState(""),da=typeof Xt<"u"?Xt:As,nl=typeof Kt=="function"?Kt:Po,[uo,Ls]=reactExports.useState({enabled:!1}),ya=typeof Jt<"u"?Jt:uo,jl=typeof tn=="function"?tn:Ls,[Ho,hi]=reactExports.useState({enabled:!1}),Bs=typeof sn<"u"?sn:Ho,Li=typeof Zt=="function"?Zt:hi,[_a,na]=reactExports.useState({enabled:!1}),Pl=typeof nn<"u"?nn:_a,lc=typeof rn=="function"?rn:na,[_l,ul]=reactExports.useState("all"),Ec=typeof on<"u"?on:_l,Sl=typeof ln=="function"?ln:ul,[Lo,cc]=reactExports.useState({enabled:!1}),ss=typeof Qt<"u"?Qt:Lo,Dl=typeof fn=="function"?fn:cc,[Ql,so]=reactExports.useState({enabled:!1}),xl=typeof pn<"u"?pn:Ql,Jl=typeof mn=="function"?mn:so,[Ll,uc]=reactExports.useState(null),Xa=typeof vn<"u"?vn:Ll,rl=typeof yn=="function"?yn:uc,[mo,ra]=reactExports.useState(null),dl=typeof xn<"u"?xn:mo,Tl=typeof Mn=="function"?Mn:ra,[Rl,Ma]=reactExports.useState(DEFAULT_CONFIG$1.tree.xScalePercent),[kr,kl]=reactExports.useState(null),bo=typeof Tn<"u"?Tn:kr,[Ys,va]=reactExports.useState(null),dc=typeof Jn<"u"?Jn:Ys,[fc,il]=reactExports.useState(!1),Bl=typeof wi<"u"?wi:fc,sl=typeof vi=="function"?vi:il,[Nl,Ml]=reactExports.useState(null),Hl=typeof qi<"u"?qi:Nl,ko=typeof ji=="function"?ji:Ml,[Zs,En]=reactExports.useState(!1),kn=typeof Ni<"u"?Ni:Zs,Vn=typeof ls=="function"?ls:En,[Nn,Dn]=reactExports.useState(!0),On=typeof xs<"u"?xs:Nn,Pn=typeof $s=="function"?$s:Dn,[Zn,sr]=reactExports.useState(!0),fr=typeof Is<"u"?Is:Zn,mr=typeof Hs=="function"?Hs:sr,[Pr,Ur]=reactExports.useState(DEFAULT_CONFIG$1.tree.ySpacing),[Rr,Wr]=reactExports.useState(DEFAULT_CONFIG$1.tree.ySpacing),$r=typeof Es=="function"?Es:Wr,[qr,Vr]=reactExports.useState(DEFAULT_CONFIG$1.text.phyloLabelSize),[ri,Ei]=reactExports.useState(DEFAULT_CONFIG$1.text.phyloLabelSize),Di=typeof Fa=="function"?Fa:Ei,[Hi,Pi]=reactExports.useState(DEFAULT_CONFIG$1.text.geneLabelSize),[Qi,Si]=reactExports.useState(DEFAULT_CONFIG$1.text.geneLabelSize),Ci=typeof oa=="function"?oa:Si,[Ai,Xs]=reactExports.useState(DEFAULT_CONFIG$1.gene.edgeWidth),[Ks,fa]=reactExports.useState(DEFAULT_CONFIG$1.gene.edgeWidth),ia=typeof Mi=="function"?Mi:fa,[Qs,Ia]=reactExports.useState(DEFAULT_CONFIG$1.genome?.xScalePercent||30),[ba,zl]=reactExports.useState(DEFAULT_CONFIG$1.genome?.xScalePercent||30),Ua=typeof Wi=="function"?Wi:zl,Il=Wn||reactExports.useRef(null),[Oa,Xo]=reactExports.useState(!0),[Pa,Ko]=reactExports.useState(!0),[Zo,Ol]=reactExports.useState(!0),[$a,Aa]=reactExports.useState(!0),[fl,hl]=reactExports.useState(!0),[pl,vl]=reactExports.useState(!0),[bc,zn]=reactExports.useState(!0),[Mr,Br]=reactExports.useState(!0),[Nr,Hr]=reactExports.useState(!0),[Fn,Ln]=reactExports.useState(!0),Gn=gn!==void 0?gn:Oa,er=wn||Xo,Er=Xn!==void 0?Xn:Pa,Tr=tr||Ko,ai=Hn!==void 0?Hn:Zo,Yr=Kn||Ol,li=_n!==void 0?_n:$a,yi=yr||Aa,Ri=Or!==void 0?Or:fl,Ki=hn||hl,ns=Ar!==void 0?Ar:pl,Vs=hr||vl,Ps=An!==void 0?An:bc,ks=nr||zn,Ms=gr!==void 0?gr:Mr,fo=ii||Br,Qo=ti!==void 0?ti:Nr,Jo=di||Hr,ha=Bi!==void 0?Bi:Fn,co=as||Ln,[Ca,Wl]=reactExports.useState(null),[ho,gl]=reactExports.useState("idle"),[sa,Eo]=reactExports.useState(null),[tc,hc]=reactExports.useState(null),Vl=400,Ac="hoodini_nvidia_api_key",[ml,nc]=reactExports.useState(""),[eu,wc]=reactExports.useState(!1),[tu,Nc]=reactExports.useState(null);reactExports.useEffect(()=>{const Gr=localStorage.getItem(Ac);Gr&&nc(Gr)},[]);const[La,en]=reactExports.useState([]),[Sn,dn]=reactExports.useState([]),Yn=reactExports.useCallback(()=>{try{const Gr=Wn&&Wn.current?Wn.current.genomeView:null;if(!Gr){dn([]),en([]);return}const Ti=typeof Gr.getClusterSummary=="function"?Gr.getClusterSummary():null;Ti&&Array.isArray(Ti.items)&&Ti.items.length>0?(en([...Ti.items]),dn([...Ti.ids||[]])):(en([]),dn([]))}catch{dn([]),en([])}},[Wn]);reactExports.useEffect(()=>{Yn()},[]),reactExports.useEffect(()=>{Wn?.current?.genomeView&&setTimeout(()=>{Yn()},100)},[Wn?.current?.genomeView,ki]),reactExports.useEffect(()=>{const Gr=Wn?.current?.genomeView;Gr&&Gr.proteinClusters&&Object.keys(Gr.proteinClusters).length>0&&Yn()},[Wn?.current?.genomeView?.proteinClusters]),reactExports.useEffect(()=>{const Gr=window;return Gr.__hoodini_refreshClusters=()=>(Yn(),{availableClusters:La,liveClusters:Sn}),Gr.__hoodini_clusterState=()=>({availableClusters:La,liveClusters:Sn}),Gr.__hoodini_getGenomeView=()=>Wn&&Wn.current?Wn.current.genomeView:null,()=>{delete Gr.__hoodini_refreshClusters,delete Gr.__hoodini_clusterState,delete Gr.__hoodini_getGenomeView}},[La,Sn,Yn]),reactExports.useEffect(()=>{if(lo!=="settings"||La.length>0)return;const Gr=setInterval(()=>{Yn()},5e3);return()=>clearInterval(Gr)},[lo,La.length,Yn]);const ur=50,lr=reactExports.useMemo(()=>La.slice(0,ur),[La]),ei=reactExports.useMemo(()=>lr.map(Ti=>jsxRuntimeExports.jsx(SelectItem,{value:String(Ti.id),children:Ti.label},Ti.id)),[lr]),zr=br&&br.length>0?br:["cluster","species","geneType"],Yi=Cr&&Cr.length>0?Cr:["species","branchLength","support"],Xr=("".trim().split(/\r?\n/)[0]||"").split(/\t/).map(Gr=>(Gr||"").trim()).filter(Gr=>Gr!==""&&Gr.toLowerCase()!=="domain_id"),eo=["domainName","start","end","evalue","coverage"],$i=Array.isArray(_r)&&_r.length>0?_r.map(Gr=>(Gr||"").toString().trim()).filter(Gr=>Gr!==""&&Gr.toLowerCase()!=="domain_id"):[...eo,...Xr],Qr=wr;reactExports.useEffect(()=>{Wl(null),gl("idle"),Eo(null),to(null),Oi(null),hc(null)},[Qr]);const os=async(Gr,Ti)=>{if(!Gr)return;const rs=Ti||(Gr.length<=Vl?"esmfold":"boltz2");if(rs==="boltz2"&&!ml){gl("needsApiKey"),wc(!0),Wl(Gr);return}if(!(Ca===Gr&&ho==="folding")&&!(sa&&Ca===Gr&&ho==="success")){Wl(Gr),gl("folding"),Nc(rs),Eo(null);try{const es=Qr&&Qr.id||Qr&&Qr.geneId||null;hc(es)}catch{hc(null)}try{to(Gr)}catch{gl("error")}}},Ro=()=>{ml.trim()&&(localStorage.setItem(Ac,ml.trim()),wc(!1),Ca&&ho==="needsApiKey"&&os(Ca,"boltz2"))},Ns=()=>{localStorage.removeItem(Ac),nc("")},[Cs,to]=reactExports.useState(null),[Ss,Oi]=reactExports.useState(null),zs=({pdb:Gr,sequenceLength:Ti,confidence:rs})=>{Eo({pdb:Gr,sequenceLength:Ti,confidence:rs}),gl("success"),Oi(null),Wl(null),to(null)},pa=Qr&&Qr.id||Qr&&Qr.geneId||null;Qr?.metadata?.sequence&&Qr.metadata.sequence.length>0;const ds=!!(pa&&tc&&pa===tc&&(Cs||ho==="success"&&sa)),Js=Gr=>{gl("error"),Oi(Gr||"Unknown viewer error")};return reactExports.useEffect(()=>{},[Cs,ho,sa,Ss]),jsxRuntimeExports.jsxs(Sidebar,{collapsible:"offcanvas",variant:yt,...Va,children:[jsxRuntimeExports.jsx("div",{className:"mx-3 p-1 bg-card/80 backdrop-blur-sm rounded-xl border border-border/50 shadow-sm",style:{backgroundColor:_o.background||void 0},children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"0.5rem",width:"100%"},children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-1 bg-muted/50 p-1 rounded-lg",children:[jsxRuntimeExports.jsx(Button,{variant:lo==="info"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="info"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("info"),title:"Show Info",children:jsxRuntimeExports.jsx(Info,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="settings"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="settings"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("settings"),title:"Show Settings",children:jsxRuntimeExports.jsx(Settings,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="palette"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="palette"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("palette"),title:"Show Palette",children:jsxRuntimeExports.jsx(Palette,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="legend"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="legend"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("legend"),title:"Show Legend",children:jsxRuntimeExports.jsx(BookOpen,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="guides"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="guides"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("guides"),title:"Show Format Guides",children:jsxRuntimeExports.jsx(Crop,{className:"h-3.5 w-3.5"})})]}),jsxRuntimeExports.jsx("a",{href:"#",className:"font-title text-xs font-medium mr-2",style:{display:"flex",alignItems:"center",gap:"0.5rem"},children:jsxRuntimeExports.jsx("img",{src:hoodiniLogoUrl,alt:"Hoodini Logo",className:"!size-5",style:{width:"200px",height:"100px",filter:io==="dark"?"brightness(0) invert(1)":"none"}})})]})}),jsxRuntimeExports.jsxs("div",{className:"mx-3 my-3 p-3 bg-card/60 backdrop-blur-sm rounded-xl border border-border/40 overflow-y-auto scrollbar-hide",style:{backgroundColor:_o.background||void 0,scrollbarWidth:"none",msOverflowStyle:"none"},children:[lo==="info"&&jsxRuntimeExports.jsxs("div",{className:"space-y-3",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Info,{className:"h-3 w-3 mr-1"}),"Information"]})}),jsxRuntimeExports.jsx("div",{className:"space-y-2",children:Qr?jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"info",className:"text-xs",children:Qr.type==="ncRNA"||Qr.type==="ncRNA_gene"?"ncRNA Details":Qr.type==="region"?"Region Details":"Gene Details"})}),jsxRuntimeExports.jsx("div",{className:"space-y-3",children:Qr.metadata&&Object.keys(Qr.metadata).length>0?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[(()=>{const Gr=es=>{const yo={};return!es||typeof es!="string"||es.split(";").filter(Bo=>Bo.trim()).forEach(Bo=>{const[El,...yc]=Bo.split("=");El&&yc.length>0&&(yo[El.trim()]=yc.join("=").trim())}),yo},Ti=Qr.metadata.attributes&&typeof Qr.metadata.attributes=="string"?Gr(Qr.metadata.attributes):typeof Qr.metadata.attributes=="object"?Qr.metadata.attributes:{},rs={...Qr.metadata};return Ti&&Object.keys(Ti).length>0&&Object.entries(Ti).forEach(([es,yo])=>{(!rs[es]||rs[es]===rs.attributes)&&(rs[es]=yo)}),delete rs.attributes,Qr._mergedMeta=rs,null})(),(()=>{const Ti=(()=>{const es=ms||"cluster";if(ya?.enabled&&Il?.current)try{let Bo=Qr?.metadata?.[es];if((Bo==null||Bo==="")&&es==="cluster"&&(Bo=Qr?.metadata?.clusterId??Qr?.metadata?.cluster_id??Qr?.cluster),!isEmptyValue(Bo)&&typeof Il.current.geneColorMap<"u"){const El=Il.current.geneColorMap;if(El&&typeof El.get=="function"){const yc=El.get(normalizeKey(Bo));if(yc&&Array.isArray(yc)){const[_c,ou,Yu,au]=yc;return`rgba(${_c}, ${ou}, ${Yu}, ${au!==void 0?au/255:1})`}}}}catch{}if(Qr.fillColor&&Array.isArray(Qr.fillColor)){const[Bo,El,yc,_c]=Qr.fillColor;return`rgba(${Bo}, ${El}, ${yc}, ${_c!==void 0?_c/255:1})`}return Qr.color||"#666"})(),rs=Qr._mergedMeta||Qr.metadata;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[!isEmptyValue(rs.product)&&jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:ms==="product"?"default":"outline",className:`text-xs flex-shrink-0 ${ms==="product"?"border-0":""}`,style:ms==="product"?{backgroundColor:Ti,border:"none"}:{},children:"Product"}),jsxRuntimeExports.jsx("p",{className:"text-xs break-all leading-relaxed flex-1",children:String(rs.product)})]}),!isEmptyValue(rs.cluster)&&jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:ms==="cluster"?"default":"outline",className:`text-xs flex-shrink-0 ${ms==="cluster"?"border-0":""}`,style:ms==="cluster"?{backgroundColor:Ti,color:"white",border:"none"}:{},children:"Cluster"}),jsxRuntimeExports.jsx("p",{className:"text-xs break-all leading-relaxed flex-1",children:String(rs.cluster)})]}),Object.entries(rs).filter(([es,yo])=>!["product","cluster","sequence","structure","clusterId","cluster_id","attributes"].includes(es)&&!isEmptyValue(yo)).map(([es,yo])=>{const Bo=ms===es;return jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:Bo?"default":"outline",className:`text-xs capitalize flex-shrink-0 ${Bo?"border-0":""}`,style:Bo?{backgroundColor:Ti,color:"white",border:"none"}:{},children:es.replace(/_/g," ")}),jsxRuntimeExports.jsx("p",{className:"text-xs break-all leading-relaxed flex-1",children:String(yo)})]},es)}),(Qr.type==="ncRNA"||Qr.type==="ncRNA_gene")&&Qr.metadata.sequence&&jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs",children:"ncRNA Sequence"}),(()=>{const es=Qr.metadata.sequence.replace(/\*+$/,"");return jsxRuntimeExports.jsxs("span",{className:"text-xs text-muted-foreground",children:["Length ",es.length," nt"]})})()]}),jsxRuntimeExports.jsx("div",{className:"mt-1 p-2 bg-muted rounded text-xs font-mono break-all leading-relaxed",children:Qr.metadata.sequence.replace(/\*+$/,"")}),Qr.metadata.structure&&jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsx(ErrorBoundary,{fallback:jsxRuntimeExports.jsx("div",{className:"text-xs text-muted-foreground",children:"RNA viewer error"}),children:jsxRuntimeExports.jsx(RNAStructureViewer,{sequence:Qr.metadata.sequence?.replace(/\*+$/,"")||"",dotBracket:String(Qr.metadata.structure)||""})}),jsxRuntimeExports.jsxs(Collapsible,{children:[jsxRuntimeExports.jsxs(CollapsibleTrigger,{className:"flex items-center gap-2 w-full hover:bg-muted/50 rounded p-1 -ml-1",children:[jsxRuntimeExports.jsx(ChevronRight,{className:"h-3 w-3 transition-transform duration-200 [[data-state=open]>&]:rotate-90"}),jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs",children:"Dot-bracket"}),jsxRuntimeExports.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",String(Qr.metadata.structure).length," chars)"]})]}),jsxRuntimeExports.jsx(CollapsibleContent,{children:jsxRuntimeExports.jsx("div",{className:"mt-1 p-2 bg-muted rounded text-xs font-mono",style:{wordBreak:"break-word",whiteSpace:"pre-wrap",overflowWrap:"break-word"},children:String(Qr.metadata.structure)})})]})]})]}),!(Qr.type==="ncRNA"||Qr.type==="ncRNA_gene")&&Qr.metadata.sequence&&jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs",children:"Protein Sequence"}),(()=>{const es=Qr.metadata.sequence.replace(/\*+$/,""),yo=es.length>Vl;return jsxRuntimeExports.jsxs(Badge,{variant:ho==="folding"||ho==="success"?"default":ho==="error"?"destructive":ho==="needsApiKey"?"outline":"secondary",className:`text-xs ${ho==="folding"?"animate-pulse":ho==="idle"||ho==="needsApiKey"?"cursor-pointer hover:bg-secondary/80":""} ${yo?"bg-purple-100 text-purple-800 dark:bg-purple-900/50 dark:text-purple-200":""}`,onClick:()=>{ho==="idle"||ho==="needsApiKey"?(Oi(null),os(es)):(ho==="success"||ho==="error")&&(gl("idle"),Eo(null),Wl(null),Nc(null))},children:[ho==="idle"&&(yo?"Fold with Boltz2":"Fold Sequence"),ho==="needsApiKey"&&"🔑 Enter API Key",ho==="folding"&&(tu==="boltz2"?"Boltz2...":"Folding..."),ho==="success"&&"View Structure",ho==="error"&&"Retry Folding"]})})(),Qr.metadata.sequence.replace(/\*+$/,"").length>Vl&&ml&&!eu&&ho!=="needsApiKey"?jsxRuntimeExports.jsx(Badge,{variant:"secondary",className:"text-xs bg-green-100 text-green-700 dark:bg-green-900/50 dark:text-green-300 cursor-pointer hover:bg-green-200 dark:hover:bg-green-800/50 px-2",onClick:()=>wc(!0),title:"API key saved - click to manage",children:jsxRuntimeExports.jsx(Key,{className:"h-3 w-3"})}):null]}),(eu||ho==="needsApiKey")&&jsxRuntimeExports.jsxs("div",{className:"p-3 bg-purple-50 dark:bg-purple-950/30 rounded-md border border-purple-200 dark:border-purple-800 space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx("span",{className:"text-xs font-medium text-purple-800 dark:text-purple-200",children:"NVIDIA API Key (for Boltz2)"}),ml&&jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200",children:"✓ Saved"})]}),jsxRuntimeExports.jsxs("div",{className:"flex gap-2",children:[jsxRuntimeExports.jsx(Input$2,{type:"password",placeholder:"nvapi-...",value:ml,onChange:es=>nc(es.target.value),className:"flex-1 font-mono text-xs h-8"}),jsxRuntimeExports.jsx(Button,{size:"sm",onClick:Ro,disabled:!ml.trim(),className:"h-8 text-xs rounded-full px-4",children:"Save & Fold"})]}),jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground",children:["Get your key at"," ",jsxRuntimeExports.jsx("a",{href:"https://build.nvidia.com/mit/boltz2",target:"_blank",rel:"noopener noreferrer",className:"text-purple-600 dark:text-purple-400 underline hover:no-underline",children:"build.nvidia.com"})," ","• Stored locally in your browser"]}),ml&&jsxRuntimeExports.jsx(Button,{variant:"ghost",size:"sm",onClick:Ns,className:"h-6 text-xs text-destructive hover:text-destructive",children:"Clear saved key"})]}),jsxRuntimeExports.jsx("div",{className:"mt-1 p-2 bg-muted rounded text-xs font-mono break-all leading-relaxed",children:Qr.metadata.sequence.replace(/\*+$/,"")}),(()=>{const es=Qr.metadata.sequence.replace(/\*+$/,""),yo=es.length>Vl;return jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground",children:["Sequence length: ",es.length," aa",yo?` (requires Boltz2, >${Vl} aa)`:" (ESMFold compatible)"]})})(),ds&&jsxRuntimeExports.jsxs("div",{className:"mt-2 p-3 bg-accent/10 rounded-md border",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between mb-2",children:[jsxRuntimeExports.jsx("h5",{className:"font-title text-xs font-medium",children:"3D Structure"}),(()=>{const es=sa&&typeof sa.confidence=="number"?sa.confidence:null,yo=es!==null?es<=1?es*100:es:null,Bo=yo!==null?getSemaphoreColor(yo):"transparent",El=yo!==null&&yo>50?"#000":"#fff";return jsxRuntimeExports.jsxs(Badge,{variant:"outline",className:"text-xs font-medium text-white border-0",style:{backgroundColor:Bo,color:El,border:yo===null?"1px dashed rgba(255,255,255,0.12)":void 0},children:["avg pLDDT: ",yo!==null?`${yo.toFixed(0)}%`:ho==="folding"?"loading...":"n/a"]})})()]}),jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(ProteinViewer,{sequence:Cs,pdbData:sa?.pdb,confidence:sa?.confidence,sequenceLength:sa?.sequenceLength,onStructureReady:zs,onError:Js,themeBackground:_o.background},`${Qr?.id||Qr?.geneId||"selected"}`)}),Ss?jsxRuntimeExports.jsxs("div",{className:"mt-2 p-2 bg-destructive/10 rounded border border-destructive/20 text-xs text-destructive",children:[jsxRuntimeExports.jsx("div",{className:"font-medium text-xs",children:"Viewer error"}),jsxRuntimeExports.jsx("div",{className:"text-xs mt-1",children:String(Ss)})]}):jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:["Structure predicted using ",tu==="boltz2"?"Boltz2":"ESMFold"," • ",sa?.sequenceLength||Cs?.length||"..."," residues"]})]})]})]})})()]}):jsxRuntimeExports.jsx("div",{className:"text-muted-foreground text-xs",children:"No metadata available for this gene"})})]}):jsxRuntimeExports.jsxs("div",{className:"p-4 bg-gradient-to-br from-muted/40 to-accent/20 rounded-lg border border-border/30 text-sm leading-relaxed",children:[jsxRuntimeExports.jsxs("div",{className:"text-center mb-4",children:[jsxRuntimeExports.jsx("span",{className:"text-lg font-semibold",children:"Hoodini 🦉🎩"}),jsxRuntimeExports.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Gene Neighborhood Visualization"})]}),jsxRuntimeExports.jsxs("div",{className:"space-y-2 text-xs",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2 p-2 bg-background/50 rounded-md",children:[jsxRuntimeExports.jsx(Badge,{variant:"info",className:"text-xs shrink-0",children:"Settings"}),jsxRuntimeExports.jsx("span",{className:"text-muted-foreground",children:"Configure tree and gene display"})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2 p-2 bg-background/50 rounded-md",children:[jsxRuntimeExports.jsx(Badge,{variant:"success",className:"text-xs shrink-0",children:"Palette"}),jsxRuntimeExports.jsx("span",{className:"text-muted-foreground",children:"Customize colors and styling"})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2 p-2 bg-background/50 rounded-md",children:[jsxRuntimeExports.jsx(Badge,{variant:"warning",className:"text-xs shrink-0",children:"Legend"}),jsxRuntimeExports.jsx("span",{className:"text-muted-foreground",children:"Understand visualization elements"})]})]}),jsxRuntimeExports.jsx("div",{className:"mt-4 p-2 bg-primary/5 rounded-lg text-center border border-primary/10",children:jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground",children:[jsxRuntimeExports.jsx("strong",{className:"text-foreground/80",children:"Click on a gene"})," to see its details"]})})]})})]}),lo==="settings"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Settings,{className:"h-3 w-3 mr-1"}),"Settings"]})}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Layer Visibility"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2 mt-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"baseline-layer",className:"text-xs",children:"Baselines"}),jsxRuntimeExports.jsx(Switch,{id:"baseline-layer",checked:ha,onCheckedChange:co})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-layer",className:"text-xs",children:"Tree Layer"}),jsxRuntimeExports.jsx(Switch,{id:"tree-layer",checked:Gn,onCheckedChange:er})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-text-layer",className:"text-xs",children:"Tree Text"}),jsxRuntimeExports.jsx(Switch,{id:"tree-text-layer",checked:Qo,onCheckedChange:Jo})]}),ki&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-layer",className:"text-xs",children:"Gene Layer"}),jsxRuntimeExports.jsx(Switch,{id:"gene-layer",checked:Er,onCheckedChange:Tr})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-text-layer",className:"text-xs",children:"Gene Text"}),jsxRuntimeExports.jsx(Switch,{id:"gene-text-layer",checked:Ms,onCheckedChange:fo})]})]}),Xi&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"domain-layer",className:"text-xs",children:"Domain Layer"}),jsxRuntimeExports.jsx(Switch,{id:"domain-layer",checked:ai,onCheckedChange:Yr})]}),_i&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"protein-link-layer",className:"text-xs",children:"Protein Links"}),jsxRuntimeExports.jsx(Switch,{id:"protein-link-layer",checked:li,onCheckedChange:yi})]}),ci&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"nucleotide-link-layer",className:"text-xs",children:"Nucleotide Links"}),jsxRuntimeExports.jsx(Switch,{id:"nucleotide-link-layer",checked:Ri,onCheckedChange:Ki})]}),xi&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"ncrna-layer",className:"text-xs",children:"ncRNA Layer"}),jsxRuntimeExports.jsx(Switch,{id:"ncrna-layer",checked:ns,onCheckedChange:Vs})]}),mi&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"regions-layer",className:"text-xs",children:"Regions Layer"}),jsxRuntimeExports.jsx(Switch,{id:"regions-layer",checked:Ps,onCheckedChange:ks})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Gene Settings"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"arrowhead-height",className:"text-xs mb-1 block",children:["Arrowhead Height: ",po]}),jsxRuntimeExports.jsx(Slider,{id:"arrowhead-height",min:0,max:100,value:[po],onValueChange:Gr=>{el(Gr[0])},onValueCommit:Gr=>{typeof Qn=="function"&&Qn(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"gene-height",className:"text-xs mb-1 block",children:["Gene Height: ",tl]}),jsxRuntimeExports.jsx(Slider,{id:"gene-height",min:10,max:200,value:[tl],onValueChange:Gr=>{ll(Gr[0])},onValueCommit:Gr=>{typeof Cn=="function"&&Cn(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tip-width-mode",className:"text-xs mb-1 block",children:"Arrow Tip Width Mode:"}),jsxRuntimeExports.jsxs(Select,{value:Un,onValueChange:Gr=>pi(Gr),children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"tip-width-mode",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"factor",children:"Proportional"}),jsxRuntimeExports.jsx(SelectItem,{value:"fixed",children:"Fixed"})]})]})]}),Un==="factor"?jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"tip-width-factor",className:"text-xs mb-1 block",children:["Tip Factor: ",(zi*100).toFixed(0),"%"]}),jsxRuntimeExports.jsx(Slider,{id:"tip-width-factor",min:1,max:50,value:[zi*100],onValueChange:Gr=>Zi(Gr[0]/100),onValueCommit:Gr=>{typeof rr=="function"&&rr(Gr[0]/100)},className:"w-full"})]}):jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"tip-width-fixed",className:"text-xs mb-1 flex items-center justify-between",children:[jsxRuntimeExports.jsxs("span",{children:["Fixed Tip Width: ",bi," nt"]}),jsxRuntimeExports.jsx("span",{className:"text-[10px] text-muted-foreground",children:"max 50% of gene"})]}),jsxRuntimeExports.jsx(Slider,{id:"tip-width-fixed",min:0,max:1e3,step:10,value:[bi],onValueChange:Gr=>Fi(Gr[0]),onValueCommit:Gr=>{typeof cr=="function"&&cr(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-label-position",className:"text-xs mb-1 block",children:"Gene Label Position:"}),jsxRuntimeExports.jsxs(Select,{value:hs,onValueChange:Rs,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"gene-label-position",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"bottom",children:"Bottom"}),jsxRuntimeExports.jsx(SelectItem,{value:"center",children:"Center"}),jsxRuntimeExports.jsx(SelectItem,{value:"top",children:"Top"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"gene-label-size",className:"text-xs mb-1 block",children:["Gene Label Size: ",Hi,"px"]}),jsxRuntimeExports.jsx(Slider,{id:"gene-label-size",min:6,max:30,value:[Hi],onValueChange:Gr=>Pi(Gr[0]),onValueCommit:Gr=>{typeof Ci=="function"&&Ci(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-label-by",className:"text-xs mb-1 block",children:"Gene Label By:"}),jsxRuntimeExports.jsx(MultiSelect,{options:["gene_id",...zr].map(Gr=>({label:Gr,value:Gr})),value:da?da.split(",").filter(Boolean):[],onValueChange:Gr=>nl(Gr.length>0?Gr.join(","):""),placeholder:"Select columns...",maxCount:2,className:"text-xs"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"stroke-line-width",className:"text-xs mb-1 block",children:["Stroke Width: ",Ai.toFixed(1)]}),jsxRuntimeExports.jsx(Slider,{id:"stroke-line-width",min:.1,max:3,step:.1,value:[Ai],onValueChange:Gr=>Xs(Gr[0]),onValueCommit:Gr=>{typeof ia=="function"&&ia(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"genome-x-scale",className:"text-xs mb-1 block",children:["Genome X-Scale: ",Qs,"%"]}),jsxRuntimeExports.jsx(Slider,{id:"genome-x-scale",min:1,max:100,value:[Qs],onValueChange:Gr=>Ia(Gr[0]),onValueCommit:Gr=>{typeof Ua=="function"&&Ua(Gr[0])},className:"w-full"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Tree Settings"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"ultrametric",className:"text-xs",children:"Ultrametric Tree"}),jsxRuntimeExports.jsx(Switch,{id:"ultrametric",checked:ma,onCheckedChange:cs})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"connecting-lines",className:"text-xs",children:"Connecting Lines"}),jsxRuntimeExports.jsx(Switch,{id:"connecting-lines",checked:Sa,onCheckedChange:Io})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"scrollbar",className:"text-xs",children:"Show Scrollbar"}),jsxRuntimeExports.jsx(Switch,{id:"scrollbar",checked:wo,onCheckedChange:Fl})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"align-labels",className:"text-xs",children:"Align Labels"}),jsxRuntimeExports.jsx(Switch,{id:"align-labels",checked:Uo,onCheckedChange:Vi})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"phylo-position",className:"text-xs mb-1 block",children:"Phylo Label Position:"}),jsxRuntimeExports.jsxs(Select,{value:gs,onValueChange:Ra,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"phylo-position",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"after-tree",children:"After Tree"}),jsxRuntimeExports.jsx(SelectItem,{value:"after-tracks",children:"After Tracks"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"tree-x-scale",className:"text-xs mb-1 block",children:["Tree X-Scale: ",Rl,"%"]}),jsxRuntimeExports.jsx(Slider,{id:"tree-x-scale",min:10,max:300,value:[Rl],onValueChange:Gr=>{Ma(Gr[0])},onValueCommit:Gr=>{typeof Rn=="function"&&Rn(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"y-spacing",className:"text-xs mb-1 block",children:["Y Spacing: ",Pr,"px"]}),jsxRuntimeExports.jsx(Slider,{id:"y-spacing",min:50,max:500,step:10,value:[Pr],onValueChange:Gr=>Ur(Gr[0]),onValueCommit:Gr=>{typeof $r=="function"&&$r(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"phylo-label-size",className:"text-xs mb-1 block",children:["Phylo Label Size: ",qr,"px"]}),jsxRuntimeExports.jsx(Slider,{id:"phylo-label-size",min:8,max:40,value:[qr],onValueChange:Gr=>Vr(Gr[0]),onValueCommit:Gr=>{typeof Di=="function"&&Di(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-label-by",className:"text-xs mb-1 block",children:"Tree Label By:"}),jsxRuntimeExports.jsx(MultiSelect,{options:["name",...Yi].map(Gr=>({label:Gr,value:Gr})),value:wl?wl.split(",").filter(Boolean):[],onValueChange:Gr=>cl(Gr.length>0?Gr.join(","):""),placeholder:"Select columns...",maxCount:2,className:"text-xs"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Alignment Controls"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"hoods-alignment",className:"text-xs mb-1 block",children:"Hoods Alignment:"}),jsxRuntimeExports.jsxs(Select,{value:qa?"default":Ts,onValueChange:Gr=>{Gr==="default"?(Ta(!0),al(null)):(Ta(!1),To(Gr),al(null))},children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"hoods-alignment",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"center",children:"Center"}),jsxRuntimeExports.jsx(SelectItem,{value:"start",children:"Start"}),jsxRuntimeExports.jsx(SelectItem,{value:"end",children:"End"}),jsxRuntimeExports.jsx(SelectItem,{value:"default",children:"Default"})]})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"gene-alignment",className:"text-xs mb-1 block",children:["Gene Alignment: ",La.length>ur?`top ${ur} of ${La.length}`:`${La.length} clusters`]}),jsxRuntimeExports.jsx(Button,{size:"sm",variant:"ghost",onClick:Yn,style:{height:"20px",minHeight:"20px"},children:"Refresh"})]}),jsxRuntimeExports.jsxs(Select,{value:$o!=null?String($o):"none",onValueChange:Gr=>{const Ti=Gr==="none"||Gr==="__more__"?null:String(Gr),rs=window;if(typeof rs.__hoodini_alignCluster=="function")Ti!==null&&rs.__hoodini_alignCluster(Ti);else{al(Ti),Ti!==null&&Ta(!1);try{const es=Il?.current||null;Ti===null?es?.alignByDefaultGenes&&es.alignByDefaultGenes():es?.alignCluster?es.alignCluster(Ti):es?.genomeView?.alignCluster?.(Ti),es?.forceAlignUpdate?.()}catch{}}},children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"gene-alignment",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"none",children:"No Cluster"}),ei,La.length>ur&&jsxRuntimeExports.jsxs(SelectItem,{value:"__more__",disabled:!0,children:["... and ",La.length-ur," more (use console)"]})]})]})]})]})]})]}),lo==="palette"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Palette,{className:"h-3 w-3 mr-1"}),"Color & Palette"]})}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Color Fields"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-colors",className:"text-xs mb-1 block",children:"Gene Colors:"}),jsxRuntimeExports.jsxs(Select,{value:ms,onValueChange:Ii,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"gene-colors",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsx(SelectContent,{children:zr.map(Gr=>jsxRuntimeExports.jsx(SelectItem,{value:Gr,children:Gr},Gr))})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-colors",className:"text-xs mb-1 block",children:"Tree Colors:"}),jsxRuntimeExports.jsxs(Select,{value:Ws,onValueChange:Ba,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"tree-colors",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsx(SelectContent,{children:Yi.map(Gr=>jsxRuntimeExports.jsx(SelectItem,{value:Gr,children:Gr},Gr))})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"domain-colors",className:"text-xs mb-1 block",children:"Domain Colors:"}),jsxRuntimeExports.jsxs(Select,{value:jo,onValueChange:qs,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"domain-colors",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsx(SelectContent,{children:$i.map(Gr=>jsxRuntimeExports.jsx(SelectItem,{value:Gr,children:Gr},Gr))})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"domain-source",className:"text-xs mb-1 block",children:"Domain Source:"}),jsxRuntimeExports.jsxs(Select,{value:Ec||"all",onValueChange:Gr=>{try{typeof Sl=="function"?Sl(Gr):Va&&typeof Va.setDomainSource=="function"&&Va.setDomainSource(Gr)}catch{}},children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"domain-source",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"all",children:"all"}),(()=>{try{const Gr=Wn&&Wn.current?Wn.current.genomeView:null;if(!Gr)return null;const Ti=Gr.getAllDomains?Gr.getAllDomains():[];return Array.from(new Set(Ti.map(es=>String(es&&(es.source||es.metadata&&es.metadata.source)||"unknown")))).sort().map(es=>jsxRuntimeExports.jsx(SelectItem,{value:String(es),children:String(es)},String(es)))}catch{return null}})()]})]})]})]})]}),jsxRuntimeExports.jsx(Separator,{className:"my-2"}),jsxRuntimeExports.jsx("div",{className:"mb-3",children:jsxRuntimeExports.jsx(UnifiedPaletteWidget,{genePalette:ya,setGenePalette:jl,phyloPalette:Bs,setPhyloPalette:Li,domainPalette:Pl,setDomainPalette:lc,ncRNAPalette:ss,setNcRNAPalette:Dl,regionPalette:xl,setRegionPalette:Jl,availableData:{parsedGFF:[1],parsedDomains:Xi?[1]:[],phyloData:[1],ncRNAFeatures:[1],regionFeatures:[1]}})}),jsxRuntimeExports.jsx(Separator,{className:"my-2"}),jsxRuntimeExports.jsxs("div",{className:"mb-3",children:[jsxRuntimeExports.jsx(Label,{className:"text-xs font-medium mb-1 block",children:"Links Color Selection:"}),jsxRuntimeExports.jsx("div",{className:"space-y-1",children:jsxRuntimeExports.jsx(LinkColorWidget,{proteinLinkConfig:Xa,nucleotideLinkConfig:dl,onProteinLinkConfigChange:rl,onNucleotideLinkConfigChange:Tl})})]})]}),lo==="legend"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(BookOpen,{className:"h-3 w-3 mr-1"}),"Legend"]})}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Visualization Legend"})}),jsxRuntimeExports.jsx("div",{className:"space-y-2",children:bo?jsxRuntimeExports.jsx(LegendWidget,{legend:bo,genePalette:ya,phyloPalette:Bs,regionPalette:xl,proteinLinkConfig:Xa,nucleotideLinkConfig:dl,styleConfig:dc,className:"",style:{}}):jsxRuntimeExports.jsxs("div",{className:"p-3 bg-accent/30 rounded-lg text-center",children:[jsxRuntimeExports.jsx("p",{className:"text-xs text-muted-foreground mb-1",children:"No legend data available yet"}),jsxRuntimeExports.jsx("p",{className:"text-xs text-muted-foreground",children:"Legend will appear once data is loaded"})]})})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Guide"})}),jsxRuntimeExports.jsxs("div",{className:"text-xs space-y-2 text-muted-foreground",children:[jsxRuntimeExports.jsxs("div",{className:"p-2 bg-accent/20 rounded-md",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1 text-foreground/80",children:"Gene Tracks:"}),jsxRuntimeExports.jsx("p",{children:"• Arrows indicate gene direction and boundaries"}),jsxRuntimeExports.jsx("p",{children:"• Colors represent different metadata categories"})]}),jsxRuntimeExports.jsxs("div",{className:"p-2 bg-accent/20 rounded-md",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1 text-foreground/80",children:"Phylogenetic Tree:"}),jsxRuntimeExports.jsx("p",{children:"• Branch lengths show evolutionary distance"}),jsxRuntimeExports.jsx("p",{children:"• Node colors represent tree metadata"})]}),jsxRuntimeExports.jsxs("div",{className:"p-2 bg-accent/20 rounded-md",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1 text-foreground/80",children:"Protein Domains:"}),jsxRuntimeExports.jsx("p",{children:"• Colored regions within genes"}),jsxRuntimeExports.jsx("p",{children:"• Represent functional protein domains"})]}),jsxRuntimeExports.jsxs("div",{className:"p-2 bg-muted/50 rounded",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1",children:"Links:"}),jsxRuntimeExports.jsx("p",{children:"• Connect related elements across tracks"}),jsxRuntimeExports.jsx("p",{children:"• Show protein or nucleotide relationships"})]})]})]})]}),lo==="guides"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Crop,{className:"h-3 w-3 mr-1"}),"Format Guides"]})}),jsxRuntimeExports.jsx("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:jsxRuntimeExports.jsx(GuideControlsWidget,{guidesVisible:Bl,selectedFormat:Hl,onGuidesVisibleChange:sl,onFormatChange:ko,scaleToFormat:kn,onScaleToFormatChange:Vn,cropToGuides:On,onCropToGuidesChange:Pn,scaleRulerWithCrop:fr,onScaleRulerWithCropChange:mr})})]})]})]})}function SVGExportButton({phyloTreeViewerRef:yt}){const Et=()=>{try{console.log("🖼️ SVGExportButton clicked, ref:",yt.current),console.log("🖼️ exportToSVG method:",yt.current?.exportToSVG),yt.current?.exportToSVG?.()}catch(xt){console.error("🖼️ SVGExportButton error:",xt)}};return jsxRuntimeExports.jsxs(Button,{variant:"ghost",size:"icon",className:"size-7 sm:size-7 min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center border touch-manipulation",onClick:Et,title:"Export current view to SVG",children:[jsxRuntimeExports.jsx(Camera,{size:16}),jsxRuntimeExports.jsx("span",{className:"sr-only",children:"Export SVG"})]})}function ThemeToggle(){const{theme:yt,resolvedTheme:Et,toggleTheme:xt}=useTheme(),vt=Et||yt||"light";return jsxRuntimeExports.jsxs(Button,{variant:"ghost",size:"icon",className:"size-7 sm:size-7 min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center border touch-manipulation",onClick:xt,title:`Switch to ${vt==="light"?"dark":"light"} theme`,children:[vt==="light"?jsxRuntimeExports.jsx(Moon,{size:16}):jsxRuntimeExports.jsx(Sun,{size:16}),jsxRuntimeExports.jsx("span",{className:"sr-only",children:"Toggle theme"})]})}class PhyloNode{constructor(){this.id=null,this.name=null,this.branchLength=0,this.parent=null,this.branchset=[],this.x=0,this.y=0,this.rootDist=0}getLeaves(){return this.branchset.length===0?[this]:this.branchset.flatMap(Et=>Et.getLeaves())}}class PhyloTree{constructor(Et,xt=DEFAULT_CONFIG$1,vt=!1,bt=null){if(this.config=xt,this.themeColors=bt,this.allNodes=[],this.leafNodes=[],Array.isArray(Et))this.hasTree=!1,this.root=this._createFlatRoot(Et);else if(!Et||Et.trim()==="")this.hasTree=!1,this.root=new PhyloNode,this.root.id=0;else try{this.root=this.parseNewick(Et),this.hasTree=!0}catch(At){console.warn("[PhyloTree] failed to parse Newick; using empty tree",At?.message||At),this.hasTree=!1,this.root=new PhyloNode,this.root.id=0}this.collectAll(),this.hasTree&&this.ladderize(!1),vt&&this.hasTree&&this.makeUltrametric()}_createFlatRoot(Et){const xt=new PhyloNode;return xt.id=0,xt.branchLength=0,xt.name="_root",Et.forEach((vt,bt)=>{const At=new PhyloNode;At.id=bt+1,At.name=String(vt),At.branchLength=1,xt.branchset.push(At)}),xt}parseNewick(Et){for(var xt=[],vt=new PhyloNode,bt=Et.split(/\s*(;|\(|\)|,|:)\s*/),At=0,Ft=0;Ft<bt.length;Ft++){var Ct=bt[Ft];switch(Ct){case"(":{var wt=new PhyloNode;wt.id=At++,vt.branchset=[wt],xt.push(vt),vt=wt;break}case",":{var wt=new PhyloNode;wt.id=At++,xt[xt.length-1].branchset.push(wt),vt=wt;break}case")":vt=xt.pop();break;case":":break;default:{var St=bt[Ft-1];St==")"||St=="("||St==","?vt.name=Ct:St==":"&&(vt.branchLength=parseFloat(Ct)),vt.id=vt.id!==null?vt.id:At++}}}return vt}ladderize(Et=!0){const xt=[],vt=[this.root];let bt=0;for(;vt.length>0;){const Ft=vt.pop();if(xt.push(Ft),Ft._sortIndex=bt++,Ft.branchset)for(const Ct of Ft.branchset)vt.push(Ct)}for(let Ft=xt.length-1;Ft>=0;Ft--){const Ct=xt[Ft];if(!Ct.branchset||Ct.branchset.length===0)Ct.num_tips=1;else{Ct.num_tips=0;for(const wt of Ct.branchset)Ct.num_tips+=wt.num_tips||1}}const At=[this.root];for(;At.length>0;){const Ft=At.pop();if(Ft.branchset&&Ft.branchset.length>0){Ft.branchset.sort((Ct,wt)=>{const St=Ct.num_tips||1,Tt=wt.num_tips||1;return St!==Tt?Et?St-Tt:Tt-St:(Ct._sortIndex||0)-(wt._sortIndex||0)});for(const Ct of Ft.branchset)At.push(Ct)}}this.collectAll()}collectAll(){this.allNodes=[];const Et=xt=>{this.allNodes.push(xt);for(let vt of xt.branchset)Et(vt)};Et(this.root)}setParents(){const Et=(xt,vt=null)=>{xt.parent=vt;for(let bt of xt.branchset)Et(bt,xt)};Et(this.root,null)}computeDistances(){const Et=xt=>{xt.rootDist=(xt.parent?xt.parent.rootDist:0)+(xt.branchLength||0);for(let vt of xt.branchset)Et(vt)};Et(this.root)}getLeafNodes(){return this.root.getLeaves()}assignX(Et){const xt=this.config.tree.ySpacing;for(let vt=0;vt<Et.length;vt++)Et[vt].x=vt*xt}assignInternalX(Et){if(Et.branchset.length===0)return Et.x;const xt=Et.branchset.map(vt=>this.assignInternalX(vt));return Et.x=xt.reduce((vt,bt)=>vt+bt,0)/xt.length,Et.x}scaleY(){const Et=this.allNodes.map(At=>At.rootDist),xt=Math.max(...Et),vt=this.config.tree.fixedCoordinateWidth||2e3,bt=xt>0?vt/xt:1;this.maxEvolutionaryDistance=xt;for(let At of this.allNodes)At.y=At.rootDist*bt}layout(Et){this.setParents(),Et?(this.leafNodes=this.getLeafNodes(),this.leafNodes.sort((xt,vt)=>Et.indexOf(xt.name)-Et.indexOf(vt.name)),this.assignX(this.leafNodes)):(this.leafNodes=this.getLeafNodes(),this.assignX(this.leafNodes)),this.assignInternalX(this.root),this.computeDistances(),this.scaleY()}buildEdges(){const Et=[],xt=this.themeColors?.treeEdges||this.config.tree.edgeColor||[85,85,85,255],vt=bt=>{for(let At of bt.branchset){const Ft=[[bt.y,bt.x],[bt.y,At.x],[At.y,At.x]];Et.push({path:Ft,color:xt,source:bt,target:At}),vt(At)}};return vt(this.root),Et}makeUltrametric(){(!this.allNodes||this.allNodes.length===0)&&this.collectAll(),this.setParents(),this.computeDistances();const Et=this.getLeafNodes(),xt=Math.max(...Et.map(At=>At.rootDist)),vt=At=>{if(At.branchset.length===0){At.rootDist=xt;return}for(let wt of At.branchset)vt(wt);const Ft=At.branchset.map(wt=>wt.rootDist),Ct=Math.min(...Ft);At.rootDist=Ct-Math.max(...At.branchset.map(wt=>wt.branchLength||0)),At.rootDist<0&&(At.rootDist=0)};vt(this.root);const bt=At=>{for(let Ft of At.branchset)Ft.branchLength=Ft.rootDist-At.rootDist,bt(Ft)};this.root.rootDist=0,bt(this.root),this.computeDistances()}}class GFFFeature{constructor(Et,xt,vt,bt,At,Ft){this.seqid=Et,this.start=xt,this.end=vt,this.strand=bt,this.type=At,this.attributes=Ft}}class Gene extends GFFFeature{constructor(Et,xt,vt,bt,At,Ft=DEFAULT_CONFIG$1){super(Et,xt,vt,bt,"gene",At),this.origStart=xt,this.origEnd=vt,this.origStrand=bt,this.domains=[],this.config=Ft||DEFAULT_CONFIG$1,this.fillColor=this.config.gene.fillColor,this.polygon=null,this.trackY=null,this.geneHeight=this.config.gene.height||this.config.gene.defaultHeight,this.centerLine=[],this.metadata={seqid:Et,start:xt,end:vt,strand:bt,attributes:At}}setTrackY(Et){this.trackY=Et,this.updatePolygon()}updatePolygon(){this.polygon=this._buildPolygon(this.trackY,this.geneHeight),this.centerLine=this.computeCenterLine();for(let Et of this.domains)Et.updatePolygon()}_buildPolygon(Et,xt){let vt=this.start,bt=this.end;if(vt>bt){const Rt=vt;vt=bt,bt=Rt}const At=Math.abs(bt-vt),Ft=calculateTipWidth(At,this.config),Ct=xt/2,wt=this.strand==="+",St=this.config.gene.arrowheadHeight||0;if(Ft<1)return[[vt,Et-Ct],[bt,Et-Ct],[bt,Et+Ct],[vt,Et+Ct]];if(St<.1)return wt?[[vt,Et-Ct],[bt-Ft,Et-Ct],[bt,Et],[bt-Ft,Et+Ct],[vt,Et+Ct]]:[[bt,Et-Ct],[vt+Ft,Et-Ct],[vt,Et],[vt+Ft,Et+Ct],[bt,Et+Ct]];const Tt=Ct+St/2;return wt?[[vt,Et-Ct],[bt-Ft,Et-Ct],[bt-Ft,Et-Tt],[bt,Et],[bt-Ft,Et+Tt],[bt-Ft,Et+Ct],[vt,Et+Ct]]:[[bt,Et-Ct],[vt+Ft,Et-Ct],[vt+Ft,Et-Tt],[vt,Et],[vt+Ft,Et+Tt],[vt+Ft,Et+Ct],[bt,Et+Ct]]}computeCenterLine(){const Et=this.polygon;if(!Et||Et.length===0)return[];if(Et.length===5){const xt=[(Et[0][0]+Et[4][0])/2,(Et[0][1]+Et[4][1])/2],vt=Et[2];return[xt,vt]}else if(Et.length===7){const xt=[(Et[0][0]+Et[6][0])/2,(Et[0][1]+Et[6][1])/2],vt=Et[3];return[xt,vt]}else if(Et.length===4){const xt=this.strand==="+",vt=[(Et[0][0]+Et[3][0])/2,(Et[0][1]+Et[3][1])/2],bt=[(Et[1][0]+Et[2][0])/2,(Et[1][1]+Et[2][1])/2];return xt?[vt,bt]:[bt,vt]}else{const xt=[(Et[0][0]+Et[Et.length-1][0])/2,(Et[0][1]+Et[Et.length-1][1])/2],vt=Et[Math.floor(Et.length/2)];return[xt,vt]}}addDomain(Et){Et.setParentGene(this),this.domains.push(Et)}}function clipPolygon(yt,Et){if(!yt||yt.length<3)return null;if(!Et||Et.length<3)return yt;let xt=yt.slice();for(let vt=0;vt<Et.length;vt++){if(xt.length===0)return null;const bt=xt;xt=[];const At=Et[vt],Ft=Et[(vt+1)%Et.length];for(let Ct=0;Ct<bt.length;Ct++){const wt=bt[Ct],St=bt[(Ct+bt.length-1)%bt.length],Tt=isInside(wt,At,Ft),Rt=isInside(St,At,Ft);if(Tt){if(!Rt){const Pt=lineIntersection(St,wt,At,Ft);Pt&&xt.push(Pt)}xt.push(wt)}else if(Rt){const Pt=lineIntersection(St,wt,At,Ft);Pt&&xt.push(Pt)}}}return xt.length>=3?xt:null}function isInside(yt,Et,xt){return(xt[0]-Et[0])*(yt[1]-Et[1])-(xt[1]-Et[1])*(yt[0]-Et[0])>=0}function lineIntersection(yt,Et,xt,vt){const bt=Et[0]-yt[0],At=Et[1]-yt[1],Ft=vt[0]-xt[0],Ct=vt[1]-xt[1],wt=bt*Ct-At*Ft;if(Math.abs(wt)<1e-10)return null;const St=xt[0]-yt[0],Tt=xt[1]-yt[1],Rt=(St*Ct-Tt*Ft)/wt;return[yt[0]+Rt*bt,yt[1]+Rt*At]}class Domain{constructor(Et,xt,vt,bt,At,Ft,Ct,wt=DEFAULT_CONFIG$1){this.geneId=Et,this.domainName=xt,this.origStart=vt,this.origEnd=bt,this.start=vt,this.end=bt,this.source=At,this.evalue=Ft,this.coverage=Ct,this.parentGene=null,this.polygon=null;const St=Ft&&Ft>0?Ft<.001?Ft.toExponential(2):Ft.toFixed(6):Ft,Tt=Ct&&`${(Ct*100).toFixed(1)}%`;this.metadata={geneId:Et,domainName:xt,start:vt,end:bt,source:At,evalue:St,coverage:Tt},this.config=wt||DEFAULT_CONFIG$1}setParentGene(Et){this.parentGene=Et,this.updatePolygon()}updatePolygon(){if(!this.parentGene||!this.parentGene.polygon)return;const Et=this.parentGene,xt=this.createDomainPolygon(Et,this.origStart,this.origEnd);if(xt&&Et.polygon){const vt=this.getConvexGenePolygon(Et);this.polygon=clipPolygon(xt,vt)}else this.polygon=xt}getConvexGenePolygon(Et){const xt=Et.geneHeight||Et.config?.gene?.height||60,vt=Et.config?.gene?.arrowheadHeight||0,bt=xt/2,At=bt+vt/2,Ft=Et.trackY;let Ct=Math.min(Et.start,Et.end),wt=Math.max(Et.start,Et.end);const St=wt-Ct,Tt=calculateTipWidth(St,Et.config?.gene),Rt=Et.strand==="+";return Tt<1?[[Ct,Ft-bt],[wt,Ft-bt],[wt,Ft+bt],[Ct,Ft+bt]]:Rt?[[Ct,Ft-bt],[wt-Tt,Ft-At],[wt,Ft],[wt-Tt,Ft+At],[Ct,Ft+bt]]:[[wt,Ft-bt],[Ct+Tt,Ft-At],[Ct,Ft],[Ct+Tt,Ft+At],[wt,Ft+bt]]}createDomainPolygon(Et,xt,vt){const bt=Et.start,At=Et.end,Ft=Math.min(bt,At),wt=Math.max(bt,At)-Ft;if(!Et.centerLine||!Array.isArray(Et.centerLine)||Et.centerLine.length<2||!isFinite(wt)||wt<=0)return null;const Tt=Math.abs(Et.origEnd-Et.origStart)/3;let Rt=xt/Tt,Pt=vt/Tt;Rt=Math.max(0,Math.min(1,Rt)),Pt=Math.max(0,Math.min(1,Pt));const Lt=this.interpolateOnLine(Et.centerLine,Rt),kt=this.interpolateOnLine(Et.centerLine,Pt),Ot=this.perpVector(Et.centerLine[0],Et.centerLine[1]),Mt=this.normalize(Ot),It=(typeof Et.geneHeight=="number"?Et.geneHeight:Et.config&&Et.config.gene&&Et.config.gene.height?Et.config.gene.height:10)/2,Nt=Et.config&&Et.config.domain&&typeof Et.config.domain.heightFactor=="number"?Et.config.domain.heightFactor:this.config&&this.config.domain&&this.config.domain.heightFactor||.6,Ut=It*Nt,jt=[Lt[0]-Mt[0]*Ut,Lt[1]-Mt[1]*Ut],Vt=[kt[0]-Mt[0]*Ut,kt[1]-Mt[1]*Ut],zt=[kt[0]+Mt[0]*Ut,kt[1]+Mt[1]*Ut],Ht=[Lt[0]+Mt[0]*Ut,Lt[1]+Mt[1]*Ut];return[jt,Vt,zt,Ht]}interpolateOnLine(Et,xt){const[vt,bt]=Et;return[vt[0]+(bt[0]-vt[0])*xt,vt[1]+(bt[1]-vt[1])*xt]}perpVector(Et,xt){const vt=xt[0]-Et[0];return[-(xt[1]-Et[1]),vt]}normalize(Et){const xt=Math.sqrt(Et[0]*Et[0]+Et[1]*Et[1]);return xt===0?[0,1]:[Et[0]/xt,Et[1]/xt]}}class Link{constructor(){}}class ProteinLink extends Link{constructor(Et,xt,vt,bt=[50,100,220]){super(),this.gAId=Et,this.gBId=xt,this.similarity=vt,this.baseColor=Array.isArray(bt)&&bt.length>=3?bt.slice(0,3):[50,100,220];const At=Math.round(255*(vt/100));this.fillColor=[...this.baseColor,At],this.metadata={gAId:Et,gBId:xt,similarity:vt}}updateColor(Et,xt=null,vt=null,bt=null,At=null){if(!Et){const St=Math.round(255*(this.similarity/100));this.fillColor=[...this.baseColor,St];return}let Ft=this.baseColor,Ct=255;const wt=At?At.slice(0,3):this.baseColor;switch(Et.colorBy){case"source_gene":Ft=xt?xt.slice(0,3):wt;break;case"target_gene":Ft=vt?vt.slice(0,3):wt;break;case"identity_solid":Ft=Et.solidColor?Et.solidColor.slice(0,3):this.baseColor;break;case"identity_gradient":bt&&(Ft=bt.slice(0,3));break;default:Ft=this.baseColor}if(Et.useAlpha){const St=this.similarity/100,Tt=Et.maxAlpha-Et.minAlpha,Rt=Et.minAlpha+St*Tt;Ct=Math.round(Rt*255)}else Ct=Et.colorBy==="identity_solid"?255:Math.round(255*(this.similarity/100));this.fillColor=[...Ft,Ct]}bezierCurve(Et,xt,vt,bt,At=120){const Ft=[];for(let Ct=0;Ct<=1;Ct+=1/At){const wt=Math.pow(1-Ct,3)*Et[0]+3*Math.pow(1-Ct,2)*Ct*xt[0]+3*(1-Ct)*Ct*Ct*vt[0]+Ct*Ct*Ct*bt[0],St=Math.pow(1-Ct,3)*Et[1]+3*Math.pow(1-Ct,2)*Ct*xt[1]+3*(1-Ct)*Ct*Ct*vt[1]+Ct*Ct*Ct*bt[1];Ft.push([wt,St])}return Ft}buildPolygon(Et,xt){if(!Et||!xt)return null;const vt=Math.min(Et.start,Et.end),bt=Math.max(Et.start,Et.end),At=Math.min(xt.start,xt.end),Ft=Math.max(xt.start,xt.end),Ct=Et.trackY,wt=xt.trackY;let St,Tt;Ct<=wt?(St={left:[vt,Ct],right:[bt,Ct]},Tt={left:[At,wt],right:[Ft,wt]}):(St={left:[At,wt],right:[Ft,wt]},Tt={left:[vt,Ct],right:[bt,Ct]});const Rt=(St.left[1]+Tt.right[1])/2,Pt=(Ot,Mt)=>this.bezierCurve(Ot,[Ot[0],Rt],[Mt[0],Rt],Mt,20),Lt=Pt(St.right,Tt.right),kt=Pt(Tt.left,St.left);return[St.left,St.right,...Lt,Tt.right,Tt.left,...kt]}}class NucleotideLink extends Link{constructor(Et,xt,vt,bt,At,Ft,Ct,wt=[220,50,50]){super(),this.seqidA=Et,this.seqidB=bt,this.strandA=xt<=vt?"+":"-",this.strandB=At<=Ft?"+":"-",xt>vt&&([xt,vt]=[vt,xt]),At>Ft&&([At,Ft]=[Ft,At]),this.origStartA=xt,this.origEndA=vt,this.origStartB=At,this.origEndB=Ft,this.startA=xt,this.endA=vt,this.startB=At,this.endB=Ft,this.similarity=Ct,this.baseColor=Array.isArray(wt)&&wt.length>=3?wt.slice(0,3):[220,50,50];const St=Math.round(255*(Ct/100));this.fillColor=[...this.baseColor,St]}updateColor(Et,xt=null){if(!Et){const At=Math.round(255*(this.similarity/100));this.fillColor=[...this.baseColor,At];return}let vt=this.baseColor,bt=255;switch(Et.colorBy){case"solid":vt=Et.solidColor?Et.solidColor.slice(0,3):this.baseColor,Et.useAlpha||(bt=Et.solidColor&&Et.solidColor.length>3?Et.solidColor[3]:255);break;case"identity_gradient":xt&&(vt=xt.slice(0,3)),bt=255;break;default:vt=this.baseColor,bt=Math.round(255*(this.similarity/100))}if(Et.useAlpha){const At=this.similarity/100,Ft=Et.maxAlpha-Et.minAlpha,Ct=Et.minAlpha+At*Ft;bt=Math.round(Ct*255)}this.fillColor=[...vt,bt]}buildPolygon(Et,xt){const vt=[this.startA,this.endA,this.startB,this.endB],bt=[Et,Et,xt,xt],At=Math.min(...vt),Ft=Math.max(...vt),Ct=Math.min(...bt),wt=Math.max(...bt);return[[At,wt],[Ft,wt],[Ft,Ct],[At,Ct]]}buildPolygonFromCoords(Et,xt,vt,bt,At,Ft){const Ct=[[Et,At],[xt,At]],wt=[[vt,Ft],[bt,Ft]];return Ct.sort((St,Tt)=>St[0]-Tt[0]),wt.sort((St,Tt)=>St[0]-Tt[0]),[Ct[0],Ct[1],wt[1],wt[0]]}}class Hood{constructor(Et,xt,vt){this.seqid=Et,this.start=xt,this.end=vt,this.origStart=xt,this.origEnd=vt}set(Et,xt){this.start=Et,this.end=xt,this.origStart=Et,this.origEnd=xt}update(Et,xt){this.start=Et,this.end=xt}get(){return{seqid:this.seqid,start:this.start,end:this.end,origStart:this.origStart,origEnd:this.origEnd}}}class Nucleotide{constructor(Et,xt,vt,bt="+"){this.seqid=Et,this.start=xt,this.end=vt,this.strand=bt,this.genes=[],this.metadata={seqid:Et,start:xt,end:vt,strand:bt},this.hood=null}addGene(Et){this.genes.push(Et)}flip(){const Et=this.start,xt=this.end;this.start=-xt,this.end=-Et,this.strand=this.strand==="+"?"-":"+";for(const vt of this.genes)vt.start=-vt.end,vt.end=-vt.start,vt.strand=vt.strand==="+"?"-":"+",typeof vt.updatePolygon=="function"&&vt.updatePolygon()}shift(Et){this.start+=Et,this.end+=Et;for(const xt of this.genes)xt.start+=Et,xt.end+=Et,typeof xt.updatePolygon=="function"&&xt.updatePolygon()}getGenePolygons(){return this.genes.map(Et=>Et.polygon).filter(Boolean)}setHood(Et,xt){this.hood?this.hood.set(Et,xt):this.hood=new Hood(this.seqid,Et,xt)}getHood(){return this.hood?this.hood.get():null}updateHood(Et,xt){this.hood?this.hood.update(Et,xt):this.setHood(Et,xt)}}class NonCodingFeature extends GFFFeature{constructor(Et,xt,vt,bt,At,Ft,Ct){super(Et,xt,vt,bt,At,Ft),this.config=Ct||DEFAULT_CONFIG$1,this.polygon=null,this.trackY=null,this.featureHeight=this.config?.gene?.height||60,this.metadata={seqid:Et,start:xt,end:vt,strand:bt,type:At,attributes:Ft}}setTrackY(Et){this.trackY=Et,this.updatePolygon()}updatePolygon(){this.polygon=this._buildHalfArrowPolygon(this.trackY,this.featureHeight)}_buildHalfArrowPolygon(Et,xt){let vt=this.start,bt=this.end;if(vt>bt){const Rt=vt;vt=bt,bt=Rt}const At=Math.abs(bt-vt),Ft=calculateTipWidth(At,this.config),Ct=xt/4,wt=this.strand==="+",St=this.config?.gene?.arrowheadHeight||0,Tt=Ct+St/2;return Ft<1?wt?[[vt,Et],[vt,Et+Ct],[bt,Et+Ct],[bt,Et]]:[[bt,Et],[bt,Et-Ct],[vt,Et-Ct],[vt,Et]]:wt?[[vt,Et],[vt,Et+Ct],[bt-Ft,Et+Ct],[bt-Ft,Et+Tt],[bt,Et]]:[[bt,Et],[bt,Et-Ct],[vt+Ft,Et-Ct],[vt+Ft,Et-Tt],[vt,Et]]}}class RegionFeature extends GFFFeature{constructor(Et,xt,vt,bt,At,Ft,Ct){super(Et,xt,vt,bt,At,Ft),this.config=Ct,this.polygon=null,this.trackY=null,this.padding=Ct?.region?.padding||10,this.fillColor=[0,0,0,0],this.strokeColor=[100,100,100,255],this.strokeWidth=Ct?.region?.strokeWidth||2,this.metadata={seqid:Et,start:xt,end:vt,type:At,length:Math.abs(vt-xt)},Ft&&(typeof Ft=="string"||Ft instanceof String?this.metadata.attributes=Ft.toString():typeof Ft=="object"&&Object.assign(this.metadata,Ft))}setTrackY(Et){this.trackY=Et}updatePolygon(Et=[],xt=null){xt!==null&&(this.trackY=xt),this.config||(console.warn("RegionFeature: No config provided, using defaults"),this.config={gene:{height:20,arrowheadHeight:30},region:{padding:10,strokeWidth:2}});const vt=Math.min(this.start,this.end),bt=Math.max(this.start,this.end),At=this.config.gene?.height||20,Ft=this.config.gene?.arrowheadHeight||30,Ct=this.config.region?.padding||this.padding,St=Math.max(At,Ft)/2,Tt=this.trackY-St-Ct,Rt=this.trackY+St+Ct;this.polygon=[[vt,Tt],[bt,Tt],[bt,Rt],[vt,Rt],[vt,Tt]]}containsGene(Et){const xt=Math.min(this.start,this.end),vt=Math.max(this.start,this.end),bt=Math.min(Et.start,Et.end);return!(Math.max(Et.start,Et.end)<xt||bt>vt)}getFillColor(){return[0,0,0,0]}getStrokeColor(){if(this.strokeColor&&this.strokeColor[3]!==0)return this.strokeColor;const Et=(this.type||"").toLowerCase(),xt=this.config?.region?.colors||{};return xt[Et]?xt[Et]:xt.default||[128,128,128,255]}getColorKey(){const Et=this.metadata?.region_id||this.metadata?.ID||this.originalId||"";if(Et){const xt=Et.match(/^([a-zA-Z]+)/);if(xt)return xt[1].toLowerCase()}return this.metadata?.region_type?this.metadata.region_type.toLowerCase():(this.type||"region").toLowerCase()}}const _paletteCache=new Map;function memoGetPalette(yt,Et,xt=!1,vt="qualitative"){const bt=`${yt}::${Et}::${xt}::${vt}`;if(_paletteCache.has(bt))return _paletteCache.get(bt);let At=[];try{At=getPaletteColors(yt,Et,xt,vt)}catch{At=[]}return _paletteCache.set(bt,At),At}class GenomeView{constructor(Et,xt,vt=DEFAULT_CONFIG$1){this.leaves=Et,this.tree=xt,this.config=vt||DEFAULT_CONFIG$1,this.featuresBySeqid={},this.genesById={},this.ncRNAsById={},this.regionsById={},this.nucleotidesBySeqid={},this.globalMin=1/0,this.globalMax=-1/0,this.geneHeight=this.config?.gene?.height||DEFAULT_CONFIG$1.gene.height,this.trackFlipped={},this.trackOffset={},this.hoodRanges={},this.hoodToSeqidMap={},this.seqidToHoodsMap={},this.proteinLinks=[],this.nucleotideLinks=[],this.domainsByGene={},this._genesByOriginalId=new Map,this._genesIndexReady=!1,this._leafIndex=null,this._hoodIndex=null,this._regionsByHood=null,this._rightmostByHood=new Map,this._paletteVersion=0}_ensureLeafIndex(){if(!this._leafIndex){if(!this.tree?.leafNodes){this._leafIndex=new Map;return}this._leafIndex=new Map(this.tree.leafNodes.map((Et,xt)=>[Et.name,xt]))}}_buildGeneIndex(){this._genesByOriginalId=new Map;for(const[Et,xt]of Object.entries(this.genesById)){const vt=xt.originalGeneId;vt&&(this._genesByOriginalId.has(vt)||this._genesByOriginalId.set(vt,[]),this._genesByOriginalId.get(vt).push(Et))}this._genesIndexReady=!0}_addOrUpdateGeneIndex(Et,xt){xt?.originalGeneId&&(this._genesByOriginalId.has(xt.originalGeneId)||this._genesByOriginalId.set(xt.originalGeneId,[]),this._genesByOriginalId.get(xt.originalGeneId).push(Et),this._genesIndexReady=!0)}_invalidateGeneIndex(){this._genesIndexReady=!1}_rebuildRegionsByHood(){this._regionsByHood=new Map;for(const Et of Object.values(this.regionsById))this._regionsByHood.has(Et.hood_id)||this._regionsByHood.set(Et.hood_id,[]),this._regionsByHood.get(Et.hood_id).push(Et)}_buildHoodIntervalIndex(){this._hoodIndex=new Map;for(const[Et,xt]of Object.entries(this.hoodRanges||{})){const vt=this._hoodIndex.get(xt.seqid)||[];vt.push({start:xt.origStart,end:xt.origEnd,hood_id:Et}),this._hoodIndex.set(xt.seqid,vt)}for(const Et of this._hoodIndex.values())Et.sort((xt,vt)=>xt.start-vt.start)}_queryHoodsCovering(Et,xt,vt){const bt=this._hoodIndex?.get(Et)||[];let At=0,Ft=bt.length;for(;At<Ft;){const wt=At+Ft>>1;bt[wt].start<=xt?At=wt+1:Ft=wt}const Ct=[];for(let wt=At-1;wt>=0&&bt[wt].start<=xt;--wt)bt[wt].end>=vt&&Ct.push(bt[wt].hood_id);for(let wt=At;wt<bt.length&&bt[wt].start<=xt;++wt)bt[wt].end>=vt&&Ct.push(bt[wt].hood_id);return Ct}static flipCoordinate(Et,xt){return 2*xt-Et}static getTransformedXUnified(Et,xt,vt,bt){let At=Et+(vt||0);return bt?GenomeView.flipCoordinate(At,xt):At}static getGeneVisualX(Et,xt){const vt=Et.hood_id,bt=xt.hoodRanges[vt];if(!bt)return null;const At=xt.trackOffset[vt]||0,Ft=!!xt.trackFlipped[vt],Ct=(bt.length||0)/2,St=(xt.config.genome&&typeof xt.config.genome.xScalePercent=="number"?xt.config.genome.xScalePercent:100)/100,Tt=Et.origStart||0,Rt=Et.origEnd||0,Pt=Et.origStrand==="+"?Math.min(Tt,Rt):Math.max(Tt,Rt),Lt=GenomeView.getTransformedXUnified(Pt,Ct,At,Ft);return Ct+(Lt-Ct)*St}addFeatures(Et){for(let xt of Et)if(!(!xt.seqid||typeof xt.start!="number"||isNaN(xt.start)||typeof xt.end!="number"||isNaN(xt.end))&&(this.featuresBySeqid[xt.seqid]?(xt.start<this.featuresBySeqid[xt.seqid].origMinStart&&(this.featuresBySeqid[xt.seqid].origMinStart=xt.start),xt.end>this.featuresBySeqid[xt.seqid].origMaxEnd&&(this.featuresBySeqid[xt.seqid].origMaxEnd=xt.end)):(this.featuresBySeqid[xt.seqid]=[],this.featuresBySeqid[xt.seqid].origMinStart=xt.start,this.featuresBySeqid[xt.seqid].origMaxEnd=xt.end),this.featuresBySeqid[xt.seqid].push(xt),!this.nucleotidesBySeqid[xt.seqid])){const vt=this.featuresBySeqid[xt.seqid],bt=Math.min(...vt.map(wt=>typeof wt.start=="bigint"?Number(wt.start):wt.start)),At=Math.max(...vt.map(wt=>typeof wt.end=="bigint"?Number(wt.end):wt.end)),Ft=vt.find(wt=>wt.type==="gene"||wt.type==="CDS"),Ct=Ft&&Ft.strand?Ft.strand:"+";this.nucleotidesBySeqid[xt.seqid]=new Nucleotide(xt.seqid,bt,At,Ct)}}initGenes(){this._invalidateGeneIndex();for(let Et of this.leaves){const xt=this.hoodToSeqidMap[Et];if(!xt)continue;const vt=this.hoodRanges[Et];if(!vt)continue;const bt=vt.origStart||0,At=vt.origEnd||0,Ft=this.featuresBySeqid[xt]||[];for(let Ct of Ft)if(Ct.type==="gene"||Ct.type==="CDS"){const wt=Ct.start||0,St=Ct.end||0;if(!(wt>=bt&&St<=At))continue;const Rt=wt-bt,Pt=St-bt;let Lt=Ct.gene_id||Ct.id||Ct.protein_id||Ct.originalGeneId;!Lt&&Ct.attributes&&(Lt=this.getGeneIdFromAttributes(Ct.attributes));const kt=`${Et}_${Lt}`;let Ot=new Gene(Ct.seqid,Rt,Pt,Ct.strand,Ct.attributes,this.config);Ot.hood_id=Et,Ot.originalGeneId=Lt,this.genesById[kt]=Ot,this._addOrUpdateGeneIndex(kt,Ot),this.nucleotidesBySeqid[xt]&&this.nucleotidesBySeqid[xt].addGene(Ot)}else if(typeof Ct.type=="string"&&Ct.type.toLowerCase().includes("ncrna")){const wt=Ct.start||0,St=Ct.end||0;if(!(wt>=bt&&St<=At))continue;const Rt=wt-bt,Pt=St-bt,Lt=this.getGeneIdFromAttributes(Ct.attributes),kt=`${Et}_${Lt}_${wt}_${St}`;let Ot=new NonCodingFeature(Ct.seqid,Rt,Pt,Ct.strand,Ct.type,Ct.attributes,this.config);Ot.hood_id=Et,Ot.id=kt,Ot.originalId=Lt,Ot.origStart=Rt,Ot.origEnd=Pt,Ot.genomicStart=wt,Ot.genomicEnd=St,Ot.origStrand=Ct.strand;let Mt=null;try{const Nt=Ct.attributes||{};Nt&&typeof Nt=="object"&&(Mt=Nt.ncrna_type||Nt.ncrnaType||Nt.ID||Nt.id||Nt.Name||null),typeof Mt=="object"&&(Mt=String(Mt)),Mt&&(Mt=String(Mt).replace(/^ID=/,"").replace(/;$/,"").trim()),Mt&&(Mt.toLowerCase()==="null"||Mt.toLowerCase()==="none"||Mt==="")&&(Mt=null)}catch{Mt=null}const It=Mt||Lt||Ct.type||"ncRNA";Ot.name=It,(!Ot.metadata||typeof Ot.metadata!="object")&&(Ot.metadata={}),Ot.metadata.type=It,Ot.metadata.attributes=Ct.attributes,this.ncRNAsById[kt]=Ot}else if(Ct.type==="region"){const wt=Ct.start||0,St=Ct.end||0;if(!(wt>=bt&&St<=At))continue;const Rt=wt-bt,Pt=St-bt,Lt=this.getGeneIdFromAttributes(Ct.attributes),kt=`${Et}_${Lt}`;let Ot=new RegionFeature(Ct.seqid,Rt,Pt,Ct.strand,Ct.type,Ct.attributes,this.config);Ot.id=kt,Ot.hood_id=Et,Ot.originalId=Lt,Ot.origStart=Rt,Ot.origEnd=Pt,Ot.origStrand=Ct.strand,this.regionsById[kt]=Ot}}}getGeneIdFromAttributes(Et){if(typeof Et=="string"){const xt=Et.match(/ID=([^;]+)/);return xt?xt[1]:null}else if(typeof Et=="object"&&Et!==null)return Et.ID||null;return null}computeTrackPositions(){const Et={},xt={};for(const At of Object.values(this.genesById))(Et[At.hood_id]||=[]).push(At);for(const At of Object.values(this.ncRNAsById))(xt[At.hood_id]||=[]).push(At);this._rebuildRegionsByHood();const bt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100;this._rightmostByHood.clear();for(let At of this.leaves){const Ft=this.tree.leafNodes.find(jt=>jt.name===At);if(!Ft)continue;const wt=(typeof Ft?.x=="number"?Ft.x:Ft?.y||0)+(this.config?.layout?.geneOffset||0),St=this.hoodToSeqidMap[At];if(!St)continue;const Tt=this.nucleotidesBySeqid[St],Rt=this.trackOffset[At]||0,Pt=this.hoodRanges[At],kt=(Pt?.length||0)/2,Ot=!!this.trackFlipped[At];let Mt=-1/0;const It=Et[At]||[];for(const jt of It){jt.trackY=wt,jt.geneHeight=this.geneHeight;const Vt=jt.origStart||0,zt=jt.origEnd||0;let Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot),Wt=GenomeView.getTransformedXUnified(zt,kt,Rt,Ot);Ht=kt+(Ht-kt)*bt,Wt=kt+(Wt-kt)*bt,jt.start=Ht,jt.end=Wt,jt.strand=Ot?jt.origStrand==="+"?"-":"+":jt.origStrand,["gene_1","gene_2"].includes(jt.id)||jt.originalGeneId?.includes("gene_1")||jt.originalGeneId?.includes("gene_2"),Mt=Math.max(Mt,Ht,Wt);for(let Gt of jt.domains)Gt.updatePolygon();jt.updatePolygon()}const Nt=xt[At]||[];for(const jt of Nt){jt.trackY=wt,jt.featureHeight=this.geneHeight;const Vt=jt.origStart||0,zt=jt.origEnd||0;let Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot),Wt=GenomeView.getTransformedXUnified(zt,kt,Rt,Ot);Ht=kt+(Ht-kt)*bt,Wt=kt+(Wt-kt)*bt,jt.start=Ht,jt.end=Wt,jt.strand=Ot?jt.origStrand==="+"?"-":"+":jt.origStrand,jt.updatePolygon(),Mt=Math.max(Mt,Ht,Wt)}const Ut=this._regionsByHood?.get(At)||[];for(const jt of Ut){jt.trackY=wt;const Vt=jt.origStart||0,zt=jt.origEnd||0;let Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot),Wt=GenomeView.getTransformedXUnified(zt,kt,Rt,Ot);Ht=kt+(Ht-kt)*bt,Wt=kt+(Wt-kt)*bt,jt.start=Ht,jt.end=Wt,jt.strand=Ot?jt.origStrand==="+"?"-":"+":jt.origStrand;const Gt=It.filter(qt=>jt.containsGene(qt));jt.updatePolygon(Gt,wt),Mt=Math.max(Mt,Ht,Wt)}if(Tt&&Tt.hood){const Vt=Pt?Pt.length||0:(Tt.hood.origEnd||0)-(Tt.hood.origStart||0);let zt=GenomeView.getTransformedXUnified(0,kt,Rt,Ot),Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot);zt=kt+(zt-kt)*bt,Ht=kt+(Ht-kt)*bt,Tt.hood.start=zt,Tt.hood.end=Ht,Mt=Math.max(Mt,zt,Ht)}if(Tt){let jt=GenomeView.getTransformedXUnified(0,kt,Rt,Ot),Vt=GenomeView.getTransformedXUnified(Pt&&Pt.length||0,kt,Rt,Ot);jt=kt+(jt-kt)*bt,Vt=kt+(Vt-kt)*bt,Tt.start=jt,Tt.end=Vt,Mt=Math.max(Mt,jt,Vt)}isFinite(Mt)&&this._rightmostByHood.set(At,Mt)}this.updateLinkPositions(),this.updateGlobalBounds()}updateGlobalBounds(){let Et=1/0,xt=-1/0;const vt=this.leaves&&this.leaves.length>0,bt=vt?new Set(this.leaves.map(Ft=>String(Ft))):null,At=vt?new Set:null;if(vt)for(const Ft of bt){const Ct=this.hoodToSeqidMap[Ft];Ct&&At.add(Ct)}for(const Ft of Object.values(this.genesById))if(!(bt&&Ft.hood_id&&!bt.has(String(Ft.hood_id))))if(Ft.polygon)for(const[Ct]of Ft.polygon)Ct<Et&&(Et=Ct),Ct>xt&&(xt=Ct);else Ft.start!==void 0&&Ft.end!==void 0&&(Ft.start<Et&&(Et=Ft.start),Ft.end<Et&&(Et=Ft.end),Ft.start>xt&&(xt=Ft.start),Ft.end>xt&&(xt=Ft.end));for(const Ft of Object.values(this.ncRNAsById))if(!(bt&&Ft.hood_id&&!bt.has(String(Ft.hood_id))))if(Ft.polygon)for(const[Ct]of Ft.polygon)Et=Math.min(Et,Ct),xt=Math.max(xt,Ct);else Ft.start!==void 0&&Ft.end!==void 0&&(Et=Math.min(Et,Ft.start,Ft.end),xt=Math.max(xt,Ft.start,Ft.end));for(const Ft of this.getAllDomains()){const Ct=Ft.parentGene;if(bt&&Ct?.hood_id&&!bt.has(String(Ct.hood_id)))continue;const wt=Ft.polygon;if(wt)for(const[St]of wt)Et=Math.min(Et,St),xt=Math.max(xt,St)}isFinite(Et)&&isFinite(xt)&&(this.globalMin=Et,this.globalMax=xt)}updateLinkPositions(){for(let Et of this.nucleotideLinks)Et.startA=Et.origStartA,Et.endA=Et.origEndA,Et.startB=Et.origStartB,Et.endB=Et.origEndB}addDomains(Et){this.domainsByGene=Et,this._cachedAllDomains=void 0,this._genesIndexReady||this._buildGeneIndex();for(const xt in Et){const vt=this._genesByOriginalId.get(xt)||[];for(const bt of vt){const At=this.genesById[bt];if(At){for(let Ft of Et[xt]){this.hoodRanges[At.hood_id];let Ct=new Domain(bt,Ft.domainName,Ft.start,Ft.end,Ft.source,Ft.evalue,Ft.coverage);At.addDomain(Ct)}At.metadata||(At.metadata={}),At.metadata.domainsSummary=At.domains&&At.domains.length>0?At.domains.map(Ft=>`${Ft.domainName}(${Ft.start}-${Ft.end})`).join(";"):""}}}}addDomainMetadata(Et){if(!Et)return;this._cachedAllDomains=void 0;let xt=Et;if(Array.isArray(Et)){xt={};for(const vt of Et){const bt=vt.domain_id||vt.domain||vt.domainName||vt.domain_name||vt.id;bt&&(xt[bt]=vt)}}for(const vt in this.genesById){const bt=this.genesById[vt];if(!(!bt.domains||bt.domains.length===0))for(const At of bt.domains){const Ft=At.domainName,Ct=xt[Ft];Ct&&(At.metadata={...At.metadata,...Ct})}}}addProteinLinks(Et,xt=[50,100,220],vt=1/0){this._genesIndexReady||this._buildGeneIndex(),this._ensureLeafIndex(),this.proteinLinks.length=0;const bt=new Set;for(let At of Et){let Ft,Ct,wt;Array.isArray(At)?(Ft=At[0],Ct=At[1],wt=At[2]):At&&typeof At=="object"&&(Ft=At.geneA??At.gAId,Ct=At.geneB??At.gBId,wt=At.score??At.similarity);const St=this._genesByOriginalId.get(Ft)||[],Tt=this._genesByOriginalId.get(Ct)||[];for(const Rt of St)for(const Pt of Tt){const Lt=this.genesById[Rt],kt=this.genesById[Pt];if(!Lt||!kt)continue;const Ot=this._leafIndex.get(Lt.hood_id),Mt=this._leafIndex.get(kt.hood_id);if(Ot==null||Mt==null||Math.abs(Ot-Mt)<=vt){const It=Rt<Pt?`${Rt}|${Pt}`:`${Pt}|${Rt}`;if(bt.has(It))continue;bt.add(It),this.proteinLinks.push(new ProteinLink(Rt,Pt,wt,xt))}}}}addNucleotideLinks(Et,xt=[220,50,50],vt=1/0){this._hoodIndex||this._buildHoodIntervalIndex(),this._ensureLeafIndex(),this.nucleotideLinks.length=0;for(let bt of Et){const{seqidA:At,seqidB:Ft,startA:Ct,endA:wt,startB:St,endB:Tt,similarity:Rt}=bt,Pt=this._queryHoodsCovering(At,Ct,wt),Lt=this._queryHoodsCovering(Ft,St,Tt);for(const kt of Pt){const Ot=this.hoodRanges[kt];if(Ot)for(const Mt of Lt){const It=this.hoodRanges[Mt];if(!It)continue;const Nt=this._leafIndex.get(kt),Ut=this._leafIndex.get(Mt);if(Nt==null||Ut==null||Math.abs(Nt-Ut)<=vt){const jt=new NucleotideLink(At,Ct,wt,Ft,St,Tt,Rt,xt);jt.hoodA=kt,jt.hoodB=Mt,jt.hoodStartA=Ct-Ot.origStart,jt.hoodEndA=wt-Ot.origStart,jt.hoodStartB=St-It.origStart,jt.hoodEndB=Tt-It.origStart,this.nucleotideLinks.push(jt)}}}}}applyProteinLinkColors(Et,xt=null){if(!this.proteinLinks?.length)return;let vt=null;if(Et?.colorBy==="identity_gradient"&&Et?.palette?.enabled)try{vt=memoGetPalette(Et.palette.name,Et.palette.numColors,Et.palette.reverse)}catch{vt=null}for(const bt of this.proteinLinks){const At=this.genesById[bt.gAId],Ft=this.genesById[bt.gBId],Ct=Et?.colorBy==="source_gene"?At?.fillColor||xt:null,wt=Et?.colorBy==="target_gene"?Ft?.fillColor||xt:null;let St=null;if(Et?.colorBy==="identity_gradient"&&vt){const Tt=Math.max(0,Math.min(1,bt.similarity/100)),Rt=Math.floor(Tt*(vt.length-1));St=vt[Rt]}bt.updateColor(Et,Ct,wt,St,xt)}}applyNucleotideLinkColors(Et){if(!this.nucleotideLinks?.length)return;let xt=null;if(Et?.colorBy==="identity_gradient"&&Et?.palette?.enabled)try{xt=memoGetPalette(Et.palette.name,Et.palette.numColors,Et.palette.reverse)}catch{xt=null}for(const vt of this.nucleotideLinks){let bt=null;if(Et?.colorBy==="identity_gradient"&&xt){const At=Math.max(0,Math.min(1,vt.similarity/100)),Ft=Math.floor(At*(xt.length-1));bt=xt[Ft]}vt.updateColor(Et,bt)}}getTrackY(Et){const xt=this.getHoodIdsFromSeqid(Et);if(xt.length>0){const vt=xt[0],bt=this.tree.leafNodes.find(At=>At.name===vt);return bt?bt.x:null}return null}getTrackYByHoodId(Et){const xt=this.tree.leafNodes.find(vt=>vt.name===Et);return xt?xt.x:null}filterBySelectedNode(Et){if(!Et)return{genes:Object.values(this.genesById),proteinPolygons:this.getProteinPolygons(),nucleotidePolygons:this.getNucleotidePolygons(),domains:this.getAllDomains(),ncRNAs:Object.values(this.ncRNAsById)};const xt=new Set(this.getNodeDescendantLeaves(Et)),vt=Object.values(this.genesById).filter(wt=>xt.has(wt.hood_id||this.getHoodIdFromSeqid(wt.seqid))),bt=this.getProteinPolygons().filter(wt=>wt.seqids?wt.seqids.every(St=>xt.has(this.getHoodIdFromSeqid(St))):!0),At=this.getNucleotidePolygons().filter(wt=>wt.seqids.every(St=>xt.has(this.getHoodIdFromSeqid(St)))),Ft=this.getAllDomains().filter(wt=>{const St=wt.geneId?this.genesById[wt.geneId]:null,Tt=St?.hood_id||this.getHoodIdFromSeqid(St?.seqid);return Tt?xt.has(Tt):!0}),Ct=Object.values(this.ncRNAsById).filter(wt=>xt.has(wt.hood_id||this.getHoodIdFromSeqid(wt.seqid)));return{genes:vt,proteinPolygons:bt,nucleotidePolygons:At,domains:Ft,ncRNAs:Ct}}getProteinPolygons(){const Et=[];for(let xt of this.proteinLinks){const vt=this.genesById[xt.gAId],bt=this.genesById[xt.gBId];if(!vt||!bt)continue;const At=xt.buildPolygon(vt,bt);At&&Et.push({polygon:At,fillColor:xt.fillColor,metadata:xt.metadata})}return Et}getNucleotidePolygons(){const Et=[],vt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100,bt={};for(let At of this.leaves){if(!this.hoodToSeqidMap[At])continue;const Ct=this.hoodRanges[At],wt=this.trackOffset[At]||0,St=!!this.trackFlipped[At],Tt=Ct?(Ct.length||0)/2:0;bt[At]={anchor:Tt,flipped:St,offset:wt,xScale:vt}}for(let At of this.nucleotideLinks){const Ft=At.hoodA,Ct=At.hoodB;if(!Ft||!Ct)continue;const wt=this.getTrackYByHoodId(Ft),St=this.getTrackYByHoodId(Ct);if(wt==null||St==null)continue;const Tt=bt[Ft],Rt=bt[Ct];if(!Tt||!Rt)continue;let Pt=GenomeView.getTransformedXUnified(At.hoodStartA||0,Tt.anchor,Tt.offset,Tt.flipped),Lt=GenomeView.getTransformedXUnified(At.hoodEndA||0,Tt.anchor,Tt.offset,Tt.flipped),kt=GenomeView.getTransformedXUnified(At.hoodStartB||0,Rt.anchor,Rt.offset,Rt.flipped),Ot=GenomeView.getTransformedXUnified(At.hoodEndB||0,Rt.anchor,Rt.offset,Rt.flipped);Pt=Tt.anchor+(Pt-Tt.anchor)*Tt.xScale,Lt=Tt.anchor+(Lt-Tt.anchor)*Tt.xScale,kt=Rt.anchor+(kt-Rt.anchor)*Rt.xScale,Ot=Rt.anchor+(Ot-Rt.anchor)*Rt.xScale;const Mt=At.buildPolygonFromCoords(Pt,Lt,kt,Ot,wt,St);Et.push({polygon:Mt,fillColor:At.fillColor,metadata:At.metadata,seqids:[At.seqidA,At.seqidB]})}return Et}getAllDomains(){if(this._cachedAllDomains!==void 0)return this._cachedAllDomains;const Et=[];let xt=0,vt=0;for(const bt in this.genesById){const At=this.genesById[bt];for(let Ft of At.domains){xt++;let Ct=Ft.polygon;Array.isArray(Ct)&&Ct.length===1&&Array.isArray(Ct[0])&&(Ct=Ct[0]),isValidPolygon(Ct)&&(vt++,Et.push({polygon:Ct,fillColor:Ft.fillColor,domainName:Ft.domainName,metadata:Ft.metadata,geneId:Ft.geneId}))}}try{typeof window<"u"&&window.__hoodini_debug&&console.debug(`GenomeView.getAllDomains: total=${xt}, valid=${vt}`)}catch{}return this._cachedAllDomains=Et,Et}getAllNcRNAs(){return Object.values(this.ncRNAsById)}getAllRegions(){return Object.values(this.regionsById)}getAllNonCodingFeatures(){return this.getAllNcRNAs()}getRegionPolygons(){const Et=[];for(const xt of Object.values(this.regionsById))xt.polygon&&Array.isArray(xt.polygon)&&xt.polygon.length>0&&Et.push({polygon:xt.polygon,fillColor:xt.getFillColor(),strokeColor:xt.getStrokeColor(),strokeWidth:xt.strokeWidth,metadata:xt.metadata});return Et}getNodeDescendantLeaves(Et){if(!Et)return[];function xt(vt){return vt.branchset.length===0&&vt.name?[vt.name]:vt.branchset.flatMap(xt)}return xt(Et)}buildScaleBar(){const Et=this.config?.layout?.scaleBarOffset??this.config?.layout?.padding??150,xt=this.tree.leafNodes[this.tree.leafNodes.length-1].x+Et;return[[{path:[[this.globalMin,xt],[this.globalMax,xt]],color:this.config?.colors?.black||[0,0,0,255]}],xt]}buildPhyloLabels(Et="after-tree"){const xt=this.config?.tree?.labelOffset||10,vt=this.config?.colors?.black||[10,10,10,255],bt=this.config?.text?.phyloLabelSize||14;return this.tree.leafNodes.map(At=>{let Ft;if(Et==="after-tracks"){const Ct=At.name;let wt=this._rightmostByHood.get(Ct);isFinite(wt)?wt+=xt:wt=At.y+xt,Ft=[wt,At.x]}else Ft=[At.y+xt,At.x];return{position:Ft,text:At.name,color:vt,size:bt,textAnchor:"start",leafNode:At}})}buildNodePoints(Et,xt){const vt=Et?new Set(this.getNodeDescendantLeaves(Et)):null,bt=this.config?.tree?.nodeRadius||DEFAULT_CONFIG$1.tree.nodeRadius;return this.tree.allNodes.map(At=>{const Ft=this.getNodeDescendantLeaves(At),Ct=!Et||Ft.some(St=>vt.has(St));let wt;if(At.branchset.length>0)wt=[0,0,0,255];else{const St=At.metadata||{};if(St[xt]){const Tt=String(St[xt]);let Rt=0;for(let Ot=0;Ot<Tt.length;++Ot)Rt=Tt.charCodeAt(Ot)+((Rt<<5)-Rt);const Pt=Rt>>0&255,Lt=Rt>>8&255,kt=Rt>>16&255;wt=[Math.abs(Pt),Math.abs(Lt),Math.abs(kt),255]}else wt=[100,100,100,255]}return Et&&!Ct&&(wt=this.fadeColor(wt,.1)),{id:At.id,node:At,position:[At.y,At.x],color:wt,radius:At.branchset.length>0?bt.internal:bt.leaf,metadata:At.metadata||{name:At.name,id:At.id}}})}buildEdgesWithMetadata(){return this.tree.buildEdges().map(Et=>({...Et,metadata:{source:Et.source?.name,target:Et.target?.name,branchLength:Et.source?.branchLength,id:Et.source?.id}}))}fadeColor(Et,xt){return[Et[0],Et[1],Et[2],Math.floor(Et[3]*xt)]}setProteinClusters(Et){if(!Et||Object.keys(Et).length===0){this.proteinClusters={},this._clusterSummary=null;return}this.proteinClusters={},this._genesIndexReady||this._buildGeneIndex();for(const bt of Object.keys(Et)){const At=Et[bt],Ft=At==null?null:String(At).trim(),Ct=this._genesByOriginalId.get(bt)||[];for(const wt of Ct)this.proteinClusters[wt]=Ft}if(this._clusterSummary=null,!this.clusterColors)return;const xt=this.genesById,vt=this.clusterColors;for(const bt in xt){const At=xt[bt],Ft=this.proteinClusters[bt];At.fillColor=Ft&&vt[Ft]?vt[Ft]:null,At.metadata||(At.metadata={}),At.metadata.clusterId=Ft||null}}setProteinClustersWithPalette(Et,xt=null){this.proteinClusters={},this._genesIndexReady||this._buildGeneIndex();for(const At in Et){const Ft=Et[At],Ct=Ft==null?null:String(Ft).trim(),wt=this._genesByOriginalId.get(At)||[];for(const St of wt)this.proteinClusters[St]=Ct}if(this._clusterSummary=null,!xt||!xt.enabled){for(const At in this.genesById){const Ft=this.genesById[At];Ft&&Ft.fillColor&&(Ft.fillColor=null)}this._paletteVersion++;return}this.clusterColors={};const vt=Array.from(new Set(Object.values(this.proteinClusters))).filter(At=>At!=null).sort((At,Ft)=>{const Ct=Number(At),wt=Number(Ft);return!isNaN(Ct)&&!isNaN(wt)?Ct-wt:String(At).localeCompare(String(Ft))});let bt=[];if(xt.name)try{bt=memoGetPalette(xt.name,Math.max(vt.length,xt.numColors||vt.length),xt.reverse||!1)}catch{bt=[]}if(bt.length===0&&(bt=vt.map((At,Ft)=>hslToRgb(Ft/vt.length,.6,.5).concat(255))),vt.forEach((At,Ft)=>{this.clusterColors[At]=bt[Ft%bt.length]}),xt.desaturateByPrevalence){const At=this.computeGenePrevalence("cluster");for(const Ft in this.clusterColors){const Ct=At.get(Ft)||0;this.clusterColors[Ft]=this._desaturateColorByPrevalence(this.clusterColors[Ft],Ct)}}this._clusterSummary=null;for(const At in this.genesById){const Ft=this.genesById[At],Ct=this.proteinClusters[At];Ft.fillColor=Ct&&this.clusterColors[Ct]?this.clusterColors[Ct]:null,Ft.metadata||(Ft.metadata={}),Ft.metadata.clusterId=Ct||null}this._paletteVersion++}computeGenePrevalence(Et="cluster"){const xt=Object.keys(this.hoodRanges).length;if(xt===0)return new Map;const vt=new Map;for(const At of Object.values(this.genesById)){if(!At.hood_id)continue;let Ft=null;if(Et==="cluster"?Ft=At.metadata?.cluster??At.metadata?.clusterId??At.cluster:Ft=At.metadata?.[Et],Ft==null||Ft==="")continue;const Ct=String(Ft);vt.has(Ct)||vt.set(Ct,new Set),vt.get(Ct).add(At.hood_id)}const bt=new Map;for(const[At,Ft]of vt){const Ct=Ft.size/xt;bt.set(At,Ct)}return bt}_desaturateColorByPrevalence(Et,xt){if(!Et||!Array.isArray(Et)||xt>=1)return Et;const[vt,bt,At,Ft=255]=Et,Ct=vt/255,wt=bt/255,St=At/255,Tt=Math.max(Ct,wt,St),Rt=Math.min(Ct,wt,St),Pt=Tt-Rt,Lt=(Tt+Rt)/2;let kt=0;Pt!==0&&(kt=Lt>.5?Pt/(2-Tt-Rt):Pt/(Tt+Rt));let Ot=0;Pt!==0&&(Tt===Ct?Ot=((wt-St)/Pt+(wt<St?6:0))/6:Tt===wt?Ot=((St-Ct)/Pt+2)/6:Ot=((Ct-wt)/Pt+4)/6);const Mt=1-xt,It=kt*(1-Mt*.8),Nt=(1-Math.abs(2*Lt-1))*It,Ut=Nt*(1-Math.abs(Ot*6%2-1)),jt=Lt-Nt/2;let Vt=0,zt=0,Ht=0;const Wt=Math.floor(Ot*6);return Wt===0?(Vt=Nt,zt=Ut,Ht=0):Wt===1?(Vt=Ut,zt=Nt,Ht=0):Wt===2?(Vt=0,zt=Nt,Ht=Ut):Wt===3?(Vt=0,zt=Ut,Ht=Nt):Wt===4?(Vt=Ut,zt=0,Ht=Nt):(Vt=Nt,zt=0,Ht=Ut),[Math.round((Vt+jt)*255),Math.round((zt+jt)*255),Math.round((Ht+jt)*255),Ft]}_transparentByPrevalence(Et,xt,vt=.1){if(!Et||!Array.isArray(Et))return Et;const[bt,At,Ft]=Et,Ct=Math.round(vt*255+xt*(255-vt*255));return[bt,At,Ft,Ct]}_computeClusterSummary(){const Et=this.proteinClusters||{},xt=Object.values(Et).reduce((bt,At)=>{const Ft=String(At);return bt[Ft]=(bt[Ft]||0)+1,bt},{}),vt=Object.entries(xt).map(([bt,At])=>({id:bt,size:Number(At),label:`Cluster ${bt} (${At} genes)`})).sort((bt,At)=>At.size-bt.size);return{items:vt,ids:vt.map(bt=>bt.id)}}getClusterSummary(){return this._clusterSummary?this._clusterSummary:(this._clusterSummary=this._computeClusterSummary(),this._clusterSummary)}setNcRNAColorsWithPalette(Et=null){const xt=Object.values(this.ncRNAsById);if(!Et||!Et.enabled){for(const Ct of xt)Ct.fillColor=this.config?.gene?.fillColor||[200,200,200,255];return}const vt=xt.filter(Ct=>{const wt=Ct.metadata&&Ct.metadata.type;return!isEmptyValue(wt)});if(vt.length===0)return;const bt=Array.from(new Set(vt.map(Ct=>normalizeKey(Ct.metadata.type))));let At=[];if(Et.name)try{At=memoGetPalette(Et.name,Math.max(bt.length,Et.numColors||bt.length),Et.reverse||!1)}catch{At=[]}At.length===0&&(At=bt.map((Ct,wt)=>{const St=wt/bt.length;return hslToRgb(St,.6,.5).concat(255)}));const Ft={};bt.forEach((Ct,wt)=>{Ft[Ct]=At[wt%At.length]});for(const Ct in this.ncRNAsById){const wt=this.ncRNAsById[Ct],St=wt.metadata&&wt.metadata.type;isEmptyValue(St)||(wt.fillColor=Ft[normalizeKey(St)])}}setRegionColorsWithPalette(Et=null){const xt=Object.values(this.regionsById);if(xt.length===0)return;if(!Et||!Et.enabled){for(const Ct of xt)Ct.fillColor=[0,0,0,0],Ct.strokeColor=[100,100,100,255];return}const vt=xt.map(Ct=>Ct.getColorKey()).map(Ct=>normalizeKey(Ct)).filter(Ct=>!isEmptyValue(Ct)),bt=[...new Set(vt)];if(bt.length===0)return;let At=[];if(Et.name)try{At=memoGetPalette(Et.name,Math.max(bt.length,Et.numColors||bt.length),Et.reverse||!1)}catch{At=[]}At.length===0&&(At=bt.map((Ct,wt)=>{const St=wt/bt.length;return hslToRgb(St,.6,.5).concat(255)}));const Ft={};bt.forEach((Ct,wt)=>{Ft[Ct]=At[wt%At.length]});for(const Ct in this.regionsById){const wt=this.regionsById[Ct],St=wt.getColorKey();isEmptyValue(St)||(wt.fillColor=Ft[normalizeKey(St)])}}toggleTrackFlip(Et){this.trackFlipped[Et]=!this.trackFlipped[Et]}flipTrack(Et){const xt=this.trackOffset[Et]||0,vt=this.getTrackAnchor(Et),At=!!this.trackFlipped[Et]?GenomeView.flipCoordinate(vt+xt,vt):vt+xt;this.trackFlipped[Et]=!this.trackFlipped[Et];const Ft=!!this.trackFlipped[Et];let Ct;Ft?Ct=vt-At:Ct=At-vt,this.trackOffset[Et]=Ct,this.computeTrackPositions()}flipTrackState(Et){this.trackFlipped[Et]=!this.trackFlipped[Et]}flipTrackStateWithCentering(Et){const xt=this.trackOffset[Et]||0,vt=this.getTrackAnchor(Et),At=!!this.trackFlipped[Et]?GenomeView.flipCoordinate(vt+xt,vt):vt+xt;this.trackFlipped[Et]=!this.trackFlipped[Et];const Ft=!!this.trackFlipped[Et];let Ct;Ft?Ct=vt-At:Ct=At-vt,this.trackOffset[Et]=Ct}shiftTrack(Et,xt){this.trackOffset[Et]||(this.trackOffset[Et]=0),this.trackFlipped[Et]&&(xt=-xt),this.trackOffset[Et]+=xt,this.computeTrackPositions()}shiftTrackPlus1kb(Et){this.shiftTrack(Et,1e3)}shiftTrackMinus1kb(Et){this.shiftTrack(Et,-1e3)}flipTrackToggle(Et){this.flipTrack(Et)}getTrackAnchor(Et){const xt=this.hoodToSeqidMap[Et];if(!xt)return 0;const vt=this.nucleotidesBySeqid[xt],bt=this.hoodRanges[Et];return bt?bt.length/2:vt&&vt.hood?(vt.hood.origEnd-vt.hood.origStart)/2:this.featuresBySeqid[xt]?(this.featuresBySeqid[xt].origMaxEnd-this.featuresBySeqid[xt].origMinStart)/2:0}alignCluster(Et){const xt=Et==null?null:String(Et).trim(),bt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100,At=Object.entries(this.genesById).filter(([Tt,Rt])=>this.proteinClusters&&this.proteinClusters[Tt]===xt).map(([Tt,Rt])=>Rt);if(At.length===0)return;const Ft={};for(const Tt of At)(Ft[Tt.hood_id]||=[]).push(Tt);const Ct=[];for(const Tt in Ft){const Rt=Ft[Tt];Rt.sort((Pt,Lt)=>Pt.originalGeneId.localeCompare(Lt.originalGeneId)),Ct.push(Rt[0])}if(!Ct.length)return;Ct.sort((Tt,Rt)=>Tt.hood_id.localeCompare(Rt.hood_id)),Ct[0];for(const Tt of Ct){const Rt=Tt.hood_id;(!!this.trackFlipped[Rt]?Tt.origStrand==="+"?"-":"+":Tt.origStrand)==="-"&&this.flipTrackStateWithCentering(Rt)}this.computeTrackPositions();const wt=0;for(const Tt of Ct){const Rt=Tt.hood_id,Pt=GenomeView.getGeneVisualX(Tt,this);if(Pt===null)continue;let Lt=(wt-Pt)/bt;this.trackFlipped[Rt]&&(Lt=-Lt);const Ot=this.trackOffset[Rt]||0;this.trackOffset[Rt]=Ot+Lt}const St=new Set(Ct.map(Tt=>Tt.hood_id));for(const Tt of this.leaves){if(St.has(Tt))continue;const Rt=this.hoodRanges[Tt],Pt=this.hoodToSeqidMap[Tt],Lt=this.nucleotidesBySeqid[Pt];if(!Rt&&!Lt?.hood)continue;const kt=Rt?Rt.length/2:(Lt.hood.origEnd-Lt.hood.origStart)/2,Mt=!!this.trackFlipped[Tt]?-1:1,It=(wt-kt)/(Mt*bt);this.trackOffset[Tt]=It}this.computeTrackPositions()}alignAllToStart(){const Et=this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100,xt=Et/100;for(const vt of this.leaves){this.trackFlipped[vt]=!1;const bt=this.hoodToSeqidMap[vt];if(!bt)continue;const At=this.nucleotidesBySeqid[bt];if(At?.hood){const wt=(this.hoodRanges[vt]?.length||At.hood.origEnd-At.hood.origStart||0)/2;this.trackOffset[vt]=wt*(1-1/xt)}}this.computeTrackPositions();try{if(this.config?.debug?.alignment){const bt=[],At=[];console.debug(`[GenomeView] alignAllToStart xScale=${Et}`);for(const Tt of this.leaves){const Rt=this.hoodToSeqidMap[Tt],Pt=Rt?this.nucleotidesBySeqid[Rt]:null,Lt=!!this.trackFlipped[Tt],kt=this.trackOffset[Tt]||0,Mt=this.hoodRanges[Tt]?.length||(Pt?.hood?Pt.hood.origEnd-Pt.hood.origStart:0)||0,It=Pt?.hood?.start,Nt=Pt?.hood?.end;typeof It=="number"&&isFinite(It)&&bt.push([Tt,It]),typeof Nt=="number"&&isFinite(Nt)&&At.push([Tt,Nt]),console.debug(`[start] hood=${Tt} flipped=${Lt} len=${Mt} offset=${kt} baseline=(${It??"n/a"}, ${Nt??"n/a"})`)}bt.sort((Tt,Rt)=>Tt[1]-Rt[1]),At.sort((Tt,Rt)=>Tt[1]-Rt[1]);const Ft=bt[0]?.[1],Ct=bt[0]?.[0],wt=At[At.length-1]?.[1],St=At[At.length-1]?.[0];console.debug(`[start] baselineMinStart=${Ft} (hood=${Ct}) baselineMaxEnd=${wt} (hood=${St})`),console.debug(`[start] global bounds: minX=${this.globalMin} maxX=${this.globalMax}`)}}catch{}}alignAllToEnd(){const xt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100;for(const vt of this.leaves){this.trackFlipped[vt]=!1;const bt=this.hoodToSeqidMap[vt];if(!bt)continue;const At=this.nucleotidesBySeqid[bt];if(At?.hood){const wt=(this.hoodRanges[vt]?.length||At.hood.origEnd-At.hood.origStart||0)/2;this.trackOffset[vt]=-wt*(1+1/xt)}}this.computeTrackPositions()}alignAllToCenter(){const Et=this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100,xt=Et/100;for(const vt of this.leaves){this.trackFlipped[vt]=!1;const bt=this.hoodToSeqidMap[vt];if(!bt)continue;const At=this.nucleotidesBySeqid[bt];if(At?.hood){const wt=(this.hoodRanges[vt]?.length||At.hood.origEnd-At.hood.origStart||0)/2;this.trackOffset[vt]=-wt/xt}}this.computeTrackPositions();try{if(this.config?.debug?.alignment){const bt=[],At=[];console.debug(`[GenomeView] alignAllToCenter xScale=${Et}`);for(const Tt of this.leaves){const Rt=this.hoodToSeqidMap[Tt],Pt=Rt?this.nucleotidesBySeqid[Rt]:null,Lt=!!this.trackFlipped[Tt],kt=this.trackOffset[Tt]||0,Mt=this.hoodRanges[Tt]?.length||(Pt?.hood?Pt.hood.origEnd-Pt.hood.origStart:0)||0,It=Pt?.hood?.start,Nt=Pt?.hood?.end;typeof It=="number"&&isFinite(It)&&bt.push([Tt,It]),typeof Nt=="number"&&isFinite(Nt)&&At.push([Tt,Nt]),console.debug(`[center] hood=${Tt} flipped=${Lt} len=${Mt} offset=${kt} baseline=(${It??"n/a"}, ${Nt??"n/a"})`)}bt.sort((Tt,Rt)=>Tt[1]-Rt[1]),At.sort((Tt,Rt)=>Tt[1]-Rt[1]);const Ft=bt[0]?.[1],Ct=bt[0]?.[0],wt=At[At.length-1]?.[1],St=At[At.length-1]?.[0];console.debug(`[center] baselineMinStart=${Ft} (hood=${Ct}) baselineMaxEnd=${wt} (hood=${St})`),console.debug(`[center] global bounds: minX=${this.globalMin} maxX=${this.globalMax}`)}}catch{}}applyHoods(Et){const xt=new Set(this.leaves.map(bt=>String(bt))),vt=[];for(const bt of Et){const At=bt.hood_id!=null?String(bt.hood_id).trim():null,Ft=bt.seqid!=null?String(bt.seqid).trim():null;let Ct=null;At&&xt.has(At)?Ct=At:Ft&&xt.has(Ft)&&(Ct=Ft),Ct&&(bt.hood_id=Ct,vt.push(bt))}for(const bt of vt)bt.hood_id&&bt.seqid&&(this.hoodToSeqidMap[bt.hood_id]=bt.seqid,(this.seqidToHoodsMap[bt.seqid]||=[]).push(bt.hood_id),this.hoodRanges[bt.hood_id]={seqid:bt.seqid,origStart:bt.start,origEnd:bt.end,start:bt.start,end:bt.end,length:bt.end-bt.start,align_gene:bt.align_gene}),this.nucleotidesBySeqid[bt.seqid]&&this.nucleotidesBySeqid[bt.seqid].setHood(bt.start,bt.end);this._buildHoodIntervalIndex()}getHoodIdsFromSeqid(Et){return this.seqidToHoodsMap[Et]||[Et]}getHoodIdFromSeqid(Et){return this.getHoodIdsFromSeqid(Et)[0]}getSeqidFromHoodId(Et){return this.hoodToSeqidMap[Et]||Et}alignByDefaultGenes(){const xt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100,vt=[];for(const Ft of this.leaves){const Ct=this.hoodRanges[Ft];if(!Ct?.align_gene)continue;const wt=`${Ft}_${Ct.align_gene}`,St=this.genesById[wt];St&&vt.push(St)}if(!vt.length)return;vt.sort((Ft,Ct)=>Ft.hood_id.localeCompare(Ct.hood_id));const bt=0;for(const Ft of vt){const Ct=Ft.hood_id;(!!this.trackFlipped[Ct]?Ft.origStrand==="+"?"-":"+":Ft.origStrand)==="-"&&this.flipTrackStateWithCentering(Ct)}this.computeTrackPositions();for(const Ft of vt){const Ct=Ft.hood_id,wt=GenomeView.getGeneVisualX(Ft,this);if(wt===null)continue;const St=bt-wt,Rt=(!!this.trackFlipped[Ct]?-1:1)*(St/xt),Pt=this.trackOffset[Ct]||0;this.trackOffset[Ct]=Pt+Rt}const At=new Set(vt.map(Ft=>Ft.hood_id));for(const Ft of this.leaves){if(At.has(Ft))continue;const Ct=this.hoodToSeqidMap[Ft];if(!Ct)continue;const wt=this.nucleotidesBySeqid[Ct];if(wt?.hood){const St=this.hoodRanges[Ft],Tt=St?St.length/2:(wt.hood.origEnd-wt.hood.origStart)/2,Pt=!!this.trackFlipped[Ft]?-1:1,Lt=(bt-Tt)/(Pt*xt);this.trackOffset[Ft]=Lt}}this.computeTrackPositions()}applyDomainPalette(Et=null){if(this._cachedAllDomains=void 0,!Et||!Et.enabled){for(const Ft of Object.values(this.genesById))for(const Ct of Ft.domains)Ct&&Ct.fillColor&&(Ct.fillColor=null);this._paletteVersion++;return}const xt=new Set;for(const Ft of Object.values(this.genesById))for(const Ct of Ft.domains)xt.add(Ct.domainName);const vt=Array.from(xt).sort();let bt=[];if(Et.name)try{bt=memoGetPalette(Et.name,Math.max(vt.length,Et.numColors||vt.length),Et.reverse||!1)}catch{bt=[]}const At={};vt.forEach((Ft,Ct)=>{At[Ft]=bt[Ct%bt.length]});for(const Ft of Object.values(this.genesById))for(const Ct of Ft.domains)Ct.fillColor=At[Ct.domainName]||[128,128,128,255]}}function hslToRgb(yt,Et,xt){let vt,bt,At;{const Ft=(St,Tt,Rt)=>(Rt<0&&(Rt+=1),Rt>1&&(Rt-=1),Rt<.16666666666666666?St+(Tt-St)*6*Rt:Rt<.5?Tt:Rt<.6666666666666666?St+(Tt-St)*(.6666666666666666-Rt)*6:St),Ct=xt+Et-xt*Et,wt=2*xt-Ct;vt=Ft(wt,Ct,yt+1/3),bt=Ft(wt,Ct,yt),At=Ft(wt,Ct,yt-1/3)}return[Math.round(vt*255),Math.round(bt*255),Math.round(At*255)]}function isValidPolygon(yt){if(!Array.isArray(yt)||yt.length<3)return!1;const[Et,xt]=yt[0];return!yt.every(([vt,bt])=>vt===Et&&bt===xt)}function assert$7(yt,Et){if(!yt)throw new Error(Et||"loader assertion failed.")}const isBrowser$2=!!(typeof process!="object"||String(process)!=="[object process]"||process.browser),matches$1=typeof process<"u"&&process.version&&/v([0-9]*)/.exec(process.version);matches$1&&parseFloat(matches$1[1]);const window_=globalThis,process_=globalThis.process||{},navigator_=globalThis.navigator||{};function isElectron(yt){if(typeof window<"u"&&window.process?.type==="renderer"||typeof process<"u"&&process.versions?.electron)return!0;const xt=typeof navigator<"u"&&navigator.userAgent;return!!(xt&&xt.indexOf("Electron")>=0)}function isBrowser$1(){return!(typeof process=="object"&&String(process)==="[object process]"&&!process?.browser)||isElectron()}function getBrowser(yt){return isBrowser$1()?isElectron()?"Electron":(navigator_.userAgent||"").indexOf("Edge")>-1?"Edge":globalThis.chrome?"Chrome":globalThis.safari?"Safari":globalThis.mozInnerScreenX?"Firefox":"Unknown":"Node"}const VERSION$4="4.1.0";function getStorage(yt){try{const Et=window[yt],xt="__storage_test__";return Et.setItem(xt,xt),Et.removeItem(xt),Et}catch{return null}}class LocalStorage{constructor(Et,xt,vt="sessionStorage"){this.storage=getStorage(vt),this.id=Et,this.config=xt,this._loadConfiguration()}getConfiguration(){return this.config}setConfiguration(Et){if(Object.assign(this.config,Et),this.storage){const xt=JSON.stringify(this.config);this.storage.setItem(this.id,xt)}}_loadConfiguration(){let Et={};if(this.storage){const xt=this.storage.getItem(this.id);Et=xt?JSON.parse(xt):{}}return Object.assign(this.config,Et),this}}function formatTime(yt){let Et;return yt<10?Et=`${yt.toFixed(2)}ms`:yt<100?Et=`${yt.toFixed(1)}ms`:yt<1e3?Et=`${yt.toFixed(0)}ms`:Et=`${(yt/1e3).toFixed(2)}s`,Et}function leftPad(yt,Et=8){const xt=Math.max(Et-yt.length,0);return`${" ".repeat(xt)}${yt}`}var COLOR;(function(yt){yt[yt.BLACK=30]="BLACK",yt[yt.RED=31]="RED",yt[yt.GREEN=32]="GREEN",yt[yt.YELLOW=33]="YELLOW",yt[yt.BLUE=34]="BLUE",yt[yt.MAGENTA=35]="MAGENTA",yt[yt.CYAN=36]="CYAN",yt[yt.WHITE=37]="WHITE",yt[yt.BRIGHT_BLACK=90]="BRIGHT_BLACK",yt[yt.BRIGHT_RED=91]="BRIGHT_RED",yt[yt.BRIGHT_GREEN=92]="BRIGHT_GREEN",yt[yt.BRIGHT_YELLOW=93]="BRIGHT_YELLOW",yt[yt.BRIGHT_BLUE=94]="BRIGHT_BLUE",yt[yt.BRIGHT_MAGENTA=95]="BRIGHT_MAGENTA",yt[yt.BRIGHT_CYAN=96]="BRIGHT_CYAN",yt[yt.BRIGHT_WHITE=97]="BRIGHT_WHITE"})(COLOR||(COLOR={}));const BACKGROUND_INCREMENT=10;function getColor(yt){return typeof yt!="string"?yt:(yt=yt.toUpperCase(),COLOR[yt]||COLOR.WHITE)}function addColor(yt,Et,xt){return!isBrowser$1&&typeof yt=="string"&&(Et&&(yt=`\x1B[${getColor(Et)}m${yt}\x1B[39m`),xt&&(yt=`\x1B[${getColor(xt)+BACKGROUND_INCREMENT}m${yt}\x1B[49m`)),yt}function autobind(yt,Et=["constructor"]){const xt=Object.getPrototypeOf(yt),vt=Object.getOwnPropertyNames(xt),bt=yt;for(const At of vt){const Ft=bt[At];typeof Ft=="function"&&(Et.find(Ct=>At===Ct)||(bt[At]=Ft.bind(yt)))}}function assert$6(yt,Et){if(!yt)throw new Error("Assertion failed")}function getHiResTimestamp$1(){let yt;if(isBrowser$1()&&window_.performance)yt=window_?.performance?.now?.();else if("hrtime"in process_){const Et=process_?.hrtime?.();yt=Et[0]*1e3+Et[1]/1e6}else yt=Date.now();return yt}const originalConsole={debug:isBrowser$1()&&console.debug||console.log,log:console.log,info:console.info,warn:console.warn,error:console.error},DEFAULT_LOG_CONFIGURATION={enabled:!0,level:0};function noop$4(){}const cache$2={},ONCE={once:!0};class Log{constructor({id:Et}={id:""}){this.VERSION=VERSION$4,this._startTs=getHiResTimestamp$1(),this._deltaTs=getHiResTimestamp$1(),this.userData={},this.LOG_THROTTLE_TIMEOUT=0,this.id=Et,this.userData={},this._storage=new LocalStorage(`__probe-${this.id}__`,DEFAULT_LOG_CONFIGURATION),this.timeStamp(`${this.id} started`),autobind(this),Object.seal(this)}set level(Et){this.setLevel(Et)}get level(){return this.getLevel()}isEnabled(){return this._storage.config.enabled}getLevel(){return this._storage.config.level}getTotal(){return Number((getHiResTimestamp$1()-this._startTs).toPrecision(10))}getDelta(){return Number((getHiResTimestamp$1()-this._deltaTs).toPrecision(10))}set priority(Et){this.level=Et}get priority(){return this.level}getPriority(){return this.level}enable(Et=!0){return this._storage.setConfiguration({enabled:Et}),this}setLevel(Et){return this._storage.setConfiguration({level:Et}),this}get(Et){return this._storage.config[Et]}set(Et,xt){this._storage.setConfiguration({[Et]:xt})}settings(){console.table?console.table(this._storage.config):console.log(this._storage.config)}assert(Et,xt){if(!Et)throw new Error(xt||"Assertion failed")}warn(Et){return this._getLogFunction(0,Et,originalConsole.warn,arguments,ONCE)}error(Et){return this._getLogFunction(0,Et,originalConsole.error,arguments)}deprecated(Et,xt){return this.warn(`\`${Et}\` is deprecated and will be removed in a later version. Use \`${xt}\` instead`)}removed(Et,xt){return this.error(`\`${Et}\` has been removed. Use \`${xt}\` instead`)}probe(Et,xt){return this._getLogFunction(Et,xt,originalConsole.log,arguments,{time:!0,once:!0})}log(Et,xt){return this._getLogFunction(Et,xt,originalConsole.debug,arguments)}info(Et,xt){return this._getLogFunction(Et,xt,console.info,arguments)}once(Et,xt){return this._getLogFunction(Et,xt,originalConsole.debug||originalConsole.info,arguments,ONCE)}table(Et,xt,vt){return xt?this._getLogFunction(Et,xt,console.table||noop$4,vt&&[vt],{tag:getTableHeader(xt)}):noop$4}time(Et,xt){return this._getLogFunction(Et,xt,console.time?console.time:console.info)}timeEnd(Et,xt){return this._getLogFunction(Et,xt,console.timeEnd?console.timeEnd:console.info)}timeStamp(Et,xt){return this._getLogFunction(Et,xt,console.timeStamp||noop$4)}group(Et,xt,vt={collapsed:!1}){const bt=normalizeArguments({logLevel:Et,message:xt,opts:vt}),{collapsed:At}=vt;return bt.method=(At?console.groupCollapsed:console.group)||console.info,this._getLogFunction(bt)}groupCollapsed(Et,xt,vt={}){return this.group(Et,xt,Object.assign({},vt,{collapsed:!0}))}groupEnd(Et){return this._getLogFunction(Et,"",console.groupEnd||noop$4)}withGroup(Et,xt,vt){this.group(Et,xt)();try{vt()}finally{this.groupEnd(Et)()}}trace(){console.trace&&console.trace()}_shouldLog(Et){return this.isEnabled()&&this.getLevel()>=normalizeLogLevel(Et)}_getLogFunction(Et,xt,vt,bt,At){if(this._shouldLog(Et)){At=normalizeArguments({logLevel:Et,message:xt,args:bt,opts:At}),vt=vt||At.method,assert$6(vt),At.total=this.getTotal(),At.delta=this.getDelta(),this._deltaTs=getHiResTimestamp$1();const Ft=At.tag||At.message;if(At.once&&Ft)if(!cache$2[Ft])cache$2[Ft]=getHiResTimestamp$1();else return noop$4;return xt=decorateMessage(this.id,At.message,At),vt.bind(console,xt,...At.args)}return noop$4}}Log.VERSION=VERSION$4;function normalizeLogLevel(yt){if(!yt)return 0;let Et;switch(typeof yt){case"number":Et=yt;break;case"object":Et=yt.logLevel||yt.priority||0;break;default:return 0}return assert$6(Number.isFinite(Et)&&Et>=0),Et}function normalizeArguments(yt){const{logLevel:Et,message:xt}=yt;yt.logLevel=normalizeLogLevel(Et);const vt=yt.args?Array.from(yt.args):[];for(;vt.length&&vt.shift()!==xt;);switch(typeof Et){case"string":case"function":xt!==void 0&&vt.unshift(xt),yt.message=Et;break;case"object":Object.assign(yt,Et);break}typeof yt.message=="function"&&(yt.message=yt.message());const bt=typeof yt.message;return assert$6(bt==="string"||bt==="object"),Object.assign(yt,{args:vt},yt.opts)}function decorateMessage(yt,Et,xt){if(typeof Et=="string"){const vt=xt.time?leftPad(formatTime(xt.total)):"";Et=xt.time?`${yt}: ${vt} ${Et}`:`${yt}: ${Et}`,Et=addColor(Et,xt.color,xt.background)}return Et}function getTableHeader(yt){for(const Et in yt)for(const xt in yt[Et])return xt||"untitled";return"empty"}const VERSION$3="4.3.3",version=VERSION$3[0]>="0"&&VERSION$3[0]<="9"?`v${VERSION$3}`:"";function createLog(){const yt=new Log({id:"loaders.gl"});return globalThis.loaders=globalThis.loaders||{},globalThis.loaders.log=yt,globalThis.loaders.version=version,globalThis.probe=globalThis.probe||{},globalThis.probe.loaders=yt,yt}const log$1=createLog();function mergeLoaderOptions(yt,Et){return mergeOptionsRecursively(yt||{},Et)}function mergeOptionsRecursively(yt,Et,xt=0){if(xt>3)return Et;const vt={...yt};for(const[bt,At]of Object.entries(Et))At&&typeof At=="object"&&!Array.isArray(At)?vt[bt]=mergeOptionsRecursively(vt[bt]||{},Et[bt],xt+1):vt[bt]=Et[bt];return vt}const NPM_TAG="latest";function getVersion(){return globalThis._loadersgl_?.version||(globalThis._loadersgl_=globalThis._loadersgl_||{},globalThis._loadersgl_.version="4.3.3"),globalThis._loadersgl_.version}const VERSION$2=getVersion();function assert$5(yt,Et){if(!yt)throw new Error(Et||"loaders.gl assertion failed.")}const isBrowser=typeof process!="object"||String(process)!=="[object process]"||process.browser,isMobile=typeof window<"u"&&typeof window.orientation<"u",matches=typeof process<"u"&&process.version&&/v([0-9]*)/.exec(process.version);matches&&parseFloat(matches[1]);class WorkerJob{name;workerThread;isRunning=!0;result;_resolve=()=>{};_reject=()=>{};constructor(Et,xt){this.name=Et,this.workerThread=xt,this.result=new Promise((vt,bt)=>{this._resolve=vt,this._reject=bt})}postMessage(Et,xt){this.workerThread.postMessage({source:"loaders.gl",type:Et,payload:xt})}done(Et){assert$5(this.isRunning),this.isRunning=!1,this._resolve(Et)}error(Et){assert$5(this.isRunning),this.isRunning=!1,this._reject(Et)}}class NodeWorker{terminate(){}}const workerURLCache=new Map;function getLoadableWorkerURL(yt){assert$5(yt.source&&!yt.url||!yt.source&&yt.url);let Et=workerURLCache.get(yt.source||yt.url);return Et||(yt.url&&(Et=getLoadableWorkerURLFromURL(yt.url),workerURLCache.set(yt.url,Et)),yt.source&&(Et=getLoadableWorkerURLFromSource(yt.source),workerURLCache.set(yt.source,Et))),assert$5(Et),Et}function getLoadableWorkerURLFromURL(yt){if(!yt.startsWith("http"))return yt;const Et=buildScriptSource(yt);return getLoadableWorkerURLFromSource(Et)}function getLoadableWorkerURLFromSource(yt){const Et=new Blob([yt],{type:"application/javascript"});return URL.createObjectURL(Et)}function buildScriptSource(yt){return`try {
|
|
79
|
+
`,hoodiniLogoUrl=(()=>{try{return typeof btoa=="function"?`data:image/svg+xml;base64,${btoa(hoodiniLogoRaw)}`:`data:image/svg+xml;utf8,${encodeURIComponent(hoodiniLogoRaw)}`}catch{return""}})(),getSemaphoreColor=yt=>{const Et=Number(yt)||0;return isFinite(Et)?Et>=90?"#006400":Et>=70?"#7CFC00":Et>=50?"#FFD700":Et>=30?"#FFA500":"#DC143C":"transparent"};function AppSidebar({variant:yt,ultrametric:Et,setUltrametric:xt,showConnectingLines:vt,setShowConnectingLines:bt,showScrollbar:At,setShowScrollbar:Ft,alignLabels:Ct,setAlignLabels:wt,alignCluster:St,setAlignCluster:Tt,useDefaultGeneAlignment:Rt,setUseDefaultGeneAlignment:Pt,defaultAlign:Lt,setDefaultAlign:kt,phyloLabelPosition:Ot,setPhyloLabelPosition:Mt,geneLabelPosition:It,setGeneLabelPosition:Nt,geneColorBy:Ut,setGeneColorBy:jt,treeColorBy:Vt,setTreeColorBy:zt,domainColorBy:Ht,setDomainColorBy:Wt,treeLabelBy:Gt,setTreeLabelBy:qt,geneLabelBy:Xt,setGeneLabelBy:Kt,genePalette:Jt,setGenePalette:tn,phyloPalette:sn,setPhyloPalette:Zt,domainPalette:nn,setDomainPalette:rn,domainSource:on,setDomainSource:ln,ncRNAPalette:Qt,setNcRNAPalette:fn,regionPalette:pn,setRegionPalette:mn,proteinLinkConfig:vn,setProteinLinkConfig:yn,nucleotideLinkConfig:xn,setNucleotideLinkConfig:Mn,treeXScale:$n,setTreeXScale:Rn,viewerLegend:Tn,setViewerLegend:ir,styleConfig:Jn,setStyleConfig:jn,phyloTreeViewerRef:Wn,geneMetadataColumns:br,setGeneMetadataColumns:Fr,treeMetadataColumns:Cr,setTreeMetadataColumns:dr,domainMetadataColumns:_r,setDomainMetadataColumns:pr,selectedGene:wr,handleTrackShiftMinus1kb:xr,handleTrackShiftPlus1kb:Dr,handleTrackFlip:ar,handleArrowheadHeightChange:Qn,handleGeneHeightChange:Cn,tipWidthMode:Bn,setTipWidthMode:In,tipWidthFactor:or,setTipWidthFactor:rr,tipWidthFixed:vr,setTipWidthFixed:cr,showTreeLayer:gn,setShowTreeLayer:wn,showGeneLayer:Xn,setShowGeneLayer:tr,showDomainLayer:Hn,setShowDomainLayer:Kn,showProteinLinkLayer:_n,setShowProteinLinkLayer:yr,showNucleotideLinkLayer:Or,setShowNucleotideLinkLayer:hn,showNcRNALayer:Ar,setShowNcRNALayer:hr,showRegionsLayer:An,setShowRegionsLayer:nr,showGeneTextLayer:gr,setShowGeneTextLayer:ii,showTreeTextLayer:ti,setShowTreeTextLayer:di,showBaselineLayer:Bi,setShowBaselineLayer:as,hasGeneData:ki,hasDomainData:Xi,hasProteinLinkData:_i,hasNucleotideLinkData:ci,hasNcRNAData:xi,hasRegionsData:mi,showFormatGuides:wi,setShowFormatGuides:vi,formatGuidePreset:qi,setFormatGuidePreset:ji,scaleExportToFormat:Ni,setScaleExportToFormat:ls,cropToGuides:xs,setCropToGuides:$s,scaleRulerWithCrop:Is,setScaleRulerWithCrop:Hs,ySpacing:ws,setYSpacing:Es,phyloLabelSize:Ds,setPhyloLabelSize:Fa,geneLabelSize:Ja,setGeneLabelSize:oa,strokeLineWidth:aa,setStrokeLineWidth:Mi,genomeXScale:Wa,setGenomeXScale:Wi,arrowheadHeight:Mo,geneHeight:ys,...Va}){const{resolvedTheme:io,getThemeColors:Fo}=useTheme(),_o=reactExports.useMemo(()=>Fo(io),[io]),[lo,Do]=reactExports.useState("info"),[Cl,ta]=reactExports.useState(!1),ma=typeof Et<"u"?Et:Cl,cs=typeof xt=="function"?xt:ta,[wa,la]=reactExports.useState(!1),Sa=typeof vt<"u"?vt:wa,Io=typeof bt=="function"?bt:la,[xo,Ga]=reactExports.useState(!1),wo=typeof At<"u"?At:xo,Fl=typeof Ft=="function"?Ft:Ga,[ca,za]=reactExports.useState(!1),Uo=typeof Ct<"u"?Ct:ca,Vi=typeof wt=="function"?wt:za,[Os,bs]=reactExports.useState(null),$o=typeof St<"u"?St:Os,al=typeof Tt=="function"?Tt:bs,[qo,Da]=reactExports.useState(!1),qa=typeof Rt<"u"?Rt:qo,Ta=typeof Pt=="function"?Pt:Da,[Zl,$l]=reactExports.useState("start"),Ts=typeof Lt<"u"?Lt:Zl,To=typeof kt=="function"?kt:$l,[Ea,Kr]=reactExports.useState("after-tree"),gs=typeof Ot<"u"?Ot:Ea,Ra=typeof Mt=="function"?Mt:Kr,[po,el]=reactExports.useState(DEFAULT_CONFIG$1.gene.arrowheadHeight),[tl,ll]=reactExports.useState(DEFAULT_CONFIG$1.gene.height),[us,si]=reactExports.useState(DEFAULT_CONFIG$1.gene.tipWidthMode),Un=Bn??us,pi=In??si,[zi,Zi]=reactExports.useState(or??DEFAULT_CONFIG$1.gene.tipWidthFactor),[bi,Fi]=reactExports.useState(vr??DEFAULT_CONFIG$1.gene.tipWidthFixed),[ts,Gi]=reactExports.useState("bottom"),hs=typeof It<"u"?It:ts,Rs=typeof Nt=="function"?Nt:Gi,[vo,go]=reactExports.useState(""),ms=typeof Ut<"u"?Ut:vo,Ii=typeof jt=="function"?jt:go,[Ui,Fs]=reactExports.useState(""),Ws=typeof Vt<"u"?Vt:Ui,Ba=typeof zt=="function"?zt:Fs,[ua,Oo]=reactExports.useState("domainName"),jo=typeof Ht<"u"?Ht:ua,qs=typeof Wt=="function"?Wt:Oo,[Ya,Yo]=reactExports.useState(""),wl=typeof Gt<"u"?Gt:Ya,cl=typeof qt=="function"?qt:Yo,[As,Po]=reactExports.useState(""),da=typeof Xt<"u"?Xt:As,nl=typeof Kt=="function"?Kt:Po,[uo,Ls]=reactExports.useState({enabled:!1}),ya=typeof Jt<"u"?Jt:uo,jl=typeof tn=="function"?tn:Ls,[Ho,hi]=reactExports.useState({enabled:!1}),Bs=typeof sn<"u"?sn:Ho,Li=typeof Zt=="function"?Zt:hi,[_a,na]=reactExports.useState({enabled:!1}),Pl=typeof nn<"u"?nn:_a,lc=typeof rn=="function"?rn:na,[_l,ul]=reactExports.useState("all"),Ec=typeof on<"u"?on:_l,Sl=typeof ln=="function"?ln:ul,[Lo,cc]=reactExports.useState({enabled:!1}),ss=typeof Qt<"u"?Qt:Lo,Dl=typeof fn=="function"?fn:cc,[Ql,so]=reactExports.useState({enabled:!1}),xl=typeof pn<"u"?pn:Ql,Jl=typeof mn=="function"?mn:so,[Ll,uc]=reactExports.useState(null),Xa=typeof vn<"u"?vn:Ll,rl=typeof yn=="function"?yn:uc,[mo,ra]=reactExports.useState(null),dl=typeof xn<"u"?xn:mo,Tl=typeof Mn=="function"?Mn:ra,[Rl,Ma]=reactExports.useState(DEFAULT_CONFIG$1.tree.xScalePercent),[kr,kl]=reactExports.useState(null),bo=typeof Tn<"u"?Tn:kr,[Ys,va]=reactExports.useState(null),dc=typeof Jn<"u"?Jn:Ys,[fc,il]=reactExports.useState(!1),Bl=typeof wi<"u"?wi:fc,sl=typeof vi=="function"?vi:il,[Nl,Ml]=reactExports.useState(null),Hl=typeof qi<"u"?qi:Nl,ko=typeof ji=="function"?ji:Ml,[Zs,En]=reactExports.useState(!1),kn=typeof Ni<"u"?Ni:Zs,Vn=typeof ls=="function"?ls:En,[Nn,Dn]=reactExports.useState(!0),On=typeof xs<"u"?xs:Nn,Pn=typeof $s=="function"?$s:Dn,[Zn,sr]=reactExports.useState(!0),fr=typeof Is<"u"?Is:Zn,mr=typeof Hs=="function"?Hs:sr,[Pr,Ur]=reactExports.useState(DEFAULT_CONFIG$1.tree.ySpacing),[Rr,Wr]=reactExports.useState(DEFAULT_CONFIG$1.tree.ySpacing),$r=typeof Es=="function"?Es:Wr,[qr,Vr]=reactExports.useState(DEFAULT_CONFIG$1.text.phyloLabelSize),[ri,Ei]=reactExports.useState(DEFAULT_CONFIG$1.text.phyloLabelSize),Di=typeof Fa=="function"?Fa:Ei,[Hi,Pi]=reactExports.useState(DEFAULT_CONFIG$1.text.geneLabelSize),[Qi,Si]=reactExports.useState(DEFAULT_CONFIG$1.text.geneLabelSize),Ci=typeof oa=="function"?oa:Si,[Ai,Xs]=reactExports.useState(DEFAULT_CONFIG$1.gene.edgeWidth),[Ks,fa]=reactExports.useState(DEFAULT_CONFIG$1.gene.edgeWidth),ia=typeof Mi=="function"?Mi:fa,[Qs,Ia]=reactExports.useState(DEFAULT_CONFIG$1.genome?.xScalePercent||30),[ba,zl]=reactExports.useState(DEFAULT_CONFIG$1.genome?.xScalePercent||30),Ua=typeof Wi=="function"?Wi:zl,Il=Wn||reactExports.useRef(null),[Oa,Xo]=reactExports.useState(!0),[Pa,Ko]=reactExports.useState(!0),[Zo,Ol]=reactExports.useState(!0),[$a,Aa]=reactExports.useState(!0),[fl,hl]=reactExports.useState(!0),[pl,vl]=reactExports.useState(!0),[bc,zn]=reactExports.useState(!0),[Mr,Br]=reactExports.useState(!0),[Nr,Hr]=reactExports.useState(!0),[Fn,Ln]=reactExports.useState(!0),Gn=gn!==void 0?gn:Oa,er=wn||Xo,Er=Xn!==void 0?Xn:Pa,Tr=tr||Ko,ai=Hn!==void 0?Hn:Zo,Yr=Kn||Ol,li=_n!==void 0?_n:$a,yi=yr||Aa,Ri=Or!==void 0?Or:fl,Ki=hn||hl,ns=Ar!==void 0?Ar:pl,Vs=hr||vl,Ps=An!==void 0?An:bc,ks=nr||zn,Ms=gr!==void 0?gr:Mr,fo=ii||Br,Qo=ti!==void 0?ti:Nr,Jo=di||Hr,ha=Bi!==void 0?Bi:Fn,co=as||Ln,[Ca,Wl]=reactExports.useState(null),[ho,gl]=reactExports.useState("idle"),[sa,Eo]=reactExports.useState(null),[tc,hc]=reactExports.useState(null),Vl=400,Ac="hoodini_nvidia_api_key",[ml,nc]=reactExports.useState(""),[eu,wc]=reactExports.useState(!1),[tu,Nc]=reactExports.useState(null);reactExports.useEffect(()=>{const Gr=localStorage.getItem(Ac);Gr&&nc(Gr)},[]);const[La,en]=reactExports.useState([]),[Sn,dn]=reactExports.useState([]),Yn=reactExports.useCallback(()=>{try{const Gr=Wn&&Wn.current?Wn.current.genomeView:null;if(!Gr){dn([]),en([]);return}const Ti=typeof Gr.getClusterSummary=="function"?Gr.getClusterSummary():null;Ti&&Array.isArray(Ti.items)&&Ti.items.length>0?(en([...Ti.items]),dn([...Ti.ids||[]])):(en([]),dn([]))}catch{dn([]),en([])}},[Wn]);reactExports.useEffect(()=>{Yn()},[]),reactExports.useEffect(()=>{Wn?.current?.genomeView&&setTimeout(()=>{Yn()},100)},[Wn?.current?.genomeView,ki]),reactExports.useEffect(()=>{const Gr=Wn?.current?.genomeView;Gr&&Gr.proteinClusters&&Object.keys(Gr.proteinClusters).length>0&&Yn()},[Wn?.current?.genomeView?.proteinClusters]),reactExports.useEffect(()=>{const Gr=window;return Gr.__hoodini_refreshClusters=()=>(Yn(),{availableClusters:La,liveClusters:Sn}),Gr.__hoodini_clusterState=()=>({availableClusters:La,liveClusters:Sn}),Gr.__hoodini_getGenomeView=()=>Wn&&Wn.current?Wn.current.genomeView:null,()=>{delete Gr.__hoodini_refreshClusters,delete Gr.__hoodini_clusterState,delete Gr.__hoodini_getGenomeView}},[La,Sn,Yn]),reactExports.useEffect(()=>{if(lo!=="settings"||La.length>0)return;const Gr=setInterval(()=>{Yn()},5e3);return()=>clearInterval(Gr)},[lo,La.length,Yn]);const ur=50,lr=reactExports.useMemo(()=>La.slice(0,ur),[La]),ei=reactExports.useMemo(()=>lr.map(Ti=>jsxRuntimeExports.jsx(SelectItem,{value:String(Ti.id),children:Ti.label},Ti.id)),[lr]),zr=br&&br.length>0?br:["cluster","species","geneType"],Yi=Cr&&Cr.length>0?Cr:["species","branchLength","support"],Xr=("".trim().split(/\r?\n/)[0]||"").split(/\t/).map(Gr=>(Gr||"").trim()).filter(Gr=>Gr!==""&&Gr.toLowerCase()!=="domain_id"),eo=["domainName","start","end","evalue","coverage"],$i=Array.isArray(_r)&&_r.length>0?_r.map(Gr=>(Gr||"").toString().trim()).filter(Gr=>Gr!==""&&Gr.toLowerCase()!=="domain_id"):[...eo,...Xr],Qr=wr;reactExports.useEffect(()=>{Wl(null),gl("idle"),Eo(null),to(null),Oi(null),hc(null)},[Qr]);const os=async(Gr,Ti)=>{if(!Gr)return;const rs=Ti||(Gr.length<=Vl?"esmfold":"boltz2");if(rs==="boltz2"&&!ml){gl("needsApiKey"),wc(!0),Wl(Gr);return}if(!(Ca===Gr&&ho==="folding")&&!(sa&&Ca===Gr&&ho==="success")){Wl(Gr),gl("folding"),Nc(rs),Eo(null);try{const es=Qr&&Qr.id||Qr&&Qr.geneId||null;hc(es)}catch{hc(null)}try{to(Gr)}catch{gl("error")}}},Ro=()=>{ml.trim()&&(localStorage.setItem(Ac,ml.trim()),wc(!1),Ca&&ho==="needsApiKey"&&os(Ca,"boltz2"))},Ns=()=>{localStorage.removeItem(Ac),nc("")},[Cs,to]=reactExports.useState(null),[Ss,Oi]=reactExports.useState(null),zs=({pdb:Gr,sequenceLength:Ti,confidence:rs})=>{Eo({pdb:Gr,sequenceLength:Ti,confidence:rs}),gl("success"),Oi(null),Wl(null),to(null)},pa=Qr&&Qr.id||Qr&&Qr.geneId||null;Qr?.metadata?.sequence&&Qr.metadata.sequence.length>0;const ds=!!(pa&&tc&&pa===tc&&(Cs||ho==="success"&&sa)),Js=Gr=>{gl("error"),Oi(Gr||"Unknown viewer error")};return reactExports.useEffect(()=>{},[Cs,ho,sa,Ss]),jsxRuntimeExports.jsxs(Sidebar,{collapsible:"offcanvas",variant:yt,...Va,children:[jsxRuntimeExports.jsx("div",{className:"mx-3 p-1 bg-card/80 backdrop-blur-sm rounded-xl border border-border/50 shadow-sm",style:{backgroundColor:_o.background||void 0},children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"0.5rem",width:"100%"},children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-1 bg-muted/50 p-1 rounded-lg",children:[jsxRuntimeExports.jsx(Button,{variant:lo==="info"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="info"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("info"),title:"Show Info",children:jsxRuntimeExports.jsx(Info,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="settings"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="settings"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("settings"),title:"Show Settings",children:jsxRuntimeExports.jsx(Settings,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="palette"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="palette"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("palette"),title:"Show Palette",children:jsxRuntimeExports.jsx(Palette,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="legend"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="legend"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("legend"),title:"Show Legend",children:jsxRuntimeExports.jsx(BookOpen,{className:"h-3.5 w-3.5"})}),jsxRuntimeExports.jsx(Button,{variant:lo==="guides"?"default":"ghost",size:"sm",className:`h-7 w-7 p-0 rounded-md transition-all ${lo==="guides"?"shadow-sm":"hover:bg-accent/80"}`,onClick:()=>Do("guides"),title:"Show Format Guides",children:jsxRuntimeExports.jsx(Crop,{className:"h-3.5 w-3.5"})})]}),jsxRuntimeExports.jsx("a",{href:"#",className:"font-title text-xs font-medium mr-2",style:{display:"flex",alignItems:"center",gap:"0.5rem"},children:jsxRuntimeExports.jsx("img",{src:hoodiniLogoUrl,alt:"Hoodini Logo",className:"!size-5",style:{width:"200px",height:"100px",filter:io==="dark"?"brightness(0) invert(1)":"none"}})})]})}),jsxRuntimeExports.jsxs("div",{className:"mx-3 my-3 p-3 bg-card/60 backdrop-blur-sm rounded-xl border border-border/40 overflow-y-auto scrollbar-hide",style:{backgroundColor:_o.background||void 0,scrollbarWidth:"none",msOverflowStyle:"none"},children:[lo==="info"&&jsxRuntimeExports.jsxs("div",{className:"space-y-3",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Info,{className:"h-3 w-3 mr-1"}),"Information"]})}),jsxRuntimeExports.jsx("div",{className:"space-y-2",children:Qr?jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"info",className:"text-xs",children:Qr.type==="ncRNA"||Qr.type==="ncRNA_gene"?"ncRNA Details":Qr.type==="region"?"Region Details":"Gene Details"})}),jsxRuntimeExports.jsx("div",{className:"space-y-3",children:Qr.metadata&&Object.keys(Qr.metadata).length>0?jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[(()=>{const Gr=es=>{const yo={};return!es||typeof es!="string"||es.split(";").filter(Bo=>Bo.trim()).forEach(Bo=>{const[El,...yc]=Bo.split("=");El&&yc.length>0&&(yo[El.trim()]=yc.join("=").trim())}),yo},Ti=Qr.metadata.attributes&&typeof Qr.metadata.attributes=="string"?Gr(Qr.metadata.attributes):typeof Qr.metadata.attributes=="object"?Qr.metadata.attributes:{},rs={...Qr.metadata};return Ti&&Object.keys(Ti).length>0&&Object.entries(Ti).forEach(([es,yo])=>{(!rs[es]||rs[es]===rs.attributes)&&(rs[es]=yo)}),delete rs.attributes,Qr._mergedMeta=rs,null})(),(()=>{const Ti=(()=>{const es=ms||"cluster";if(ya?.enabled&&Il?.current)try{let Bo=Qr?.metadata?.[es];if((Bo==null||Bo==="")&&es==="cluster"&&(Bo=Qr?.metadata?.clusterId??Qr?.metadata?.cluster_id??Qr?.cluster),!isEmptyValue(Bo)&&typeof Il.current.geneColorMap<"u"){const El=Il.current.geneColorMap;if(El&&typeof El.get=="function"){const yc=El.get(normalizeKey(Bo));if(yc&&Array.isArray(yc)){const[_c,ou,Yu,au]=yc;return`rgba(${_c}, ${ou}, ${Yu}, ${au!==void 0?au/255:1})`}}}}catch{}if(Qr.fillColor&&Array.isArray(Qr.fillColor)){const[Bo,El,yc,_c]=Qr.fillColor;return`rgba(${Bo}, ${El}, ${yc}, ${_c!==void 0?_c/255:1})`}return Qr.color||"#666"})(),rs=Qr._mergedMeta||Qr.metadata;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[!isEmptyValue(rs.product)&&jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:ms==="product"?"default":"outline",className:`text-xs flex-shrink-0 ${ms==="product"?"border-0":""}`,style:ms==="product"?{backgroundColor:Ti,border:"none"}:{},children:"Product"}),jsxRuntimeExports.jsx("p",{className:"text-xs break-all leading-relaxed flex-1",children:String(rs.product)})]}),!isEmptyValue(rs.cluster)&&jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:ms==="cluster"?"default":"outline",className:`text-xs flex-shrink-0 ${ms==="cluster"?"border-0":""}`,style:ms==="cluster"?{backgroundColor:Ti,color:"white",border:"none"}:{},children:"Cluster"}),jsxRuntimeExports.jsx("p",{className:"text-xs break-all leading-relaxed flex-1",children:String(rs.cluster)})]}),Object.entries(rs).filter(([es,yo])=>!["product","cluster","sequence","structure","clusterId","cluster_id","attributes"].includes(es)&&!isEmptyValue(yo)).map(([es,yo])=>{const Bo=ms===es;return jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:Bo?"default":"outline",className:`text-xs capitalize flex-shrink-0 ${Bo?"border-0":""}`,style:Bo?{backgroundColor:Ti,color:"white",border:"none"}:{},children:es.replace(/_/g," ")}),jsxRuntimeExports.jsx("p",{className:"text-xs break-all leading-relaxed flex-1",children:String(yo)})]},es)}),(Qr.type==="ncRNA"||Qr.type==="ncRNA_gene")&&Qr.metadata.sequence&&jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs",children:"ncRNA Sequence"}),(()=>{const es=Qr.metadata.sequence.replace(/\*+$/,"");return jsxRuntimeExports.jsxs("span",{className:"text-xs text-muted-foreground",children:["Length ",es.length," nt"]})})()]}),jsxRuntimeExports.jsx("div",{className:"mt-1 p-2 bg-muted rounded text-xs font-mono break-all leading-relaxed",children:Qr.metadata.sequence.replace(/\*+$/,"")}),Qr.metadata.structure&&jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsx(ErrorBoundary,{fallback:jsxRuntimeExports.jsx("div",{className:"text-xs text-muted-foreground",children:"RNA viewer error"}),children:jsxRuntimeExports.jsx(RNAStructureViewer,{sequence:Qr.metadata.sequence?.replace(/\*+$/,"")||"",dotBracket:String(Qr.metadata.structure)||""})}),jsxRuntimeExports.jsxs(Collapsible,{children:[jsxRuntimeExports.jsxs(CollapsibleTrigger,{className:"flex items-center gap-2 w-full hover:bg-muted/50 rounded p-1 -ml-1",children:[jsxRuntimeExports.jsx(ChevronRight,{className:"h-3 w-3 transition-transform duration-200 [[data-state=open]>&]:rotate-90"}),jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs",children:"Dot-bracket"}),jsxRuntimeExports.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",String(Qr.metadata.structure).length," chars)"]})]}),jsxRuntimeExports.jsx(CollapsibleContent,{children:jsxRuntimeExports.jsx("div",{className:"mt-1 p-2 bg-muted rounded text-xs font-mono",style:{wordBreak:"break-word",whiteSpace:"pre-wrap",overflowWrap:"break-word"},children:String(Qr.metadata.structure)})})]})]})]}),!(Qr.type==="ncRNA"||Qr.type==="ncRNA_gene")&&Qr.metadata.sequence&&jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs",children:"Protein Sequence"}),(()=>{const es=Qr.metadata.sequence.replace(/\*+$/,""),yo=es.length>Vl;return jsxRuntimeExports.jsxs(Badge,{variant:ho==="folding"||ho==="success"?"default":ho==="error"?"destructive":ho==="needsApiKey"?"outline":"secondary",className:`text-xs ${ho==="folding"?"animate-pulse":ho==="idle"||ho==="needsApiKey"?"cursor-pointer hover:bg-secondary/80":""} ${yo?"bg-purple-100 text-purple-800 dark:bg-purple-900/50 dark:text-purple-200":""}`,onClick:()=>{ho==="idle"||ho==="needsApiKey"?(Oi(null),os(es)):(ho==="success"||ho==="error")&&(gl("idle"),Eo(null),Wl(null),Nc(null))},children:[ho==="idle"&&(yo?"Fold with Boltz2":"Fold Sequence"),ho==="needsApiKey"&&"🔑 Enter API Key",ho==="folding"&&(tu==="boltz2"?"Boltz2...":"Folding..."),ho==="success"&&"View Structure",ho==="error"&&"Retry Folding"]})})(),Qr.metadata.sequence.replace(/\*+$/,"").length>Vl&&ml&&!eu&&ho!=="needsApiKey"?jsxRuntimeExports.jsx(Badge,{variant:"secondary",className:"text-xs bg-green-100 text-green-700 dark:bg-green-900/50 dark:text-green-300 cursor-pointer hover:bg-green-200 dark:hover:bg-green-800/50 px-2",onClick:()=>wc(!0),title:"API key saved - click to manage",children:jsxRuntimeExports.jsx(Key,{className:"h-3 w-3"})}):null]}),(eu||ho==="needsApiKey")&&jsxRuntimeExports.jsxs("div",{className:"p-3 bg-purple-50 dark:bg-purple-950/30 rounded-md border border-purple-200 dark:border-purple-800 space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx("span",{className:"text-xs font-medium text-purple-800 dark:text-purple-200",children:"NVIDIA API Key (for Boltz2)"}),ml&&jsxRuntimeExports.jsx(Badge,{variant:"outline",className:"text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200",children:"✓ Saved"})]}),jsxRuntimeExports.jsxs("div",{className:"flex gap-2",children:[jsxRuntimeExports.jsx(Input$2,{type:"password",placeholder:"nvapi-...",value:ml,onChange:es=>nc(es.target.value),className:"flex-1 font-mono text-xs h-8"}),jsxRuntimeExports.jsx(Button,{size:"sm",onClick:Ro,disabled:!ml.trim(),className:"h-8 text-xs rounded-full px-4",children:"Save & Fold"})]}),jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground",children:["Get your key at"," ",jsxRuntimeExports.jsx("a",{href:"https://build.nvidia.com/mit/boltz2",target:"_blank",rel:"noopener noreferrer",className:"text-purple-600 dark:text-purple-400 underline hover:no-underline",children:"build.nvidia.com"})," ","• Stored locally in your browser"]}),ml&&jsxRuntimeExports.jsx(Button,{variant:"ghost",size:"sm",onClick:Ns,className:"h-6 text-xs text-destructive hover:text-destructive",children:"Clear saved key"})]}),jsxRuntimeExports.jsx("div",{className:"mt-1 p-2 bg-muted rounded text-xs font-mono break-all leading-relaxed",children:Qr.metadata.sequence.replace(/\*+$/,"")}),(()=>{const es=Qr.metadata.sequence.replace(/\*+$/,""),yo=es.length>Vl;return jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground",children:["Sequence length: ",es.length," aa",yo?` (requires Boltz2, >${Vl} aa)`:" (ESMFold compatible)"]})})(),ds&&jsxRuntimeExports.jsxs("div",{className:"mt-2 p-3 bg-accent/10 rounded-md border",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between mb-2",children:[jsxRuntimeExports.jsx("h5",{className:"font-title text-xs font-medium",children:"3D Structure"}),(()=>{const es=sa&&typeof sa.confidence=="number"?sa.confidence:null,yo=es!==null?es<=1?es*100:es:null,Bo=yo!==null?getSemaphoreColor(yo):"transparent",El=yo!==null&&yo>50?"#000":"#fff";return jsxRuntimeExports.jsxs(Badge,{variant:"outline",className:"text-xs font-medium text-white border-0",style:{backgroundColor:Bo,color:El,border:yo===null?"1px dashed rgba(255,255,255,0.12)":void 0},children:["avg pLDDT: ",yo!==null?`${yo.toFixed(0)}%`:ho==="folding"?"loading...":"n/a"]})})()]}),jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(ProteinViewer,{sequence:Cs,pdbData:sa?.pdb,confidence:sa?.confidence,sequenceLength:sa?.sequenceLength,onStructureReady:zs,onError:Js,themeBackground:_o.background},`${Qr?.id||Qr?.geneId||"selected"}`)}),Ss?jsxRuntimeExports.jsxs("div",{className:"mt-2 p-2 bg-destructive/10 rounded border border-destructive/20 text-xs text-destructive",children:[jsxRuntimeExports.jsx("div",{className:"font-medium text-xs",children:"Viewer error"}),jsxRuntimeExports.jsx("div",{className:"text-xs mt-1",children:String(Ss)})]}):jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:["Structure predicted using ",tu==="boltz2"?"Boltz2":"ESMFold"," • ",sa?.sequenceLength||Cs?.length||"..."," residues"]})]})]})]})})()]}):jsxRuntimeExports.jsx("div",{className:"text-muted-foreground text-xs",children:"No metadata available for this gene"})})]}):jsxRuntimeExports.jsxs("div",{className:"p-4 bg-gradient-to-br from-muted/40 to-accent/20 rounded-lg border border-border/30 text-sm leading-relaxed",children:[jsxRuntimeExports.jsxs("div",{className:"text-center mb-4",children:[jsxRuntimeExports.jsx("span",{className:"text-lg font-semibold",children:"Hoodini 🦉🎩"}),jsxRuntimeExports.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Gene Neighborhood Visualization"})]}),jsxRuntimeExports.jsxs("div",{className:"space-y-2 text-xs",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2 p-2 bg-background/50 rounded-md",children:[jsxRuntimeExports.jsx(Badge,{variant:"info",className:"text-xs shrink-0",children:"Settings"}),jsxRuntimeExports.jsx("span",{className:"text-muted-foreground",children:"Configure tree and gene display"})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2 p-2 bg-background/50 rounded-md",children:[jsxRuntimeExports.jsx(Badge,{variant:"success",className:"text-xs shrink-0",children:"Palette"}),jsxRuntimeExports.jsx("span",{className:"text-muted-foreground",children:"Customize colors and styling"})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center gap-2 p-2 bg-background/50 rounded-md",children:[jsxRuntimeExports.jsx(Badge,{variant:"warning",className:"text-xs shrink-0",children:"Legend"}),jsxRuntimeExports.jsx("span",{className:"text-muted-foreground",children:"Understand visualization elements"})]})]}),jsxRuntimeExports.jsx("div",{className:"mt-4 p-2 bg-primary/5 rounded-lg text-center border border-primary/10",children:jsxRuntimeExports.jsxs("p",{className:"text-xs text-muted-foreground",children:[jsxRuntimeExports.jsx("strong",{className:"text-foreground/80",children:"Click on a gene"})," to see its details"]})})]})})]}),lo==="settings"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Settings,{className:"h-3 w-3 mr-1"}),"Settings"]})}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Layer Visibility"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2 mt-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"baseline-layer",className:"text-xs",children:"Baselines"}),jsxRuntimeExports.jsx(Switch,{id:"baseline-layer",checked:ha,onCheckedChange:co})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-layer",className:"text-xs",children:"Tree Layer"}),jsxRuntimeExports.jsx(Switch,{id:"tree-layer",checked:Gn,onCheckedChange:er})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-text-layer",className:"text-xs",children:"Tree Text"}),jsxRuntimeExports.jsx(Switch,{id:"tree-text-layer",checked:Qo,onCheckedChange:Jo})]}),ki&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-layer",className:"text-xs",children:"Gene Layer"}),jsxRuntimeExports.jsx(Switch,{id:"gene-layer",checked:Er,onCheckedChange:Tr})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-text-layer",className:"text-xs",children:"Gene Text"}),jsxRuntimeExports.jsx(Switch,{id:"gene-text-layer",checked:Ms,onCheckedChange:fo})]})]}),Xi&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"domain-layer",className:"text-xs",children:"Domain Layer"}),jsxRuntimeExports.jsx(Switch,{id:"domain-layer",checked:ai,onCheckedChange:Yr})]}),_i&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"protein-link-layer",className:"text-xs",children:"Protein Links"}),jsxRuntimeExports.jsx(Switch,{id:"protein-link-layer",checked:li,onCheckedChange:yi})]}),ci&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"nucleotide-link-layer",className:"text-xs",children:"Nucleotide Links"}),jsxRuntimeExports.jsx(Switch,{id:"nucleotide-link-layer",checked:Ri,onCheckedChange:Ki})]}),xi&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"ncrna-layer",className:"text-xs",children:"ncRNA Layer"}),jsxRuntimeExports.jsx(Switch,{id:"ncrna-layer",checked:ns,onCheckedChange:Vs})]}),mi&&jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"regions-layer",className:"text-xs",children:"Regions Layer"}),jsxRuntimeExports.jsx(Switch,{id:"regions-layer",checked:Ps,onCheckedChange:ks})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Gene Settings"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"arrowhead-height",className:"text-xs mb-1 block",children:["Arrowhead Height: ",po]}),jsxRuntimeExports.jsx(Slider,{id:"arrowhead-height",min:0,max:100,value:[po],onValueChange:Gr=>{el(Gr[0])},onValueCommit:Gr=>{typeof Qn=="function"&&Qn(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"gene-height",className:"text-xs mb-1 block",children:["Gene Height: ",tl]}),jsxRuntimeExports.jsx(Slider,{id:"gene-height",min:10,max:200,value:[tl],onValueChange:Gr=>{ll(Gr[0])},onValueCommit:Gr=>{typeof Cn=="function"&&Cn(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tip-width-mode",className:"text-xs mb-1 block",children:"Arrow Tip Width Mode:"}),jsxRuntimeExports.jsxs(Select,{value:Un,onValueChange:Gr=>pi(Gr),children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"tip-width-mode",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"factor",children:"Proportional"}),jsxRuntimeExports.jsx(SelectItem,{value:"fixed",children:"Fixed"})]})]})]}),Un==="factor"?jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"tip-width-factor",className:"text-xs mb-1 block",children:["Tip Factor: ",(zi*100).toFixed(0),"%"]}),jsxRuntimeExports.jsx(Slider,{id:"tip-width-factor",min:1,max:50,value:[zi*100],onValueChange:Gr=>Zi(Gr[0]/100),onValueCommit:Gr=>{typeof rr=="function"&&rr(Gr[0]/100)},className:"w-full"})]}):jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"tip-width-fixed",className:"text-xs mb-1 flex items-center justify-between",children:[jsxRuntimeExports.jsxs("span",{children:["Fixed Tip Width: ",bi," nt"]}),jsxRuntimeExports.jsx("span",{className:"text-[10px] text-muted-foreground",children:"max 50% of gene"})]}),jsxRuntimeExports.jsx(Slider,{id:"tip-width-fixed",min:0,max:1e3,step:10,value:[bi],onValueChange:Gr=>Fi(Gr[0]),onValueCommit:Gr=>{typeof cr=="function"&&cr(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-label-position",className:"text-xs mb-1 block",children:"Gene Label Position:"}),jsxRuntimeExports.jsxs(Select,{value:hs,onValueChange:Rs,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"gene-label-position",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"bottom",children:"Bottom"}),jsxRuntimeExports.jsx(SelectItem,{value:"center",children:"Center"}),jsxRuntimeExports.jsx(SelectItem,{value:"top",children:"Top"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"gene-label-size",className:"text-xs mb-1 block",children:["Gene Label Size: ",Hi,"px"]}),jsxRuntimeExports.jsx(Slider,{id:"gene-label-size",min:6,max:30,value:[Hi],onValueChange:Gr=>Pi(Gr[0]),onValueCommit:Gr=>{typeof Ci=="function"&&Ci(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-label-by",className:"text-xs mb-1 block",children:"Gene Label By:"}),jsxRuntimeExports.jsx(MultiSelect,{options:["gene_id",...zr].map(Gr=>({label:Gr,value:Gr})),value:da?da.split(",").filter(Boolean):[],onValueChange:Gr=>nl(Gr.length>0?Gr.join(","):""),placeholder:"Select columns...",maxCount:2,className:"text-xs"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"stroke-line-width",className:"text-xs mb-1 block",children:["Stroke Width: ",Ai.toFixed(1)]}),jsxRuntimeExports.jsx(Slider,{id:"stroke-line-width",min:.1,max:3,step:.1,value:[Ai],onValueChange:Gr=>Xs(Gr[0]),onValueCommit:Gr=>{typeof ia=="function"&&ia(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"genome-x-scale",className:"text-xs mb-1 block",children:["Genome X-Scale: ",Qs,"%"]}),jsxRuntimeExports.jsx(Slider,{id:"genome-x-scale",min:1,max:100,value:[Qs],onValueChange:Gr=>Ia(Gr[0]),onValueCommit:Gr=>{typeof Ua=="function"&&Ua(Gr[0])},className:"w-full"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Tree Settings"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"ultrametric",className:"text-xs",children:"Ultrametric Tree"}),jsxRuntimeExports.jsx(Switch,{id:"ultrametric",checked:ma,onCheckedChange:cs})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"connecting-lines",className:"text-xs",children:"Connecting Lines"}),jsxRuntimeExports.jsx(Switch,{id:"connecting-lines",checked:Sa,onCheckedChange:Io})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"scrollbar",className:"text-xs",children:"Show Scrollbar"}),jsxRuntimeExports.jsx(Switch,{id:"scrollbar",checked:wo,onCheckedChange:Fl})]}),jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"align-labels",className:"text-xs",children:"Align Labels"}),jsxRuntimeExports.jsx(Switch,{id:"align-labels",checked:Uo,onCheckedChange:Vi})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"phylo-position",className:"text-xs mb-1 block",children:"Phylo Label Position:"}),jsxRuntimeExports.jsxs(Select,{value:gs,onValueChange:Ra,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"phylo-position",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"after-tree",children:"After Tree"}),jsxRuntimeExports.jsx(SelectItem,{value:"after-tracks",children:"After Tracks"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"tree-x-scale",className:"text-xs mb-1 block",children:["Tree X-Scale: ",Rl,"%"]}),jsxRuntimeExports.jsx(Slider,{id:"tree-x-scale",min:10,max:300,value:[Rl],onValueChange:Gr=>{Ma(Gr[0])},onValueCommit:Gr=>{typeof Rn=="function"&&Rn(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"y-spacing",className:"text-xs mb-1 block",children:["Y Spacing: ",Pr,"px"]}),jsxRuntimeExports.jsx(Slider,{id:"y-spacing",min:50,max:500,step:10,value:[Pr],onValueChange:Gr=>Ur(Gr[0]),onValueCommit:Gr=>{typeof $r=="function"&&$r(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-2",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"phylo-label-size",className:"text-xs mb-1 block",children:["Phylo Label Size: ",qr,"px"]}),jsxRuntimeExports.jsx(Slider,{id:"phylo-label-size",min:8,max:40,value:[qr],onValueChange:Gr=>Vr(Gr[0]),onValueCommit:Gr=>{typeof Di=="function"&&Di(Gr[0])},className:"w-full"})]}),jsxRuntimeExports.jsxs("div",{className:"mt-1",children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-label-by",className:"text-xs mb-1 block",children:"Tree Label By:"}),jsxRuntimeExports.jsx(MultiSelect,{options:["name",...Yi].map(Gr=>({label:Gr,value:Gr})),value:wl?wl.split(",").filter(Boolean):[],onValueChange:Gr=>cl(Gr.length>0?Gr.join(","):""),placeholder:"Select columns...",maxCount:2,className:"text-xs"})]})]})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Alignment Controls"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"hoods-alignment",className:"text-xs mb-1 block",children:"Hoods Alignment:"}),jsxRuntimeExports.jsxs(Select,{value:qa?"default":Ts,onValueChange:Gr=>{Gr==="default"?(Ta(!0),al(null)):(Ta(!1),To(Gr),al(null))},children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"hoods-alignment",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"center",children:"Center"}),jsxRuntimeExports.jsx(SelectItem,{value:"start",children:"Start"}),jsxRuntimeExports.jsx(SelectItem,{value:"end",children:"End"}),jsxRuntimeExports.jsx(SelectItem,{value:"default",children:"Default"})]})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntimeExports.jsxs(Label,{htmlFor:"gene-alignment",className:"text-xs mb-1 block",children:["Gene Alignment: ",La.length>ur?`top ${ur} of ${La.length}`:`${La.length} clusters`]}),jsxRuntimeExports.jsx(Button,{size:"sm",variant:"ghost",onClick:Yn,style:{height:"20px",minHeight:"20px"},children:"Refresh"})]}),jsxRuntimeExports.jsxs(Select,{value:$o!=null?String($o):"none",onValueChange:Gr=>{const Ti=Gr==="none"||Gr==="__more__"?null:String(Gr),rs=window;if(typeof rs.__hoodini_alignCluster=="function")Ti!==null&&rs.__hoodini_alignCluster(Ti);else{al(Ti),Ti!==null&&Ta(!1);try{const es=Il?.current||null;Ti===null?es?.alignByDefaultGenes&&es.alignByDefaultGenes():es?.alignCluster?es.alignCluster(Ti):es?.genomeView?.alignCluster?.(Ti),es?.forceAlignUpdate?.()}catch{}}},children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"gene-alignment",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"none",children:"No Cluster"}),ei,La.length>ur&&jsxRuntimeExports.jsxs(SelectItem,{value:"__more__",disabled:!0,children:["... and ",La.length-ur," more (use console)"]})]})]})]})]})]})]}),lo==="palette"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Palette,{className:"h-3 w-3 mr-1"}),"Color & Palette"]})}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Color Fields"})}),jsxRuntimeExports.jsxs("div",{className:"space-y-2",children:[jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"gene-colors",className:"text-xs mb-1 block",children:"Gene Colors:"}),jsxRuntimeExports.jsxs(Select,{value:ms,onValueChange:Ii,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"gene-colors",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsx(SelectContent,{children:zr.map(Gr=>jsxRuntimeExports.jsx(SelectItem,{value:Gr,children:Gr},Gr))})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"tree-colors",className:"text-xs mb-1 block",children:"Tree Colors:"}),jsxRuntimeExports.jsxs(Select,{value:Ws,onValueChange:Ba,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"tree-colors",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsx(SelectContent,{children:Yi.map(Gr=>jsxRuntimeExports.jsx(SelectItem,{value:Gr,children:Gr},Gr))})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"domain-colors",className:"text-xs mb-1 block",children:"Domain Colors:"}),jsxRuntimeExports.jsxs(Select,{value:jo,onValueChange:qs,children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"domain-colors",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsx(SelectContent,{children:$i.map(Gr=>jsxRuntimeExports.jsx(SelectItem,{value:Gr,children:Gr},Gr))})]})]}),jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(Label,{htmlFor:"domain-source",className:"text-xs mb-1 block",children:"Domain Source:"}),jsxRuntimeExports.jsxs(Select,{value:Ec||"all",onValueChange:Gr=>{try{typeof Sl=="function"?Sl(Gr):Va&&typeof Va.setDomainSource=="function"&&Va.setDomainSource(Gr)}catch{}},children:[jsxRuntimeExports.jsx(SelectTrigger,{id:"domain-source",className:"w-full text-xs",style:{height:"20px",minHeight:"20px"},children:jsxRuntimeExports.jsx(SelectValue,{})}),jsxRuntimeExports.jsxs(SelectContent,{children:[jsxRuntimeExports.jsx(SelectItem,{value:"all",children:"all"}),(()=>{try{const Gr=Wn&&Wn.current?Wn.current.genomeView:null;if(!Gr)return null;const Ti=Gr.getAllDomains?Gr.getAllDomains():[];return Array.from(new Set(Ti.map(es=>String(es&&(es.source||es.metadata&&es.metadata.source)||"unknown")))).sort().map(es=>jsxRuntimeExports.jsx(SelectItem,{value:String(es),children:String(es)},String(es)))}catch{return null}})()]})]})]})]})]}),jsxRuntimeExports.jsx(Separator,{className:"my-2"}),jsxRuntimeExports.jsx("div",{className:"mb-3",children:jsxRuntimeExports.jsx(UnifiedPaletteWidget,{genePalette:ya,setGenePalette:jl,phyloPalette:Bs,setPhyloPalette:Li,domainPalette:Pl,setDomainPalette:lc,ncRNAPalette:ss,setNcRNAPalette:Dl,regionPalette:xl,setRegionPalette:Jl,availableData:{parsedGFF:[1],parsedDomains:Xi?[1]:[],phyloData:[1],ncRNAFeatures:[1],regionFeatures:[1]}})}),jsxRuntimeExports.jsx(Separator,{className:"my-2"}),jsxRuntimeExports.jsxs("div",{className:"mb-3",children:[jsxRuntimeExports.jsx(Label,{className:"text-xs font-medium mb-1 block",children:"Links Color Selection:"}),jsxRuntimeExports.jsx("div",{className:"space-y-1",children:jsxRuntimeExports.jsx(LinkColorWidget,{proteinLinkConfig:Xa,nucleotideLinkConfig:dl,onProteinLinkConfigChange:rl,onNucleotideLinkConfigChange:Tl})})]})]}),lo==="legend"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(BookOpen,{className:"h-3 w-3 mr-1"}),"Legend"]})}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Visualization Legend"})}),jsxRuntimeExports.jsx("div",{className:"space-y-2",children:bo?jsxRuntimeExports.jsx(LegendWidget,{legend:bo,genePalette:ya,phyloPalette:Bs,regionPalette:xl,proteinLinkConfig:Xa,nucleotideLinkConfig:dl,styleConfig:dc,className:"",style:{}}):jsxRuntimeExports.jsxs("div",{className:"p-3 bg-accent/30 rounded-lg text-center",children:[jsxRuntimeExports.jsx("p",{className:"text-xs text-muted-foreground mb-1",children:"No legend data available yet"}),jsxRuntimeExports.jsx("p",{className:"text-xs text-muted-foreground",children:"Legend will appear once data is loaded"})]})})]}),jsxRuntimeExports.jsxs("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-2",children:jsxRuntimeExports.jsx(Badge,{variant:"muted",className:"text-xs",children:"Guide"})}),jsxRuntimeExports.jsxs("div",{className:"text-xs space-y-2 text-muted-foreground",children:[jsxRuntimeExports.jsxs("div",{className:"p-2 bg-accent/20 rounded-md",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1 text-foreground/80",children:"Gene Tracks:"}),jsxRuntimeExports.jsx("p",{children:"• Arrows indicate gene direction and boundaries"}),jsxRuntimeExports.jsx("p",{children:"• Colors represent different metadata categories"})]}),jsxRuntimeExports.jsxs("div",{className:"p-2 bg-accent/20 rounded-md",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1 text-foreground/80",children:"Phylogenetic Tree:"}),jsxRuntimeExports.jsx("p",{children:"• Branch lengths show evolutionary distance"}),jsxRuntimeExports.jsx("p",{children:"• Node colors represent tree metadata"})]}),jsxRuntimeExports.jsxs("div",{className:"p-2 bg-accent/20 rounded-md",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1 text-foreground/80",children:"Protein Domains:"}),jsxRuntimeExports.jsx("p",{children:"• Colored regions within genes"}),jsxRuntimeExports.jsx("p",{children:"• Represent functional protein domains"})]}),jsxRuntimeExports.jsxs("div",{className:"p-2 bg-muted/50 rounded",children:[jsxRuntimeExports.jsx("p",{className:"font-medium mb-1",children:"Links:"}),jsxRuntimeExports.jsx("p",{children:"• Connect related elements across tracks"}),jsxRuntimeExports.jsx("p",{children:"• Show protein or nucleotide relationships"})]})]})]})]}),lo==="guides"&&jsxRuntimeExports.jsxs("div",{className:"space-y-4",children:[jsxRuntimeExports.jsx("div",{className:"flex items-center gap-2 mb-3",children:jsxRuntimeExports.jsxs(Badge,{variant:"soft",className:"text-xs font-medium",children:[jsxRuntimeExports.jsx(Crop,{className:"h-3 w-3 mr-1"}),"Format Guides"]})}),jsxRuntimeExports.jsx("div",{className:"bg-muted/30 p-3 rounded-lg border border-border/30",children:jsxRuntimeExports.jsx(GuideControlsWidget,{guidesVisible:Bl,selectedFormat:Hl,onGuidesVisibleChange:sl,onFormatChange:ko,scaleToFormat:kn,onScaleToFormatChange:Vn,cropToGuides:On,onCropToGuidesChange:Pn,scaleRulerWithCrop:fr,onScaleRulerWithCropChange:mr})})]})]})]})}function SVGExportButton({phyloTreeViewerRef:yt}){const Et=()=>{try{console.log("🖼️ SVGExportButton clicked, ref:",yt.current),console.log("🖼️ exportToSVG method:",yt.current?.exportToSVG),yt.current?.exportToSVG?.()}catch(xt){console.error("🖼️ SVGExportButton error:",xt)}};return jsxRuntimeExports.jsxs(Button,{variant:"ghost",size:"icon",className:"size-7 sm:size-7 min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center border touch-manipulation",onClick:Et,title:"Export current view to SVG",children:[jsxRuntimeExports.jsx(Camera,{size:16}),jsxRuntimeExports.jsx("span",{className:"sr-only",children:"Export SVG"})]})}function ThemeToggle(){const{theme:yt,resolvedTheme:Et,toggleTheme:xt}=useTheme(),vt=Et||yt||"light";return jsxRuntimeExports.jsxs(Button,{variant:"ghost",size:"icon",className:"size-7 sm:size-7 min-w-[44px] min-h-[44px] sm:min-w-0 sm:min-h-0 flex items-center justify-center border touch-manipulation",onClick:xt,title:`Switch to ${vt==="light"?"dark":"light"} theme`,children:[vt==="light"?jsxRuntimeExports.jsx(Moon,{size:16}):jsxRuntimeExports.jsx(Sun,{size:16}),jsxRuntimeExports.jsx("span",{className:"sr-only",children:"Toggle theme"})]})}class PhyloNode{constructor(){this.id=null,this.name=null,this.branchLength=0,this.parent=null,this.branchset=[],this.x=0,this.y=0,this.rootDist=0}getLeaves(){return this.branchset.length===0?[this]:this.branchset.flatMap(Et=>Et.getLeaves())}}class PhyloTree{constructor(Et,xt=DEFAULT_CONFIG$1,vt=!1,bt=null){if(this.config=xt,this.themeColors=bt,this.allNodes=[],this.leafNodes=[],Array.isArray(Et))this.hasTree=!1,this.root=this._createFlatRoot(Et);else if(!Et||Et.trim()==="")this.hasTree=!1,this.root=new PhyloNode,this.root.id=0;else try{this.root=this.parseNewick(Et),this.hasTree=!0}catch(At){console.warn("[PhyloTree] failed to parse Newick; using empty tree",At?.message||At),this.hasTree=!1,this.root=new PhyloNode,this.root.id=0}this.collectAll(),this.hasTree&&this.ladderize(!1),vt&&this.hasTree&&this.makeUltrametric()}_createFlatRoot(Et){const xt=new PhyloNode;return xt.id=0,xt.branchLength=0,xt.name="_root",Et.forEach((vt,bt)=>{const At=new PhyloNode;At.id=bt+1,At.name=String(vt),At.branchLength=1,xt.branchset.push(At)}),xt}parseNewick(Et){for(var xt=[],vt=new PhyloNode,bt=Et.split(/\s*(;|\(|\)|,|:)\s*/),At=0,Ft=0;Ft<bt.length;Ft++){var Ct=bt[Ft];switch(Ct){case"(":{var wt=new PhyloNode;wt.id=At++,vt.branchset=[wt],xt.push(vt),vt=wt;break}case",":{var wt=new PhyloNode;wt.id=At++,xt[xt.length-1].branchset.push(wt),vt=wt;break}case")":vt=xt.pop();break;case":":break;default:{var St=bt[Ft-1];St==")"||St=="("||St==","?vt.name=Ct:St==":"&&(vt.branchLength=parseFloat(Ct)),vt.id=vt.id!==null?vt.id:At++}}}return vt}ladderize(Et=!0){const xt=[],vt=[this.root];let bt=0;for(;vt.length>0;){const Ft=vt.pop();if(xt.push(Ft),Ft._sortIndex=bt++,Ft.branchset)for(const Ct of Ft.branchset)vt.push(Ct)}for(let Ft=xt.length-1;Ft>=0;Ft--){const Ct=xt[Ft];if(!Ct.branchset||Ct.branchset.length===0)Ct.num_tips=1;else{Ct.num_tips=0;for(const wt of Ct.branchset)Ct.num_tips+=wt.num_tips||1}}const At=[this.root];for(;At.length>0;){const Ft=At.pop();if(Ft.branchset&&Ft.branchset.length>0){Ft.branchset.sort((Ct,wt)=>{const St=Ct.num_tips||1,Tt=wt.num_tips||1;return St!==Tt?Et?St-Tt:Tt-St:(Ct._sortIndex||0)-(wt._sortIndex||0)});for(const Ct of Ft.branchset)At.push(Ct)}}this.collectAll()}collectAll(){this.allNodes=[];const Et=xt=>{this.allNodes.push(xt);for(let vt of xt.branchset)Et(vt)};Et(this.root)}setParents(){const Et=(xt,vt=null)=>{xt.parent=vt;for(let bt of xt.branchset)Et(bt,xt)};Et(this.root,null)}computeDistances(){const Et=xt=>{xt.rootDist=(xt.parent?xt.parent.rootDist:0)+(xt.branchLength||0);for(let vt of xt.branchset)Et(vt)};Et(this.root)}getLeafNodes(){return this.root.getLeaves()}assignX(Et){const xt=this.config.tree.ySpacing;for(let vt=0;vt<Et.length;vt++)Et[vt].x=vt*xt}assignInternalX(Et){if(Et.branchset.length===0)return Et.x;const xt=Et.branchset.map(vt=>this.assignInternalX(vt));return Et.x=xt.reduce((vt,bt)=>vt+bt,0)/xt.length,Et.x}scaleY(){const Et=this.allNodes.map(At=>At.rootDist),xt=Math.max(...Et),vt=this.config.tree.fixedCoordinateWidth||2e3,bt=xt>0?vt/xt:1;this.maxEvolutionaryDistance=xt;for(let At of this.allNodes)At.y=At.rootDist*bt}layout(Et){this.setParents(),Et?(this.leafNodes=this.getLeafNodes(),this.leafNodes.sort((xt,vt)=>Et.indexOf(xt.name)-Et.indexOf(vt.name)),this.assignX(this.leafNodes)):(this.leafNodes=this.getLeafNodes(),this.assignX(this.leafNodes)),this.assignInternalX(this.root),this.computeDistances(),this.scaleY()}buildEdges(){const Et=[],xt=this.themeColors?.treeEdges||this.config.tree.edgeColor||[85,85,85,255],vt=bt=>{for(let At of bt.branchset){const Ft=[[bt.y,bt.x],[bt.y,At.x],[At.y,At.x]];Et.push({path:Ft,color:xt,source:bt,target:At}),vt(At)}};return vt(this.root),Et}makeUltrametric(){(!this.allNodes||this.allNodes.length===0)&&this.collectAll(),this.setParents(),this.computeDistances();const Et=this.getLeafNodes(),xt=Math.max(...Et.map(At=>At.rootDist)),vt=At=>{if(At.branchset.length===0){At.rootDist=xt;return}for(let wt of At.branchset)vt(wt);const Ft=At.branchset.map(wt=>wt.rootDist),Ct=Math.min(...Ft);At.rootDist=Ct-Math.max(...At.branchset.map(wt=>wt.branchLength||0)),At.rootDist<0&&(At.rootDist=0)};vt(this.root);const bt=At=>{for(let Ft of At.branchset)Ft.branchLength=Ft.rootDist-At.rootDist,bt(Ft)};this.root.rootDist=0,bt(this.root),this.computeDistances()}}class GFFFeature{constructor(Et,xt,vt,bt,At,Ft){this.seqid=Et,this.start=xt,this.end=vt,this.strand=bt,this.type=At,this.attributes=Ft}}class Gene extends GFFFeature{constructor(Et,xt,vt,bt,At,Ft=DEFAULT_CONFIG$1){super(Et,xt,vt,bt,"gene",At),this.origStart=xt,this.origEnd=vt,this.origStrand=bt,this.domains=[],this.config=Ft||DEFAULT_CONFIG$1,this.fillColor=this.config.gene.fillColor,this.polygon=null,this.trackY=null,this.geneHeight=this.config.gene.height||this.config.gene.defaultHeight,this.centerLine=[],this.metadata={seqid:Et,start:xt,end:vt,strand:bt,attributes:At}}setTrackY(Et){this.trackY=Et,this.updatePolygon()}updatePolygon(){this.polygon=this._buildPolygon(this.trackY,this.geneHeight),this.centerLine=this.computeCenterLine();for(let Et of this.domains)Et.updatePolygon()}_buildPolygon(Et,xt){let vt=this.start,bt=this.end;if(vt>bt){const Rt=vt;vt=bt,bt=Rt}const At=Math.abs(bt-vt),Ft=calculateTipWidth(At,this.config),Ct=xt/2,wt=this.strand==="+",St=this.config.gene.arrowheadHeight||0;if(Ft<1)return[[vt,Et-Ct],[bt,Et-Ct],[bt,Et+Ct],[vt,Et+Ct]];if(St<.1)return wt?[[vt,Et-Ct],[bt-Ft,Et-Ct],[bt,Et],[bt-Ft,Et+Ct],[vt,Et+Ct]]:[[bt,Et-Ct],[vt+Ft,Et-Ct],[vt,Et],[vt+Ft,Et+Ct],[bt,Et+Ct]];const Tt=Ct+St/2;return wt?[[vt,Et-Ct],[bt-Ft,Et-Ct],[bt-Ft,Et-Tt],[bt,Et],[bt-Ft,Et+Tt],[bt-Ft,Et+Ct],[vt,Et+Ct]]:[[bt,Et-Ct],[vt+Ft,Et-Ct],[vt+Ft,Et-Tt],[vt,Et],[vt+Ft,Et+Tt],[vt+Ft,Et+Ct],[bt,Et+Ct]]}computeCenterLine(){const Et=this.polygon;if(!Et||Et.length===0)return[];if(Et.length===5){const xt=[(Et[0][0]+Et[4][0])/2,(Et[0][1]+Et[4][1])/2],vt=Et[2];return[xt,vt]}else if(Et.length===7){const xt=[(Et[0][0]+Et[6][0])/2,(Et[0][1]+Et[6][1])/2],vt=Et[3];return[xt,vt]}else if(Et.length===4){const xt=this.strand==="+",vt=[(Et[0][0]+Et[3][0])/2,(Et[0][1]+Et[3][1])/2],bt=[(Et[1][0]+Et[2][0])/2,(Et[1][1]+Et[2][1])/2];return xt?[vt,bt]:[bt,vt]}else{const xt=[(Et[0][0]+Et[Et.length-1][0])/2,(Et[0][1]+Et[Et.length-1][1])/2],vt=Et[Math.floor(Et.length/2)];return[xt,vt]}}addDomain(Et){Et.setParentGene(this),this.domains.push(Et)}}function clipPolygon(yt,Et){if(!yt||yt.length<3)return null;if(!Et||Et.length<3)return yt;let xt=yt.slice();for(let vt=0;vt<Et.length;vt++){if(xt.length===0)return null;const bt=xt;xt=[];const At=Et[vt],Ft=Et[(vt+1)%Et.length];for(let Ct=0;Ct<bt.length;Ct++){const wt=bt[Ct],St=bt[(Ct+bt.length-1)%bt.length],Tt=isInside(wt,At,Ft),Rt=isInside(St,At,Ft);if(Tt){if(!Rt){const Pt=lineIntersection(St,wt,At,Ft);Pt&&xt.push(Pt)}xt.push(wt)}else if(Rt){const Pt=lineIntersection(St,wt,At,Ft);Pt&&xt.push(Pt)}}}return xt.length>=3?xt:null}function isInside(yt,Et,xt){return(xt[0]-Et[0])*(yt[1]-Et[1])-(xt[1]-Et[1])*(yt[0]-Et[0])>=0}function lineIntersection(yt,Et,xt,vt){const bt=Et[0]-yt[0],At=Et[1]-yt[1],Ft=vt[0]-xt[0],Ct=vt[1]-xt[1],wt=bt*Ct-At*Ft;if(Math.abs(wt)<1e-10)return null;const St=xt[0]-yt[0],Tt=xt[1]-yt[1],Rt=(St*Ct-Tt*Ft)/wt;return[yt[0]+Rt*bt,yt[1]+Rt*At]}class Domain{constructor(Et,xt,vt,bt,At,Ft,Ct,wt=DEFAULT_CONFIG$1){this.geneId=Et,this.domainName=xt,this.origStart=vt,this.origEnd=bt,this.start=vt,this.end=bt,this.source=At,this.evalue=Ft,this.coverage=Ct,this.parentGene=null,this.polygon=null;const St=Ft&&Ft>0?Ft<.001?Ft.toExponential(2):Ft.toFixed(6):Ft,Tt=Ct&&`${(Ct*100).toFixed(1)}%`;this.metadata={geneId:Et,domainName:xt,start:vt,end:bt,source:At,evalue:St,coverage:Tt},this.config=wt||DEFAULT_CONFIG$1}setParentGene(Et){this.parentGene=Et,this.updatePolygon()}updatePolygon(){if(!this.parentGene||!this.parentGene.polygon)return;const Et=this.parentGene,xt=this.createDomainPolygon(Et,this.origStart,this.origEnd);if(xt&&Et.polygon){const vt=this.getGeneClipRect(Et);this.polygon=clipPolygon(xt,vt)}else this.polygon=xt}getGeneClipRect(Et){const vt=(Et.geneHeight||Et.config?.gene?.height||60)/2,bt=Et.trackY,At=Math.min(Et.start,Et.end),Ft=Math.max(Et.start,Et.end);return[[At,bt-vt],[Ft,bt-vt],[Ft,bt+vt],[At,bt+vt]]}getConvexGenePolygon(Et){const xt=Et.geneHeight||Et.config?.gene?.height||60,vt=Et.config?.gene?.arrowheadHeight||0,bt=xt/2,At=bt+vt/2,Ft=Et.trackY;let Ct=Math.min(Et.start,Et.end),wt=Math.max(Et.start,Et.end);const St=wt-Ct,Tt=calculateTipWidth(St,Et.config?.gene),Rt=Et.strand==="+";return Tt<1?[[Ct,Ft-bt],[wt,Ft-bt],[wt,Ft+bt],[Ct,Ft+bt]]:Rt?[[Ct,Ft-bt],[wt-Tt,Ft-At],[wt,Ft],[wt-Tt,Ft+At],[Ct,Ft+bt]]:[[wt,Ft-bt],[Ct+Tt,Ft-At],[Ct,Ft],[Ct+Tt,Ft+At],[wt,Ft+bt]]}createDomainPolygon(Et,xt,vt){const bt=Et.start,At=Et.end,Ft=Math.min(bt,At),wt=Math.max(bt,At)-Ft;if(!Et.centerLine||!Array.isArray(Et.centerLine)||Et.centerLine.length<2||!isFinite(wt)||wt<=0)return null;const Tt=Math.abs(Et.origEnd-Et.origStart)/3;let Rt=xt/Tt,Pt=vt/Tt;if(Rt=Math.max(0,Math.min(1,Rt)),Pt=Math.max(0,Math.min(1,Pt)),Et.strand==="-"){const Wt=1-Pt,Gt=1-Rt;Rt=Wt,Pt=Gt}const Lt=this.interpolateOnLine(Et.centerLine,Rt),kt=this.interpolateOnLine(Et.centerLine,Pt),Ot=this.perpVector(Et.centerLine[0],Et.centerLine[1]),Mt=this.normalize(Ot),It=(typeof Et.geneHeight=="number"?Et.geneHeight:Et.config&&Et.config.gene&&Et.config.gene.height?Et.config.gene.height:10)/2,Nt=Et.config&&Et.config.domain&&typeof Et.config.domain.heightFactor=="number"?Et.config.domain.heightFactor:this.config&&this.config.domain&&this.config.domain.heightFactor||.6,Ut=It*Nt,jt=[Lt[0]-Mt[0]*Ut,Lt[1]-Mt[1]*Ut],Vt=[kt[0]-Mt[0]*Ut,kt[1]-Mt[1]*Ut],zt=[kt[0]+Mt[0]*Ut,kt[1]+Mt[1]*Ut],Ht=[Lt[0]+Mt[0]*Ut,Lt[1]+Mt[1]*Ut];return[jt,Vt,zt,Ht]}interpolateOnLine(Et,xt){const[vt,bt]=Et;return[vt[0]+(bt[0]-vt[0])*xt,vt[1]+(bt[1]-vt[1])*xt]}perpVector(Et,xt){const vt=xt[0]-Et[0];return[-(xt[1]-Et[1]),vt]}normalize(Et){const xt=Math.sqrt(Et[0]*Et[0]+Et[1]*Et[1]);return xt===0?[0,1]:[Et[0]/xt,Et[1]/xt]}}class Link{constructor(){}}class ProteinLink extends Link{constructor(Et,xt,vt,bt=[50,100,220]){super(),this.gAId=Et,this.gBId=xt,this.similarity=vt,this.baseColor=Array.isArray(bt)&&bt.length>=3?bt.slice(0,3):[50,100,220];const At=Math.round(255*(vt/100));this.fillColor=[...this.baseColor,At],this.metadata={gAId:Et,gBId:xt,similarity:vt}}updateColor(Et,xt=null,vt=null,bt=null,At=null){if(!Et){const St=Math.round(255*(this.similarity/100));this.fillColor=[...this.baseColor,St];return}let Ft=this.baseColor,Ct=255;const wt=At?At.slice(0,3):this.baseColor;switch(Et.colorBy){case"source_gene":Ft=xt?xt.slice(0,3):wt;break;case"target_gene":Ft=vt?vt.slice(0,3):wt;break;case"identity_solid":Ft=Et.solidColor?Et.solidColor.slice(0,3):this.baseColor;break;case"identity_gradient":bt&&(Ft=bt.slice(0,3));break;default:Ft=this.baseColor}if(Et.useAlpha){const St=this.similarity/100,Tt=Et.maxAlpha-Et.minAlpha,Rt=Et.minAlpha+St*Tt;Ct=Math.round(Rt*255)}else Ct=Et.colorBy==="identity_solid"?255:Math.round(255*(this.similarity/100));this.fillColor=[...Ft,Ct]}bezierCurve(Et,xt,vt,bt,At=120){const Ft=[];for(let Ct=0;Ct<=1;Ct+=1/At){const wt=Math.pow(1-Ct,3)*Et[0]+3*Math.pow(1-Ct,2)*Ct*xt[0]+3*(1-Ct)*Ct*Ct*vt[0]+Ct*Ct*Ct*bt[0],St=Math.pow(1-Ct,3)*Et[1]+3*Math.pow(1-Ct,2)*Ct*xt[1]+3*(1-Ct)*Ct*Ct*vt[1]+Ct*Ct*Ct*bt[1];Ft.push([wt,St])}return Ft}buildPolygon(Et,xt){if(!Et||!xt)return null;const vt=Math.min(Et.start,Et.end),bt=Math.max(Et.start,Et.end),At=Math.min(xt.start,xt.end),Ft=Math.max(xt.start,xt.end),Ct=Et.trackY,wt=xt.trackY;let St,Tt;Ct<=wt?(St={left:[vt,Ct],right:[bt,Ct]},Tt={left:[At,wt],right:[Ft,wt]}):(St={left:[At,wt],right:[Ft,wt]},Tt={left:[vt,Ct],right:[bt,Ct]});const Rt=(St.left[1]+Tt.right[1])/2,Pt=(Ot,Mt)=>this.bezierCurve(Ot,[Ot[0],Rt],[Mt[0],Rt],Mt,20),Lt=Pt(St.right,Tt.right),kt=Pt(Tt.left,St.left);return[St.left,St.right,...Lt,Tt.right,Tt.left,...kt]}}class NucleotideLink extends Link{constructor(Et,xt,vt,bt,At,Ft,Ct,wt=[220,50,50]){super(),this.seqidA=Et,this.seqidB=bt,this.strandA=xt<=vt?"+":"-",this.strandB=At<=Ft?"+":"-",xt>vt&&([xt,vt]=[vt,xt]),At>Ft&&([At,Ft]=[Ft,At]),this.origStartA=xt,this.origEndA=vt,this.origStartB=At,this.origEndB=Ft,this.startA=xt,this.endA=vt,this.startB=At,this.endB=Ft,this.similarity=Ct,this.baseColor=Array.isArray(wt)&&wt.length>=3?wt.slice(0,3):[220,50,50];const St=Math.round(255*(Ct/100));this.fillColor=[...this.baseColor,St]}updateColor(Et,xt=null){if(!Et){const At=Math.round(255*(this.similarity/100));this.fillColor=[...this.baseColor,At];return}let vt=this.baseColor,bt=255;switch(Et.colorBy){case"solid":vt=Et.solidColor?Et.solidColor.slice(0,3):this.baseColor,Et.useAlpha||(bt=Et.solidColor&&Et.solidColor.length>3?Et.solidColor[3]:255);break;case"identity_gradient":xt&&(vt=xt.slice(0,3)),bt=255;break;default:vt=this.baseColor,bt=Math.round(255*(this.similarity/100))}if(Et.useAlpha){const At=this.similarity/100,Ft=Et.maxAlpha-Et.minAlpha,Ct=Et.minAlpha+At*Ft;bt=Math.round(Ct*255)}this.fillColor=[...vt,bt]}buildPolygon(Et,xt){const vt=[this.startA,this.endA,this.startB,this.endB],bt=[Et,Et,xt,xt],At=Math.min(...vt),Ft=Math.max(...vt),Ct=Math.min(...bt),wt=Math.max(...bt);return[[At,wt],[Ft,wt],[Ft,Ct],[At,Ct]]}buildPolygonFromCoords(Et,xt,vt,bt,At,Ft){const Ct=[[Et,At],[xt,At]],wt=[[vt,Ft],[bt,Ft]];return Ct.sort((St,Tt)=>St[0]-Tt[0]),wt.sort((St,Tt)=>St[0]-Tt[0]),[Ct[0],Ct[1],wt[1],wt[0]]}}class Hood{constructor(Et,xt,vt){this.seqid=Et,this.start=xt,this.end=vt,this.origStart=xt,this.origEnd=vt}set(Et,xt){this.start=Et,this.end=xt,this.origStart=Et,this.origEnd=xt}update(Et,xt){this.start=Et,this.end=xt}get(){return{seqid:this.seqid,start:this.start,end:this.end,origStart:this.origStart,origEnd:this.origEnd}}}class Nucleotide{constructor(Et,xt,vt,bt="+"){this.seqid=Et,this.start=xt,this.end=vt,this.strand=bt,this.genes=[],this.metadata={seqid:Et,start:xt,end:vt,strand:bt},this.hood=null}addGene(Et){this.genes.push(Et)}flip(){const Et=this.start,xt=this.end;this.start=-xt,this.end=-Et,this.strand=this.strand==="+"?"-":"+";for(const vt of this.genes)vt.start=-vt.end,vt.end=-vt.start,vt.strand=vt.strand==="+"?"-":"+",typeof vt.updatePolygon=="function"&&vt.updatePolygon()}shift(Et){this.start+=Et,this.end+=Et;for(const xt of this.genes)xt.start+=Et,xt.end+=Et,typeof xt.updatePolygon=="function"&&xt.updatePolygon()}getGenePolygons(){return this.genes.map(Et=>Et.polygon).filter(Boolean)}setHood(Et,xt){this.hood?this.hood.set(Et,xt):this.hood=new Hood(this.seqid,Et,xt)}getHood(){return this.hood?this.hood.get():null}updateHood(Et,xt){this.hood?this.hood.update(Et,xt):this.setHood(Et,xt)}}class NonCodingFeature extends GFFFeature{constructor(Et,xt,vt,bt,At,Ft,Ct){super(Et,xt,vt,bt,At,Ft),this.config=Ct||DEFAULT_CONFIG$1,this.polygon=null,this.trackY=null,this.featureHeight=this.config?.gene?.height||60,this.metadata={seqid:Et,start:xt,end:vt,strand:bt,type:At,attributes:Ft}}setTrackY(Et){this.trackY=Et,this.updatePolygon()}updatePolygon(){this.polygon=this._buildHalfArrowPolygon(this.trackY,this.featureHeight)}_buildHalfArrowPolygon(Et,xt){let vt=this.start,bt=this.end;if(vt>bt){const Rt=vt;vt=bt,bt=Rt}const At=Math.abs(bt-vt),Ft=calculateTipWidth(At,this.config),Ct=xt/4,wt=this.strand==="+",St=this.config?.gene?.arrowheadHeight||0,Tt=Ct+St/2;return Ft<1?wt?[[vt,Et],[vt,Et+Ct],[bt,Et+Ct],[bt,Et]]:[[bt,Et],[bt,Et-Ct],[vt,Et-Ct],[vt,Et]]:wt?[[vt,Et],[vt,Et+Ct],[bt-Ft,Et+Ct],[bt-Ft,Et+Tt],[bt,Et]]:[[bt,Et],[bt,Et-Ct],[vt+Ft,Et-Ct],[vt+Ft,Et-Tt],[vt,Et]]}}class RegionFeature extends GFFFeature{constructor(Et,xt,vt,bt,At,Ft,Ct){super(Et,xt,vt,bt,At,Ft),this.config=Ct,this.polygon=null,this.trackY=null,this.padding=Ct?.region?.padding||10,this.fillColor=[0,0,0,0],this.strokeColor=[100,100,100,255],this.strokeWidth=Ct?.region?.strokeWidth||2,this.metadata={seqid:Et,start:xt,end:vt,type:At,length:Math.abs(vt-xt)},Ft&&(typeof Ft=="string"||Ft instanceof String?this.metadata.attributes=Ft.toString():typeof Ft=="object"&&Object.assign(this.metadata,Ft))}setTrackY(Et){this.trackY=Et}updatePolygon(Et=[],xt=null){xt!==null&&(this.trackY=xt),this.config||(console.warn("RegionFeature: No config provided, using defaults"),this.config={gene:{height:20,arrowheadHeight:30},region:{padding:10,strokeWidth:2}});const vt=Math.min(this.start,this.end),bt=Math.max(this.start,this.end),At=this.config.gene?.height||20,Ft=this.config.gene?.arrowheadHeight||30,Ct=this.config.region?.padding||this.padding,St=Math.max(At,Ft)/2,Tt=this.trackY-St-Ct,Rt=this.trackY+St+Ct;this.polygon=[[vt,Tt],[bt,Tt],[bt,Rt],[vt,Rt],[vt,Tt]]}containsGene(Et){const xt=Math.min(this.start,this.end),vt=Math.max(this.start,this.end),bt=Math.min(Et.start,Et.end);return!(Math.max(Et.start,Et.end)<xt||bt>vt)}getFillColor(){return[0,0,0,0]}getStrokeColor(){if(this.strokeColor&&this.strokeColor[3]!==0)return this.strokeColor;const Et=(this.type||"").toLowerCase(),xt=this.config?.region?.colors||{};return xt[Et]?xt[Et]:xt.default||[128,128,128,255]}getColorKey(){const Et=this.metadata?.region_id||this.metadata?.ID||this.originalId||"";if(Et){const xt=Et.match(/^([a-zA-Z]+)/);if(xt)return xt[1].toLowerCase()}return this.metadata?.region_type?this.metadata.region_type.toLowerCase():(this.type||"region").toLowerCase()}}const _paletteCache=new Map;function memoGetPalette(yt,Et,xt=!1,vt="qualitative"){const bt=`${yt}::${Et}::${xt}::${vt}`;if(_paletteCache.has(bt))return _paletteCache.get(bt);let At=[];try{At=getPaletteColors(yt,Et,xt,vt)}catch{At=[]}return _paletteCache.set(bt,At),At}class GenomeView{constructor(Et,xt,vt=DEFAULT_CONFIG$1){this.leaves=Et,this.tree=xt,this.config=vt||DEFAULT_CONFIG$1,this.featuresBySeqid={},this.genesById={},this.ncRNAsById={},this.regionsById={},this.nucleotidesBySeqid={},this.globalMin=1/0,this.globalMax=-1/0,this.geneHeight=this.config?.gene?.height||DEFAULT_CONFIG$1.gene.height,this.trackFlipped={},this.trackOffset={},this.hoodRanges={},this.hoodToSeqidMap={},this.seqidToHoodsMap={},this.proteinLinks=[],this.nucleotideLinks=[],this.domainsByGene={},this._genesByOriginalId=new Map,this._genesIndexReady=!1,this._leafIndex=null,this._hoodIndex=null,this._regionsByHood=null,this._rightmostByHood=new Map,this._paletteVersion=0}_ensureLeafIndex(){if(!this._leafIndex){if(!this.tree?.leafNodes){this._leafIndex=new Map;return}this._leafIndex=new Map(this.tree.leafNodes.map((Et,xt)=>[Et.name,xt]))}}_buildGeneIndex(){this._genesByOriginalId=new Map;for(const[Et,xt]of Object.entries(this.genesById)){const vt=xt.originalGeneId;vt&&(this._genesByOriginalId.has(vt)||this._genesByOriginalId.set(vt,[]),this._genesByOriginalId.get(vt).push(Et))}this._genesIndexReady=!0}_addOrUpdateGeneIndex(Et,xt){xt?.originalGeneId&&(this._genesByOriginalId.has(xt.originalGeneId)||this._genesByOriginalId.set(xt.originalGeneId,[]),this._genesByOriginalId.get(xt.originalGeneId).push(Et),this._genesIndexReady=!0)}_invalidateGeneIndex(){this._genesIndexReady=!1}_rebuildRegionsByHood(){this._regionsByHood=new Map;for(const Et of Object.values(this.regionsById))this._regionsByHood.has(Et.hood_id)||this._regionsByHood.set(Et.hood_id,[]),this._regionsByHood.get(Et.hood_id).push(Et)}_buildHoodIntervalIndex(){this._hoodIndex=new Map;for(const[Et,xt]of Object.entries(this.hoodRanges||{})){const vt=this._hoodIndex.get(xt.seqid)||[];vt.push({start:xt.origStart,end:xt.origEnd,hood_id:Et}),this._hoodIndex.set(xt.seqid,vt)}for(const Et of this._hoodIndex.values())Et.sort((xt,vt)=>xt.start-vt.start)}_queryHoodsCovering(Et,xt,vt){const bt=this._hoodIndex?.get(Et)||[];let At=0,Ft=bt.length;for(;At<Ft;){const wt=At+Ft>>1;bt[wt].start<=xt?At=wt+1:Ft=wt}const Ct=[];for(let wt=At-1;wt>=0&&bt[wt].start<=xt;--wt)bt[wt].end>=vt&&Ct.push(bt[wt].hood_id);for(let wt=At;wt<bt.length&&bt[wt].start<=xt;++wt)bt[wt].end>=vt&&Ct.push(bt[wt].hood_id);return Ct}static flipCoordinate(Et,xt){return 2*xt-Et}static getTransformedXUnified(Et,xt,vt,bt){let At=Et+(vt||0);return bt?GenomeView.flipCoordinate(At,xt):At}static getGeneVisualX(Et,xt){const vt=Et.hood_id,bt=xt.hoodRanges[vt];if(!bt)return null;const At=xt.trackOffset[vt]||0,Ft=!!xt.trackFlipped[vt],Ct=(bt.length||0)/2,St=(xt.config.genome&&typeof xt.config.genome.xScalePercent=="number"?xt.config.genome.xScalePercent:100)/100,Tt=Et.origStart||0,Rt=Et.origEnd||0,Pt=Et.origStrand==="+"?Math.min(Tt,Rt):Math.max(Tt,Rt),Lt=GenomeView.getTransformedXUnified(Pt,Ct,At,Ft);return Ct+(Lt-Ct)*St}addFeatures(Et){for(let xt of Et)if(!(!xt.seqid||typeof xt.start!="number"||isNaN(xt.start)||typeof xt.end!="number"||isNaN(xt.end))&&(this.featuresBySeqid[xt.seqid]?(xt.start<this.featuresBySeqid[xt.seqid].origMinStart&&(this.featuresBySeqid[xt.seqid].origMinStart=xt.start),xt.end>this.featuresBySeqid[xt.seqid].origMaxEnd&&(this.featuresBySeqid[xt.seqid].origMaxEnd=xt.end)):(this.featuresBySeqid[xt.seqid]=[],this.featuresBySeqid[xt.seqid].origMinStart=xt.start,this.featuresBySeqid[xt.seqid].origMaxEnd=xt.end),this.featuresBySeqid[xt.seqid].push(xt),!this.nucleotidesBySeqid[xt.seqid])){const vt=this.featuresBySeqid[xt.seqid],bt=Math.min(...vt.map(wt=>typeof wt.start=="bigint"?Number(wt.start):wt.start)),At=Math.max(...vt.map(wt=>typeof wt.end=="bigint"?Number(wt.end):wt.end)),Ft=vt.find(wt=>wt.type==="gene"||wt.type==="CDS"),Ct=Ft&&Ft.strand?Ft.strand:"+";this.nucleotidesBySeqid[xt.seqid]=new Nucleotide(xt.seqid,bt,At,Ct)}}initGenes(){this._invalidateGeneIndex();for(let Et of this.leaves){const xt=this.hoodToSeqidMap[Et];if(!xt)continue;const vt=this.hoodRanges[Et];if(!vt)continue;const bt=vt.origStart||0,At=vt.origEnd||0,Ft=this.featuresBySeqid[xt]||[];for(let Ct of Ft)if(Ct.type==="gene"||Ct.type==="CDS"){const wt=Ct.start||0,St=Ct.end||0;if(!(wt>=bt&&St<=At))continue;const Rt=wt-bt,Pt=St-bt;let Lt=Ct.gene_id||Ct.id||Ct.protein_id||Ct.originalGeneId;!Lt&&Ct.attributes&&(Lt=this.getGeneIdFromAttributes(Ct.attributes));const kt=`${Et}_${Lt}`;let Ot=new Gene(Ct.seqid,Rt,Pt,Ct.strand,Ct.attributes,this.config);Ot.hood_id=Et,Ot.originalGeneId=Lt,this.genesById[kt]=Ot,this._addOrUpdateGeneIndex(kt,Ot),this.nucleotidesBySeqid[xt]&&this.nucleotidesBySeqid[xt].addGene(Ot)}else if(typeof Ct.type=="string"&&Ct.type.toLowerCase().includes("ncrna")){const wt=Ct.start||0,St=Ct.end||0;if(!(wt>=bt&&St<=At))continue;const Rt=wt-bt,Pt=St-bt,Lt=this.getGeneIdFromAttributes(Ct.attributes),kt=`${Et}_${Lt}_${wt}_${St}`;let Ot=new NonCodingFeature(Ct.seqid,Rt,Pt,Ct.strand,Ct.type,Ct.attributes,this.config);Ot.hood_id=Et,Ot.id=kt,Ot.originalId=Lt,Ot.origStart=Rt,Ot.origEnd=Pt,Ot.genomicStart=wt,Ot.genomicEnd=St,Ot.origStrand=Ct.strand;let Mt=null;try{const Nt=Ct.attributes||{};Nt&&typeof Nt=="object"&&(Mt=Nt.ncrna_type||Nt.ncrnaType||Nt.ID||Nt.id||Nt.Name||null),typeof Mt=="object"&&(Mt=String(Mt)),Mt&&(Mt=String(Mt).replace(/^ID=/,"").replace(/;$/,"").trim()),Mt&&(Mt.toLowerCase()==="null"||Mt.toLowerCase()==="none"||Mt==="")&&(Mt=null)}catch{Mt=null}const It=Mt||Lt||Ct.type||"ncRNA";Ot.name=It,(!Ot.metadata||typeof Ot.metadata!="object")&&(Ot.metadata={}),Ot.metadata.type=It,Ot.metadata.attributes=Ct.attributes,this.ncRNAsById[kt]=Ot}else if(Ct.type==="region"){const wt=Ct.start||0,St=Ct.end||0;if(!(wt>=bt&&St<=At))continue;const Rt=wt-bt,Pt=St-bt,Lt=this.getGeneIdFromAttributes(Ct.attributes),kt=`${Et}_${Lt}`;let Ot=new RegionFeature(Ct.seqid,Rt,Pt,Ct.strand,Ct.type,Ct.attributes,this.config);Ot.id=kt,Ot.hood_id=Et,Ot.originalId=Lt,Ot.origStart=Rt,Ot.origEnd=Pt,Ot.origStrand=Ct.strand,this.regionsById[kt]=Ot}}}getGeneIdFromAttributes(Et){if(typeof Et=="string"){const xt=Et.match(/ID=([^;]+)/);return xt?xt[1]:null}else if(typeof Et=="object"&&Et!==null)return Et.ID||null;return null}computeTrackPositions(){const Et={},xt={};for(const At of Object.values(this.genesById))(Et[At.hood_id]||=[]).push(At);for(const At of Object.values(this.ncRNAsById))(xt[At.hood_id]||=[]).push(At);this._rebuildRegionsByHood();const bt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100;this._rightmostByHood.clear();for(let At of this.leaves){const Ft=this.tree.leafNodes.find(jt=>jt.name===At);if(!Ft)continue;const wt=(typeof Ft?.x=="number"?Ft.x:Ft?.y||0)+(this.config?.layout?.geneOffset||0),St=this.hoodToSeqidMap[At];if(!St)continue;const Tt=this.nucleotidesBySeqid[St],Rt=this.trackOffset[At]||0,Pt=this.hoodRanges[At],kt=(Pt?.length||0)/2,Ot=!!this.trackFlipped[At];let Mt=-1/0;const It=Et[At]||[];for(const jt of It){jt.trackY=wt,jt.geneHeight=this.geneHeight;const Vt=jt.origStart||0,zt=jt.origEnd||0;let Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot),Wt=GenomeView.getTransformedXUnified(zt,kt,Rt,Ot);Ht=kt+(Ht-kt)*bt,Wt=kt+(Wt-kt)*bt,jt.start=Ht,jt.end=Wt,jt.strand=Ot?jt.origStrand==="+"?"-":"+":jt.origStrand,["gene_1","gene_2"].includes(jt.id)||jt.originalGeneId?.includes("gene_1")||jt.originalGeneId?.includes("gene_2"),Mt=Math.max(Mt,Ht,Wt);for(let Gt of jt.domains)Gt.updatePolygon();jt.updatePolygon()}const Nt=xt[At]||[];for(const jt of Nt){jt.trackY=wt,jt.featureHeight=this.geneHeight;const Vt=jt.origStart||0,zt=jt.origEnd||0;let Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot),Wt=GenomeView.getTransformedXUnified(zt,kt,Rt,Ot);Ht=kt+(Ht-kt)*bt,Wt=kt+(Wt-kt)*bt,jt.start=Ht,jt.end=Wt,jt.strand=Ot?jt.origStrand==="+"?"-":"+":jt.origStrand,jt.updatePolygon(),Mt=Math.max(Mt,Ht,Wt)}const Ut=this._regionsByHood?.get(At)||[];for(const jt of Ut){jt.trackY=wt;const Vt=jt.origStart||0,zt=jt.origEnd||0;let Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot),Wt=GenomeView.getTransformedXUnified(zt,kt,Rt,Ot);Ht=kt+(Ht-kt)*bt,Wt=kt+(Wt-kt)*bt,jt.start=Ht,jt.end=Wt,jt.strand=Ot?jt.origStrand==="+"?"-":"+":jt.origStrand;const Gt=It.filter(qt=>jt.containsGene(qt));jt.updatePolygon(Gt,wt),Mt=Math.max(Mt,Ht,Wt)}if(Tt&&Tt.hood){const Vt=Pt?Pt.length||0:(Tt.hood.origEnd||0)-(Tt.hood.origStart||0);let zt=GenomeView.getTransformedXUnified(0,kt,Rt,Ot),Ht=GenomeView.getTransformedXUnified(Vt,kt,Rt,Ot);zt=kt+(zt-kt)*bt,Ht=kt+(Ht-kt)*bt,Tt.hood.start=zt,Tt.hood.end=Ht,Mt=Math.max(Mt,zt,Ht)}if(Tt){let jt=GenomeView.getTransformedXUnified(0,kt,Rt,Ot),Vt=GenomeView.getTransformedXUnified(Pt&&Pt.length||0,kt,Rt,Ot);jt=kt+(jt-kt)*bt,Vt=kt+(Vt-kt)*bt,Tt.start=jt,Tt.end=Vt,Mt=Math.max(Mt,jt,Vt)}isFinite(Mt)&&this._rightmostByHood.set(At,Mt)}this.updateLinkPositions(),this.updateGlobalBounds()}updateGlobalBounds(){let Et=1/0,xt=-1/0;const vt=this.leaves&&this.leaves.length>0,bt=vt?new Set(this.leaves.map(Ft=>String(Ft))):null,At=vt?new Set:null;if(vt)for(const Ft of bt){const Ct=this.hoodToSeqidMap[Ft];Ct&&At.add(Ct)}for(const Ft of Object.values(this.genesById))if(!(bt&&Ft.hood_id&&!bt.has(String(Ft.hood_id))))if(Ft.polygon)for(const[Ct]of Ft.polygon)Ct<Et&&(Et=Ct),Ct>xt&&(xt=Ct);else Ft.start!==void 0&&Ft.end!==void 0&&(Ft.start<Et&&(Et=Ft.start),Ft.end<Et&&(Et=Ft.end),Ft.start>xt&&(xt=Ft.start),Ft.end>xt&&(xt=Ft.end));for(const Ft of Object.values(this.ncRNAsById))if(!(bt&&Ft.hood_id&&!bt.has(String(Ft.hood_id))))if(Ft.polygon)for(const[Ct]of Ft.polygon)Et=Math.min(Et,Ct),xt=Math.max(xt,Ct);else Ft.start!==void 0&&Ft.end!==void 0&&(Et=Math.min(Et,Ft.start,Ft.end),xt=Math.max(xt,Ft.start,Ft.end));for(const Ft of this.getAllDomains()){const Ct=Ft.parentGene;if(bt&&Ct?.hood_id&&!bt.has(String(Ct.hood_id)))continue;const wt=Ft.polygon;if(wt)for(const[St]of wt)Et=Math.min(Et,St),xt=Math.max(xt,St)}isFinite(Et)&&isFinite(xt)&&(this.globalMin=Et,this.globalMax=xt)}updateLinkPositions(){for(let Et of this.nucleotideLinks)Et.startA=Et.origStartA,Et.endA=Et.origEndA,Et.startB=Et.origStartB,Et.endB=Et.origEndB}addDomains(Et){this.domainsByGene=Et,this._cachedAllDomains=void 0,this._genesIndexReady||this._buildGeneIndex();for(const xt in Et){const vt=this._genesByOriginalId.get(xt)||[];for(const bt of vt){const At=this.genesById[bt];if(At){for(let Ft of Et[xt]){this.hoodRanges[At.hood_id];let Ct=new Domain(bt,Ft.domainName,Ft.start,Ft.end,Ft.source,Ft.evalue,Ft.coverage);At.addDomain(Ct)}At.metadata||(At.metadata={}),At.metadata.domainsSummary=At.domains&&At.domains.length>0?At.domains.map(Ft=>`${Ft.domainName}(${Ft.start}-${Ft.end})`).join(";"):""}}}}addDomainMetadata(Et){if(!Et)return;this._cachedAllDomains=void 0;let xt=Et;if(Array.isArray(Et)){xt={};for(const vt of Et){const bt=vt.domain_id||vt.domain||vt.domainName||vt.domain_name||vt.id;bt&&(xt[bt]=vt)}}for(const vt in this.genesById){const bt=this.genesById[vt];if(!(!bt.domains||bt.domains.length===0))for(const At of bt.domains){const Ft=At.domainName,Ct=xt[Ft];Ct&&(At.metadata={...At.metadata,...Ct})}}}addProteinLinks(Et,xt=[50,100,220],vt=1/0){this._genesIndexReady||this._buildGeneIndex(),this._ensureLeafIndex(),this.proteinLinks.length=0;const bt=new Set;for(let At of Et){let Ft,Ct,wt;Array.isArray(At)?(Ft=At[0],Ct=At[1],wt=At[2]):At&&typeof At=="object"&&(Ft=At.geneA??At.gAId,Ct=At.geneB??At.gBId,wt=At.score??At.similarity);const St=this._genesByOriginalId.get(Ft)||[],Tt=this._genesByOriginalId.get(Ct)||[];for(const Rt of St)for(const Pt of Tt){const Lt=this.genesById[Rt],kt=this.genesById[Pt];if(!Lt||!kt)continue;const Ot=this._leafIndex.get(Lt.hood_id),Mt=this._leafIndex.get(kt.hood_id);if(Ot==null||Mt==null||Math.abs(Ot-Mt)<=vt){const It=Rt<Pt?`${Rt}|${Pt}`:`${Pt}|${Rt}`;if(bt.has(It))continue;bt.add(It),this.proteinLinks.push(new ProteinLink(Rt,Pt,wt,xt))}}}}addNucleotideLinks(Et,xt=[220,50,50],vt=1/0){this._hoodIndex||this._buildHoodIntervalIndex(),this._ensureLeafIndex(),this.nucleotideLinks.length=0;for(let bt of Et){const{seqidA:At,seqidB:Ft,startA:Ct,endA:wt,startB:St,endB:Tt,similarity:Rt}=bt,Pt=this._queryHoodsCovering(At,Ct,wt),Lt=this._queryHoodsCovering(Ft,St,Tt);for(const kt of Pt){const Ot=this.hoodRanges[kt];if(Ot)for(const Mt of Lt){const It=this.hoodRanges[Mt];if(!It)continue;const Nt=this._leafIndex.get(kt),Ut=this._leafIndex.get(Mt);if(Nt==null||Ut==null||Math.abs(Nt-Ut)<=vt){const jt=new NucleotideLink(At,Ct,wt,Ft,St,Tt,Rt,xt);jt.hoodA=kt,jt.hoodB=Mt,jt.hoodStartA=Ct-Ot.origStart,jt.hoodEndA=wt-Ot.origStart,jt.hoodStartB=St-It.origStart,jt.hoodEndB=Tt-It.origStart,this.nucleotideLinks.push(jt)}}}}}applyProteinLinkColors(Et,xt=null){if(!this.proteinLinks?.length)return;let vt=null;if(Et?.colorBy==="identity_gradient"&&Et?.palette?.enabled)try{vt=memoGetPalette(Et.palette.name,Et.palette.numColors,Et.palette.reverse)}catch{vt=null}for(const bt of this.proteinLinks){const At=this.genesById[bt.gAId],Ft=this.genesById[bt.gBId],Ct=Et?.colorBy==="source_gene"?At?.fillColor||xt:null,wt=Et?.colorBy==="target_gene"?Ft?.fillColor||xt:null;let St=null;if(Et?.colorBy==="identity_gradient"&&vt){const Tt=Math.max(0,Math.min(1,bt.similarity/100)),Rt=Math.floor(Tt*(vt.length-1));St=vt[Rt]}bt.updateColor(Et,Ct,wt,St,xt)}}applyNucleotideLinkColors(Et){if(!this.nucleotideLinks?.length)return;let xt=null;if(Et?.colorBy==="identity_gradient"&&Et?.palette?.enabled)try{xt=memoGetPalette(Et.palette.name,Et.palette.numColors,Et.palette.reverse)}catch{xt=null}for(const vt of this.nucleotideLinks){let bt=null;if(Et?.colorBy==="identity_gradient"&&xt){const At=Math.max(0,Math.min(1,vt.similarity/100)),Ft=Math.floor(At*(xt.length-1));bt=xt[Ft]}vt.updateColor(Et,bt)}}getTrackY(Et){const xt=this.getHoodIdsFromSeqid(Et);if(xt.length>0){const vt=xt[0],bt=this.tree.leafNodes.find(At=>At.name===vt);return bt?bt.x:null}return null}getTrackYByHoodId(Et){const xt=this.tree.leafNodes.find(vt=>vt.name===Et);return xt?xt.x:null}filterBySelectedNode(Et){if(!Et)return{genes:Object.values(this.genesById),proteinPolygons:this.getProteinPolygons(),nucleotidePolygons:this.getNucleotidePolygons(),domains:this.getAllDomains(),ncRNAs:Object.values(this.ncRNAsById)};const xt=new Set(this.getNodeDescendantLeaves(Et)),vt=Object.values(this.genesById).filter(wt=>xt.has(wt.hood_id||this.getHoodIdFromSeqid(wt.seqid))),bt=this.getProteinPolygons().filter(wt=>wt.seqids?wt.seqids.every(St=>xt.has(this.getHoodIdFromSeqid(St))):!0),At=this.getNucleotidePolygons().filter(wt=>wt.seqids.every(St=>xt.has(this.getHoodIdFromSeqid(St)))),Ft=this.getAllDomains().filter(wt=>{const St=wt.geneId?this.genesById[wt.geneId]:null,Tt=St?.hood_id||this.getHoodIdFromSeqid(St?.seqid);return Tt?xt.has(Tt):!0}),Ct=Object.values(this.ncRNAsById).filter(wt=>xt.has(wt.hood_id||this.getHoodIdFromSeqid(wt.seqid)));return{genes:vt,proteinPolygons:bt,nucleotidePolygons:At,domains:Ft,ncRNAs:Ct}}getProteinPolygons(){const Et=[];for(let xt of this.proteinLinks){const vt=this.genesById[xt.gAId],bt=this.genesById[xt.gBId];if(!vt||!bt)continue;const At=xt.buildPolygon(vt,bt);At&&Et.push({polygon:At,fillColor:xt.fillColor,metadata:xt.metadata})}return Et}getNucleotidePolygons(){const Et=[],vt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100,bt={};for(let At of this.leaves){if(!this.hoodToSeqidMap[At])continue;const Ct=this.hoodRanges[At],wt=this.trackOffset[At]||0,St=!!this.trackFlipped[At],Tt=Ct?(Ct.length||0)/2:0;bt[At]={anchor:Tt,flipped:St,offset:wt,xScale:vt}}for(let At of this.nucleotideLinks){const Ft=At.hoodA,Ct=At.hoodB;if(!Ft||!Ct)continue;const wt=this.getTrackYByHoodId(Ft),St=this.getTrackYByHoodId(Ct);if(wt==null||St==null)continue;const Tt=bt[Ft],Rt=bt[Ct];if(!Tt||!Rt)continue;let Pt=GenomeView.getTransformedXUnified(At.hoodStartA||0,Tt.anchor,Tt.offset,Tt.flipped),Lt=GenomeView.getTransformedXUnified(At.hoodEndA||0,Tt.anchor,Tt.offset,Tt.flipped),kt=GenomeView.getTransformedXUnified(At.hoodStartB||0,Rt.anchor,Rt.offset,Rt.flipped),Ot=GenomeView.getTransformedXUnified(At.hoodEndB||0,Rt.anchor,Rt.offset,Rt.flipped);Pt=Tt.anchor+(Pt-Tt.anchor)*Tt.xScale,Lt=Tt.anchor+(Lt-Tt.anchor)*Tt.xScale,kt=Rt.anchor+(kt-Rt.anchor)*Rt.xScale,Ot=Rt.anchor+(Ot-Rt.anchor)*Rt.xScale;const Mt=At.buildPolygonFromCoords(Pt,Lt,kt,Ot,wt,St);Et.push({polygon:Mt,fillColor:At.fillColor,metadata:At.metadata,seqids:[At.seqidA,At.seqidB]})}return Et}getAllDomains(){if(this._cachedAllDomains!==void 0)return this._cachedAllDomains;const Et=[];let xt=0,vt=0;for(const bt in this.genesById){const At=this.genesById[bt];for(let Ft of At.domains){xt++;let Ct=Ft.polygon;Array.isArray(Ct)&&Ct.length===1&&Array.isArray(Ct[0])&&(Ct=Ct[0]),isValidPolygon(Ct)&&(vt++,Et.push({polygon:Ct,fillColor:Ft.fillColor,domainName:Ft.domainName,metadata:Ft.metadata,geneId:Ft.geneId}))}}try{typeof window<"u"&&window.__hoodini_debug&&console.debug(`GenomeView.getAllDomains: total=${xt}, valid=${vt}`)}catch{}return this._cachedAllDomains=Et,Et}getAllNcRNAs(){return Object.values(this.ncRNAsById)}getAllRegions(){return Object.values(this.regionsById)}getAllNonCodingFeatures(){return this.getAllNcRNAs()}getRegionPolygons(){const Et=[];for(const xt of Object.values(this.regionsById))xt.polygon&&Array.isArray(xt.polygon)&&xt.polygon.length>0&&Et.push({polygon:xt.polygon,fillColor:xt.getFillColor(),strokeColor:xt.getStrokeColor(),strokeWidth:xt.strokeWidth,metadata:xt.metadata});return Et}getNodeDescendantLeaves(Et){if(!Et)return[];function xt(vt){return vt.branchset.length===0&&vt.name?[vt.name]:vt.branchset.flatMap(xt)}return xt(Et)}buildScaleBar(){const Et=this.config?.layout?.scaleBarOffset??this.config?.layout?.padding??150,xt=this.tree.leafNodes[this.tree.leafNodes.length-1].x+Et;return[[{path:[[this.globalMin,xt],[this.globalMax,xt]],color:this.config?.colors?.black||[0,0,0,255]}],xt]}buildPhyloLabels(Et="after-tree"){const xt=this.config?.tree?.labelOffset||10,vt=this.config?.colors?.black||[10,10,10,255],bt=this.config?.text?.phyloLabelSize||14;return this.tree.leafNodes.map(At=>{let Ft;if(Et==="after-tracks"){const Ct=At.name;let wt=this._rightmostByHood.get(Ct);isFinite(wt)?wt+=xt:wt=At.y+xt,Ft=[wt,At.x]}else Ft=[At.y+xt,At.x];return{position:Ft,text:At.name,color:vt,size:bt,textAnchor:"start",leafNode:At}})}buildNodePoints(Et,xt){const vt=Et?new Set(this.getNodeDescendantLeaves(Et)):null,bt=this.config?.tree?.nodeRadius||DEFAULT_CONFIG$1.tree.nodeRadius;return this.tree.allNodes.map(At=>{const Ft=this.getNodeDescendantLeaves(At),Ct=!Et||Ft.some(St=>vt.has(St));let wt;if(At.branchset.length>0)wt=[0,0,0,255];else{const St=At.metadata||{};if(St[xt]){const Tt=String(St[xt]);let Rt=0;for(let Ot=0;Ot<Tt.length;++Ot)Rt=Tt.charCodeAt(Ot)+((Rt<<5)-Rt);const Pt=Rt>>0&255,Lt=Rt>>8&255,kt=Rt>>16&255;wt=[Math.abs(Pt),Math.abs(Lt),Math.abs(kt),255]}else wt=[100,100,100,255]}return Et&&!Ct&&(wt=this.fadeColor(wt,.1)),{id:At.id,node:At,position:[At.y,At.x],color:wt,radius:At.branchset.length>0?bt.internal:bt.leaf,metadata:At.metadata||{name:At.name,id:At.id}}})}buildEdgesWithMetadata(){return this.tree.buildEdges().map(Et=>({...Et,metadata:{source:Et.source?.name,target:Et.target?.name,branchLength:Et.source?.branchLength,id:Et.source?.id}}))}fadeColor(Et,xt){return[Et[0],Et[1],Et[2],Math.floor(Et[3]*xt)]}setProteinClusters(Et){if(!Et||Object.keys(Et).length===0){this.proteinClusters={},this._clusterSummary=null;return}this.proteinClusters={},this._genesIndexReady||this._buildGeneIndex();for(const bt of Object.keys(Et)){const At=Et[bt],Ft=At==null?null:String(At).trim(),Ct=this._genesByOriginalId.get(bt)||[];for(const wt of Ct)this.proteinClusters[wt]=Ft}if(this._clusterSummary=null,!this.clusterColors)return;const xt=this.genesById,vt=this.clusterColors;for(const bt in xt){const At=xt[bt],Ft=this.proteinClusters[bt];At.fillColor=Ft&&vt[Ft]?vt[Ft]:null,At.metadata||(At.metadata={}),At.metadata.clusterId=Ft||null}}setProteinClustersWithPalette(Et,xt=null){this.proteinClusters={},this._genesIndexReady||this._buildGeneIndex();for(const At in Et){const Ft=Et[At],Ct=Ft==null?null:String(Ft).trim(),wt=this._genesByOriginalId.get(At)||[];for(const St of wt)this.proteinClusters[St]=Ct}if(this._clusterSummary=null,!xt||!xt.enabled){for(const At in this.genesById){const Ft=this.genesById[At];Ft&&Ft.fillColor&&(Ft.fillColor=null)}this._paletteVersion++;return}this.clusterColors={};const vt=Array.from(new Set(Object.values(this.proteinClusters))).filter(At=>At!=null).sort((At,Ft)=>{const Ct=Number(At),wt=Number(Ft);return!isNaN(Ct)&&!isNaN(wt)?Ct-wt:String(At).localeCompare(String(Ft))});let bt=[];if(xt.name)try{bt=memoGetPalette(xt.name,Math.max(vt.length,xt.numColors||vt.length),xt.reverse||!1)}catch{bt=[]}if(bt.length===0&&(bt=vt.map((At,Ft)=>hslToRgb(Ft/vt.length,.6,.5).concat(255))),vt.forEach((At,Ft)=>{this.clusterColors[At]=bt[Ft%bt.length]}),xt.desaturateByPrevalence){const At=this.computeGenePrevalence("cluster");for(const Ft in this.clusterColors){const Ct=At.get(Ft)||0;this.clusterColors[Ft]=this._desaturateColorByPrevalence(this.clusterColors[Ft],Ct)}}this._clusterSummary=null;for(const At in this.genesById){const Ft=this.genesById[At],Ct=this.proteinClusters[At];Ft.fillColor=Ct&&this.clusterColors[Ct]?this.clusterColors[Ct]:null,Ft.metadata||(Ft.metadata={}),Ft.metadata.clusterId=Ct||null}this._paletteVersion++}computeGenePrevalence(Et="cluster"){const xt=Object.keys(this.hoodRanges).length;if(xt===0)return new Map;const vt=new Map;for(const At of Object.values(this.genesById)){if(!At.hood_id)continue;let Ft=null;if(Et==="cluster"?Ft=At.metadata?.cluster??At.metadata?.clusterId??At.cluster:Ft=At.metadata?.[Et],Ft==null||Ft==="")continue;const Ct=String(Ft);vt.has(Ct)||vt.set(Ct,new Set),vt.get(Ct).add(At.hood_id)}const bt=new Map;for(const[At,Ft]of vt){const Ct=Ft.size/xt;bt.set(At,Ct)}return bt}_desaturateColorByPrevalence(Et,xt){if(!Et||!Array.isArray(Et)||xt>=1)return Et;const[vt,bt,At,Ft=255]=Et,Ct=vt/255,wt=bt/255,St=At/255,Tt=Math.max(Ct,wt,St),Rt=Math.min(Ct,wt,St),Pt=Tt-Rt,Lt=(Tt+Rt)/2;let kt=0;Pt!==0&&(kt=Lt>.5?Pt/(2-Tt-Rt):Pt/(Tt+Rt));let Ot=0;Pt!==0&&(Tt===Ct?Ot=((wt-St)/Pt+(wt<St?6:0))/6:Tt===wt?Ot=((St-Ct)/Pt+2)/6:Ot=((Ct-wt)/Pt+4)/6);const Mt=1-xt,It=kt*(1-Mt*.8),Nt=(1-Math.abs(2*Lt-1))*It,Ut=Nt*(1-Math.abs(Ot*6%2-1)),jt=Lt-Nt/2;let Vt=0,zt=0,Ht=0;const Wt=Math.floor(Ot*6);return Wt===0?(Vt=Nt,zt=Ut,Ht=0):Wt===1?(Vt=Ut,zt=Nt,Ht=0):Wt===2?(Vt=0,zt=Nt,Ht=Ut):Wt===3?(Vt=0,zt=Ut,Ht=Nt):Wt===4?(Vt=Ut,zt=0,Ht=Nt):(Vt=Nt,zt=0,Ht=Ut),[Math.round((Vt+jt)*255),Math.round((zt+jt)*255),Math.round((Ht+jt)*255),Ft]}_transparentByPrevalence(Et,xt,vt=.1){if(!Et||!Array.isArray(Et))return Et;const[bt,At,Ft]=Et,Ct=Math.round(vt*255+xt*(255-vt*255));return[bt,At,Ft,Ct]}_computeClusterSummary(){const Et=this.proteinClusters||{},xt=Object.values(Et).reduce((bt,At)=>{const Ft=String(At);return bt[Ft]=(bt[Ft]||0)+1,bt},{}),vt=Object.entries(xt).map(([bt,At])=>({id:bt,size:Number(At),label:`Cluster ${bt} (${At} genes)`})).sort((bt,At)=>At.size-bt.size);return{items:vt,ids:vt.map(bt=>bt.id)}}getClusterSummary(){return this._clusterSummary?this._clusterSummary:(this._clusterSummary=this._computeClusterSummary(),this._clusterSummary)}setNcRNAColorsWithPalette(Et=null){const xt=Object.values(this.ncRNAsById);if(!Et||!Et.enabled){for(const Ct of xt)Ct.fillColor=this.config?.gene?.fillColor||[200,200,200,255];return}const vt=xt.filter(Ct=>{const wt=Ct.metadata&&Ct.metadata.type;return!isEmptyValue(wt)});if(vt.length===0)return;const bt=Array.from(new Set(vt.map(Ct=>normalizeKey(Ct.metadata.type))));let At=[];if(Et.name)try{At=memoGetPalette(Et.name,Math.max(bt.length,Et.numColors||bt.length),Et.reverse||!1)}catch{At=[]}At.length===0&&(At=bt.map((Ct,wt)=>{const St=wt/bt.length;return hslToRgb(St,.6,.5).concat(255)}));const Ft={};bt.forEach((Ct,wt)=>{Ft[Ct]=At[wt%At.length]});for(const Ct in this.ncRNAsById){const wt=this.ncRNAsById[Ct],St=wt.metadata&&wt.metadata.type;isEmptyValue(St)||(wt.fillColor=Ft[normalizeKey(St)])}}setRegionColorsWithPalette(Et=null){const xt=Object.values(this.regionsById);if(xt.length===0)return;if(!Et||!Et.enabled){for(const Ct of xt)Ct.fillColor=[0,0,0,0],Ct.strokeColor=[100,100,100,255];return}const vt=xt.map(Ct=>Ct.getColorKey()).map(Ct=>normalizeKey(Ct)).filter(Ct=>!isEmptyValue(Ct)),bt=[...new Set(vt)];if(bt.length===0)return;let At=[];if(Et.name)try{At=memoGetPalette(Et.name,Math.max(bt.length,Et.numColors||bt.length),Et.reverse||!1)}catch{At=[]}At.length===0&&(At=bt.map((Ct,wt)=>{const St=wt/bt.length;return hslToRgb(St,.6,.5).concat(255)}));const Ft={};bt.forEach((Ct,wt)=>{Ft[Ct]=At[wt%At.length]});for(const Ct in this.regionsById){const wt=this.regionsById[Ct],St=wt.getColorKey();isEmptyValue(St)||(wt.fillColor=Ft[normalizeKey(St)])}}toggleTrackFlip(Et){this.trackFlipped[Et]=!this.trackFlipped[Et]}flipTrack(Et){const xt=this.trackOffset[Et]||0,vt=this.getTrackAnchor(Et),At=!!this.trackFlipped[Et]?GenomeView.flipCoordinate(vt+xt,vt):vt+xt;this.trackFlipped[Et]=!this.trackFlipped[Et];const Ft=!!this.trackFlipped[Et];let Ct;Ft?Ct=vt-At:Ct=At-vt,this.trackOffset[Et]=Ct,this.computeTrackPositions()}flipTrackState(Et){this.trackFlipped[Et]=!this.trackFlipped[Et]}flipTrackStateWithCentering(Et){const xt=this.trackOffset[Et]||0,vt=this.getTrackAnchor(Et),At=!!this.trackFlipped[Et]?GenomeView.flipCoordinate(vt+xt,vt):vt+xt;this.trackFlipped[Et]=!this.trackFlipped[Et];const Ft=!!this.trackFlipped[Et];let Ct;Ft?Ct=vt-At:Ct=At-vt,this.trackOffset[Et]=Ct}shiftTrack(Et,xt){this.trackOffset[Et]||(this.trackOffset[Et]=0),this.trackFlipped[Et]&&(xt=-xt),this.trackOffset[Et]+=xt,this.computeTrackPositions()}shiftTrackPlus1kb(Et){this.shiftTrack(Et,1e3)}shiftTrackMinus1kb(Et){this.shiftTrack(Et,-1e3)}flipTrackToggle(Et){this.flipTrack(Et)}getTrackAnchor(Et){const xt=this.hoodToSeqidMap[Et];if(!xt)return 0;const vt=this.nucleotidesBySeqid[xt],bt=this.hoodRanges[Et];return bt?bt.length/2:vt&&vt.hood?(vt.hood.origEnd-vt.hood.origStart)/2:this.featuresBySeqid[xt]?(this.featuresBySeqid[xt].origMaxEnd-this.featuresBySeqid[xt].origMinStart)/2:0}alignCluster(Et){const xt=Et==null?null:String(Et).trim(),bt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100,At=Object.entries(this.genesById).filter(([Tt,Rt])=>this.proteinClusters&&this.proteinClusters[Tt]===xt).map(([Tt,Rt])=>Rt);if(At.length===0)return;const Ft={};for(const Tt of At)(Ft[Tt.hood_id]||=[]).push(Tt);const Ct=[];for(const Tt in Ft){const Rt=Ft[Tt];Rt.sort((Pt,Lt)=>Pt.originalGeneId.localeCompare(Lt.originalGeneId)),Ct.push(Rt[0])}if(!Ct.length)return;Ct.sort((Tt,Rt)=>Tt.hood_id.localeCompare(Rt.hood_id)),Ct[0];for(const Tt of Ct){const Rt=Tt.hood_id;(!!this.trackFlipped[Rt]?Tt.origStrand==="+"?"-":"+":Tt.origStrand)==="-"&&this.flipTrackStateWithCentering(Rt)}this.computeTrackPositions();const wt=0;for(const Tt of Ct){const Rt=Tt.hood_id,Pt=GenomeView.getGeneVisualX(Tt,this);if(Pt===null)continue;let Lt=(wt-Pt)/bt;this.trackFlipped[Rt]&&(Lt=-Lt);const Ot=this.trackOffset[Rt]||0;this.trackOffset[Rt]=Ot+Lt}const St=new Set(Ct.map(Tt=>Tt.hood_id));for(const Tt of this.leaves){if(St.has(Tt))continue;const Rt=this.hoodRanges[Tt],Pt=this.hoodToSeqidMap[Tt],Lt=this.nucleotidesBySeqid[Pt];if(!Rt&&!Lt?.hood)continue;const kt=Rt?Rt.length/2:(Lt.hood.origEnd-Lt.hood.origStart)/2,Mt=!!this.trackFlipped[Tt]?-1:1,It=(wt-kt)/(Mt*bt);this.trackOffset[Tt]=It}this.computeTrackPositions()}alignAllToStart(){const Et=this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100,xt=Et/100;for(const vt of this.leaves){this.trackFlipped[vt]=!1;const bt=this.hoodToSeqidMap[vt];if(!bt)continue;const At=this.nucleotidesBySeqid[bt];if(At?.hood){const wt=(this.hoodRanges[vt]?.length||At.hood.origEnd-At.hood.origStart||0)/2;this.trackOffset[vt]=wt*(1-1/xt)}}this.computeTrackPositions();try{if(this.config?.debug?.alignment){const bt=[],At=[];console.debug(`[GenomeView] alignAllToStart xScale=${Et}`);for(const Tt of this.leaves){const Rt=this.hoodToSeqidMap[Tt],Pt=Rt?this.nucleotidesBySeqid[Rt]:null,Lt=!!this.trackFlipped[Tt],kt=this.trackOffset[Tt]||0,Mt=this.hoodRanges[Tt]?.length||(Pt?.hood?Pt.hood.origEnd-Pt.hood.origStart:0)||0,It=Pt?.hood?.start,Nt=Pt?.hood?.end;typeof It=="number"&&isFinite(It)&&bt.push([Tt,It]),typeof Nt=="number"&&isFinite(Nt)&&At.push([Tt,Nt]),console.debug(`[start] hood=${Tt} flipped=${Lt} len=${Mt} offset=${kt} baseline=(${It??"n/a"}, ${Nt??"n/a"})`)}bt.sort((Tt,Rt)=>Tt[1]-Rt[1]),At.sort((Tt,Rt)=>Tt[1]-Rt[1]);const Ft=bt[0]?.[1],Ct=bt[0]?.[0],wt=At[At.length-1]?.[1],St=At[At.length-1]?.[0];console.debug(`[start] baselineMinStart=${Ft} (hood=${Ct}) baselineMaxEnd=${wt} (hood=${St})`),console.debug(`[start] global bounds: minX=${this.globalMin} maxX=${this.globalMax}`)}}catch{}}alignAllToEnd(){const xt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100;for(const vt of this.leaves){this.trackFlipped[vt]=!1;const bt=this.hoodToSeqidMap[vt];if(!bt)continue;const At=this.nucleotidesBySeqid[bt];if(At?.hood){const wt=(this.hoodRanges[vt]?.length||At.hood.origEnd-At.hood.origStart||0)/2;this.trackOffset[vt]=-wt*(1+1/xt)}}this.computeTrackPositions()}alignAllToCenter(){const Et=this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100,xt=Et/100;for(const vt of this.leaves){this.trackFlipped[vt]=!1;const bt=this.hoodToSeqidMap[vt];if(!bt)continue;const At=this.nucleotidesBySeqid[bt];if(At?.hood){const wt=(this.hoodRanges[vt]?.length||At.hood.origEnd-At.hood.origStart||0)/2;this.trackOffset[vt]=-wt/xt}}this.computeTrackPositions();try{if(this.config?.debug?.alignment){const bt=[],At=[];console.debug(`[GenomeView] alignAllToCenter xScale=${Et}`);for(const Tt of this.leaves){const Rt=this.hoodToSeqidMap[Tt],Pt=Rt?this.nucleotidesBySeqid[Rt]:null,Lt=!!this.trackFlipped[Tt],kt=this.trackOffset[Tt]||0,Mt=this.hoodRanges[Tt]?.length||(Pt?.hood?Pt.hood.origEnd-Pt.hood.origStart:0)||0,It=Pt?.hood?.start,Nt=Pt?.hood?.end;typeof It=="number"&&isFinite(It)&&bt.push([Tt,It]),typeof Nt=="number"&&isFinite(Nt)&&At.push([Tt,Nt]),console.debug(`[center] hood=${Tt} flipped=${Lt} len=${Mt} offset=${kt} baseline=(${It??"n/a"}, ${Nt??"n/a"})`)}bt.sort((Tt,Rt)=>Tt[1]-Rt[1]),At.sort((Tt,Rt)=>Tt[1]-Rt[1]);const Ft=bt[0]?.[1],Ct=bt[0]?.[0],wt=At[At.length-1]?.[1],St=At[At.length-1]?.[0];console.debug(`[center] baselineMinStart=${Ft} (hood=${Ct}) baselineMaxEnd=${wt} (hood=${St})`),console.debug(`[center] global bounds: minX=${this.globalMin} maxX=${this.globalMax}`)}}catch{}}applyHoods(Et){const xt=new Set(this.leaves.map(bt=>String(bt))),vt=[];for(const bt of Et){const At=bt.hood_id!=null?String(bt.hood_id).trim():null,Ft=bt.seqid!=null?String(bt.seqid).trim():null;let Ct=null;At&&xt.has(At)?Ct=At:Ft&&xt.has(Ft)&&(Ct=Ft),Ct&&(bt.hood_id=Ct,vt.push(bt))}for(const bt of vt)bt.hood_id&&bt.seqid&&(this.hoodToSeqidMap[bt.hood_id]=bt.seqid,(this.seqidToHoodsMap[bt.seqid]||=[]).push(bt.hood_id),this.hoodRanges[bt.hood_id]={seqid:bt.seqid,origStart:bt.start,origEnd:bt.end,start:bt.start,end:bt.end,length:bt.end-bt.start,align_gene:bt.align_gene}),this.nucleotidesBySeqid[bt.seqid]&&this.nucleotidesBySeqid[bt.seqid].setHood(bt.start,bt.end);this._buildHoodIntervalIndex()}getHoodIdsFromSeqid(Et){return this.seqidToHoodsMap[Et]||[Et]}getHoodIdFromSeqid(Et){return this.getHoodIdsFromSeqid(Et)[0]}getSeqidFromHoodId(Et){return this.hoodToSeqidMap[Et]||Et}alignByDefaultGenes(){const xt=(this.config.genome&&typeof this.config.genome.xScalePercent=="number"?this.config.genome.xScalePercent:100)/100,vt=[];for(const Ft of this.leaves){const Ct=this.hoodRanges[Ft];if(!Ct?.align_gene)continue;const wt=`${Ft}_${Ct.align_gene}`,St=this.genesById[wt];St&&vt.push(St)}if(!vt.length)return;vt.sort((Ft,Ct)=>Ft.hood_id.localeCompare(Ct.hood_id));const bt=0;for(const Ft of vt){const Ct=Ft.hood_id;(!!this.trackFlipped[Ct]?Ft.origStrand==="+"?"-":"+":Ft.origStrand)==="-"&&this.flipTrackStateWithCentering(Ct)}this.computeTrackPositions();for(const Ft of vt){const Ct=Ft.hood_id,wt=GenomeView.getGeneVisualX(Ft,this);if(wt===null)continue;const St=bt-wt,Rt=(!!this.trackFlipped[Ct]?-1:1)*(St/xt),Pt=this.trackOffset[Ct]||0;this.trackOffset[Ct]=Pt+Rt}const At=new Set(vt.map(Ft=>Ft.hood_id));for(const Ft of this.leaves){if(At.has(Ft))continue;const Ct=this.hoodToSeqidMap[Ft];if(!Ct)continue;const wt=this.nucleotidesBySeqid[Ct];if(wt?.hood){const St=this.hoodRanges[Ft],Tt=St?St.length/2:(wt.hood.origEnd-wt.hood.origStart)/2,Pt=!!this.trackFlipped[Ft]?-1:1,Lt=(bt-Tt)/(Pt*xt);this.trackOffset[Ft]=Lt}}this.computeTrackPositions()}applyDomainPalette(Et=null){if(this._cachedAllDomains=void 0,!Et||!Et.enabled){for(const Ft of Object.values(this.genesById))for(const Ct of Ft.domains)Ct&&Ct.fillColor&&(Ct.fillColor=null);this._paletteVersion++;return}const xt=new Set;for(const Ft of Object.values(this.genesById))for(const Ct of Ft.domains)xt.add(Ct.domainName);const vt=Array.from(xt).sort();let bt=[];if(Et.name)try{bt=memoGetPalette(Et.name,Math.max(vt.length,Et.numColors||vt.length),Et.reverse||!1)}catch{bt=[]}const At={};vt.forEach((Ft,Ct)=>{At[Ft]=bt[Ct%bt.length]});for(const Ft of Object.values(this.genesById))for(const Ct of Ft.domains)Ct.fillColor=At[Ct.domainName]||[128,128,128,255]}}function hslToRgb(yt,Et,xt){let vt,bt,At;{const Ft=(St,Tt,Rt)=>(Rt<0&&(Rt+=1),Rt>1&&(Rt-=1),Rt<.16666666666666666?St+(Tt-St)*6*Rt:Rt<.5?Tt:Rt<.6666666666666666?St+(Tt-St)*(.6666666666666666-Rt)*6:St),Ct=xt+Et-xt*Et,wt=2*xt-Ct;vt=Ft(wt,Ct,yt+1/3),bt=Ft(wt,Ct,yt),At=Ft(wt,Ct,yt-1/3)}return[Math.round(vt*255),Math.round(bt*255),Math.round(At*255)]}function isValidPolygon(yt){if(!Array.isArray(yt)||yt.length<3)return!1;const[Et,xt]=yt[0];return!yt.every(([vt,bt])=>vt===Et&&bt===xt)}function assert$7(yt,Et){if(!yt)throw new Error(Et||"loader assertion failed.")}const isBrowser$2=!!(typeof process!="object"||String(process)!=="[object process]"||process.browser),matches$1=typeof process<"u"&&process.version&&/v([0-9]*)/.exec(process.version);matches$1&&parseFloat(matches$1[1]);const window_=globalThis,process_=globalThis.process||{},navigator_=globalThis.navigator||{};function isElectron(yt){if(typeof window<"u"&&window.process?.type==="renderer"||typeof process<"u"&&process.versions?.electron)return!0;const xt=typeof navigator<"u"&&navigator.userAgent;return!!(xt&&xt.indexOf("Electron")>=0)}function isBrowser$1(){return!(typeof process=="object"&&String(process)==="[object process]"&&!process?.browser)||isElectron()}function getBrowser(yt){return isBrowser$1()?isElectron()?"Electron":(navigator_.userAgent||"").indexOf("Edge")>-1?"Edge":globalThis.chrome?"Chrome":globalThis.safari?"Safari":globalThis.mozInnerScreenX?"Firefox":"Unknown":"Node"}const VERSION$4="4.1.0";function getStorage(yt){try{const Et=window[yt],xt="__storage_test__";return Et.setItem(xt,xt),Et.removeItem(xt),Et}catch{return null}}class LocalStorage{constructor(Et,xt,vt="sessionStorage"){this.storage=getStorage(vt),this.id=Et,this.config=xt,this._loadConfiguration()}getConfiguration(){return this.config}setConfiguration(Et){if(Object.assign(this.config,Et),this.storage){const xt=JSON.stringify(this.config);this.storage.setItem(this.id,xt)}}_loadConfiguration(){let Et={};if(this.storage){const xt=this.storage.getItem(this.id);Et=xt?JSON.parse(xt):{}}return Object.assign(this.config,Et),this}}function formatTime(yt){let Et;return yt<10?Et=`${yt.toFixed(2)}ms`:yt<100?Et=`${yt.toFixed(1)}ms`:yt<1e3?Et=`${yt.toFixed(0)}ms`:Et=`${(yt/1e3).toFixed(2)}s`,Et}function leftPad(yt,Et=8){const xt=Math.max(Et-yt.length,0);return`${" ".repeat(xt)}${yt}`}var COLOR;(function(yt){yt[yt.BLACK=30]="BLACK",yt[yt.RED=31]="RED",yt[yt.GREEN=32]="GREEN",yt[yt.YELLOW=33]="YELLOW",yt[yt.BLUE=34]="BLUE",yt[yt.MAGENTA=35]="MAGENTA",yt[yt.CYAN=36]="CYAN",yt[yt.WHITE=37]="WHITE",yt[yt.BRIGHT_BLACK=90]="BRIGHT_BLACK",yt[yt.BRIGHT_RED=91]="BRIGHT_RED",yt[yt.BRIGHT_GREEN=92]="BRIGHT_GREEN",yt[yt.BRIGHT_YELLOW=93]="BRIGHT_YELLOW",yt[yt.BRIGHT_BLUE=94]="BRIGHT_BLUE",yt[yt.BRIGHT_MAGENTA=95]="BRIGHT_MAGENTA",yt[yt.BRIGHT_CYAN=96]="BRIGHT_CYAN",yt[yt.BRIGHT_WHITE=97]="BRIGHT_WHITE"})(COLOR||(COLOR={}));const BACKGROUND_INCREMENT=10;function getColor(yt){return typeof yt!="string"?yt:(yt=yt.toUpperCase(),COLOR[yt]||COLOR.WHITE)}function addColor(yt,Et,xt){return!isBrowser$1&&typeof yt=="string"&&(Et&&(yt=`\x1B[${getColor(Et)}m${yt}\x1B[39m`),xt&&(yt=`\x1B[${getColor(xt)+BACKGROUND_INCREMENT}m${yt}\x1B[49m`)),yt}function autobind(yt,Et=["constructor"]){const xt=Object.getPrototypeOf(yt),vt=Object.getOwnPropertyNames(xt),bt=yt;for(const At of vt){const Ft=bt[At];typeof Ft=="function"&&(Et.find(Ct=>At===Ct)||(bt[At]=Ft.bind(yt)))}}function assert$6(yt,Et){if(!yt)throw new Error("Assertion failed")}function getHiResTimestamp$1(){let yt;if(isBrowser$1()&&window_.performance)yt=window_?.performance?.now?.();else if("hrtime"in process_){const Et=process_?.hrtime?.();yt=Et[0]*1e3+Et[1]/1e6}else yt=Date.now();return yt}const originalConsole={debug:isBrowser$1()&&console.debug||console.log,log:console.log,info:console.info,warn:console.warn,error:console.error},DEFAULT_LOG_CONFIGURATION={enabled:!0,level:0};function noop$4(){}const cache$2={},ONCE={once:!0};class Log{constructor({id:Et}={id:""}){this.VERSION=VERSION$4,this._startTs=getHiResTimestamp$1(),this._deltaTs=getHiResTimestamp$1(),this.userData={},this.LOG_THROTTLE_TIMEOUT=0,this.id=Et,this.userData={},this._storage=new LocalStorage(`__probe-${this.id}__`,DEFAULT_LOG_CONFIGURATION),this.timeStamp(`${this.id} started`),autobind(this),Object.seal(this)}set level(Et){this.setLevel(Et)}get level(){return this.getLevel()}isEnabled(){return this._storage.config.enabled}getLevel(){return this._storage.config.level}getTotal(){return Number((getHiResTimestamp$1()-this._startTs).toPrecision(10))}getDelta(){return Number((getHiResTimestamp$1()-this._deltaTs).toPrecision(10))}set priority(Et){this.level=Et}get priority(){return this.level}getPriority(){return this.level}enable(Et=!0){return this._storage.setConfiguration({enabled:Et}),this}setLevel(Et){return this._storage.setConfiguration({level:Et}),this}get(Et){return this._storage.config[Et]}set(Et,xt){this._storage.setConfiguration({[Et]:xt})}settings(){console.table?console.table(this._storage.config):console.log(this._storage.config)}assert(Et,xt){if(!Et)throw new Error(xt||"Assertion failed")}warn(Et){return this._getLogFunction(0,Et,originalConsole.warn,arguments,ONCE)}error(Et){return this._getLogFunction(0,Et,originalConsole.error,arguments)}deprecated(Et,xt){return this.warn(`\`${Et}\` is deprecated and will be removed in a later version. Use \`${xt}\` instead`)}removed(Et,xt){return this.error(`\`${Et}\` has been removed. Use \`${xt}\` instead`)}probe(Et,xt){return this._getLogFunction(Et,xt,originalConsole.log,arguments,{time:!0,once:!0})}log(Et,xt){return this._getLogFunction(Et,xt,originalConsole.debug,arguments)}info(Et,xt){return this._getLogFunction(Et,xt,console.info,arguments)}once(Et,xt){return this._getLogFunction(Et,xt,originalConsole.debug||originalConsole.info,arguments,ONCE)}table(Et,xt,vt){return xt?this._getLogFunction(Et,xt,console.table||noop$4,vt&&[vt],{tag:getTableHeader(xt)}):noop$4}time(Et,xt){return this._getLogFunction(Et,xt,console.time?console.time:console.info)}timeEnd(Et,xt){return this._getLogFunction(Et,xt,console.timeEnd?console.timeEnd:console.info)}timeStamp(Et,xt){return this._getLogFunction(Et,xt,console.timeStamp||noop$4)}group(Et,xt,vt={collapsed:!1}){const bt=normalizeArguments({logLevel:Et,message:xt,opts:vt}),{collapsed:At}=vt;return bt.method=(At?console.groupCollapsed:console.group)||console.info,this._getLogFunction(bt)}groupCollapsed(Et,xt,vt={}){return this.group(Et,xt,Object.assign({},vt,{collapsed:!0}))}groupEnd(Et){return this._getLogFunction(Et,"",console.groupEnd||noop$4)}withGroup(Et,xt,vt){this.group(Et,xt)();try{vt()}finally{this.groupEnd(Et)()}}trace(){console.trace&&console.trace()}_shouldLog(Et){return this.isEnabled()&&this.getLevel()>=normalizeLogLevel(Et)}_getLogFunction(Et,xt,vt,bt,At){if(this._shouldLog(Et)){At=normalizeArguments({logLevel:Et,message:xt,args:bt,opts:At}),vt=vt||At.method,assert$6(vt),At.total=this.getTotal(),At.delta=this.getDelta(),this._deltaTs=getHiResTimestamp$1();const Ft=At.tag||At.message;if(At.once&&Ft)if(!cache$2[Ft])cache$2[Ft]=getHiResTimestamp$1();else return noop$4;return xt=decorateMessage(this.id,At.message,At),vt.bind(console,xt,...At.args)}return noop$4}}Log.VERSION=VERSION$4;function normalizeLogLevel(yt){if(!yt)return 0;let Et;switch(typeof yt){case"number":Et=yt;break;case"object":Et=yt.logLevel||yt.priority||0;break;default:return 0}return assert$6(Number.isFinite(Et)&&Et>=0),Et}function normalizeArguments(yt){const{logLevel:Et,message:xt}=yt;yt.logLevel=normalizeLogLevel(Et);const vt=yt.args?Array.from(yt.args):[];for(;vt.length&&vt.shift()!==xt;);switch(typeof Et){case"string":case"function":xt!==void 0&&vt.unshift(xt),yt.message=Et;break;case"object":Object.assign(yt,Et);break}typeof yt.message=="function"&&(yt.message=yt.message());const bt=typeof yt.message;return assert$6(bt==="string"||bt==="object"),Object.assign(yt,{args:vt},yt.opts)}function decorateMessage(yt,Et,xt){if(typeof Et=="string"){const vt=xt.time?leftPad(formatTime(xt.total)):"";Et=xt.time?`${yt}: ${vt} ${Et}`:`${yt}: ${Et}`,Et=addColor(Et,xt.color,xt.background)}return Et}function getTableHeader(yt){for(const Et in yt)for(const xt in yt[Et])return xt||"untitled";return"empty"}const VERSION$3="4.3.3",version=VERSION$3[0]>="0"&&VERSION$3[0]<="9"?`v${VERSION$3}`:"";function createLog(){const yt=new Log({id:"loaders.gl"});return globalThis.loaders=globalThis.loaders||{},globalThis.loaders.log=yt,globalThis.loaders.version=version,globalThis.probe=globalThis.probe||{},globalThis.probe.loaders=yt,yt}const log$1=createLog();function mergeLoaderOptions(yt,Et){return mergeOptionsRecursively(yt||{},Et)}function mergeOptionsRecursively(yt,Et,xt=0){if(xt>3)return Et;const vt={...yt};for(const[bt,At]of Object.entries(Et))At&&typeof At=="object"&&!Array.isArray(At)?vt[bt]=mergeOptionsRecursively(vt[bt]||{},Et[bt],xt+1):vt[bt]=Et[bt];return vt}const NPM_TAG="latest";function getVersion(){return globalThis._loadersgl_?.version||(globalThis._loadersgl_=globalThis._loadersgl_||{},globalThis._loadersgl_.version="4.3.3"),globalThis._loadersgl_.version}const VERSION$2=getVersion();function assert$5(yt,Et){if(!yt)throw new Error(Et||"loaders.gl assertion failed.")}const isBrowser=typeof process!="object"||String(process)!=="[object process]"||process.browser,isMobile=typeof window<"u"&&typeof window.orientation<"u",matches=typeof process<"u"&&process.version&&/v([0-9]*)/.exec(process.version);matches&&parseFloat(matches[1]);class WorkerJob{name;workerThread;isRunning=!0;result;_resolve=()=>{};_reject=()=>{};constructor(Et,xt){this.name=Et,this.workerThread=xt,this.result=new Promise((vt,bt)=>{this._resolve=vt,this._reject=bt})}postMessage(Et,xt){this.workerThread.postMessage({source:"loaders.gl",type:Et,payload:xt})}done(Et){assert$5(this.isRunning),this.isRunning=!1,this._resolve(Et)}error(Et){assert$5(this.isRunning),this.isRunning=!1,this._reject(Et)}}class NodeWorker{terminate(){}}const workerURLCache=new Map;function getLoadableWorkerURL(yt){assert$5(yt.source&&!yt.url||!yt.source&&yt.url);let Et=workerURLCache.get(yt.source||yt.url);return Et||(yt.url&&(Et=getLoadableWorkerURLFromURL(yt.url),workerURLCache.set(yt.url,Et)),yt.source&&(Et=getLoadableWorkerURLFromSource(yt.source),workerURLCache.set(yt.source,Et))),assert$5(Et),Et}function getLoadableWorkerURLFromURL(yt){if(!yt.startsWith("http"))return yt;const Et=buildScriptSource(yt);return getLoadableWorkerURLFromSource(Et)}function getLoadableWorkerURLFromSource(yt){const Et=new Blob([yt],{type:"application/javascript"});return URL.createObjectURL(Et)}function buildScriptSource(yt){return`try {
|
|
80
80
|
importScripts('${yt}');
|
|
81
81
|
} catch (error) {
|
|
82
82
|
console.error(error);
|