@qfo/qfchart 0.5.5 → 0.5.7

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/index.d.ts CHANGED
@@ -26,13 +26,20 @@ interface IndicatorPoint {
26
26
  offset?: number;
27
27
  };
28
28
  }
29
- type IndicatorStyle = 'line' | 'step' | 'columns' | 'histogram' | 'circles' | 'cross' | 'background';
29
+ type IndicatorStyle = 'line' | 'step' | 'columns' | 'histogram' | 'circles' | 'cross' | 'background' | 'shape';
30
30
  interface IndicatorOptions {
31
31
  style: IndicatorStyle;
32
32
  color: string;
33
33
  offset?: number;
34
34
  linewidth?: number;
35
35
  smooth?: boolean;
36
+ shape?: string;
37
+ size?: string;
38
+ text?: string;
39
+ textcolor?: string;
40
+ location?: string;
41
+ width?: number;
42
+ height?: number;
36
43
  }
37
44
  interface IndicatorPlot {
38
45
  data: IndicatorPoint[];
@@ -14,24 +14,24 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- (function(H,J){typeof exports=="object"&&typeof module<"u"?J(exports,require("echarts")):typeof define=="function"&&define.amd?define(["exports","echarts"],J):(H=typeof globalThis<"u"?globalThis:H||self,J(H.QFChart={},H.echarts))})(this,function(H,J){"use strict";function gt(a){var e=Object.create(null);return a&&Object.keys(a).forEach(function(t){if(t!=="default"){var i=Object.getOwnPropertyDescriptor(a,t);Object.defineProperty(e,t,i.get?i:{enumerable:!0,get:function(){return a[t]}})}}),e.default=a,Object.freeze(e)}var D=gt(J),ft=Object.defineProperty,yt=(a,e,t)=>e in a?ft(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,q=(a,e,t)=>(yt(a,typeof e!="symbol"?e+"":e,t),t);class xt{constructor(e,t,i,s={}){q(this,"id"),q(this,"plots"),q(this,"paneIndex"),q(this,"height"),q(this,"collapsed"),q(this,"titleColor"),q(this,"controls"),this.id=e,this.plots=t,this.paneIndex=i,this.height=s.height,this.collapsed=s.collapsed||!1,this.titleColor=s.titleColor,this.controls=s.controls}toggleCollapse(){this.collapsed=!this.collapsed}isVisible(){return!this.collapsed}updateData(e){Object.keys(e).forEach(t=>{if(!this.plots[t])this.plots[t]=e[t];else{const i=this.plots[t],s=e[t];s.options&&(i.options={...i.options,...s.options});const n=new Map;i.data.forEach(o=>{n.set(o.time,o)}),s.data.forEach(o=>{n.set(o.time,o)}),i.data=Array.from(n.values()).sort((o,h)=>o.time-h.time)}})}}class pt{static calculate(e,t,i,s=!1,n=null){let o=0;e>0&&(o=1/e*100);const h=Array.from(t.values()).map(m=>m.paneIndex).filter(m=>m>0).sort((m,P)=>m-P).filter((m,P,T)=>T.indexOf(m)===P),p=h.length>0,d=i.dataZoom?.visible??!0,b=i.dataZoom?.position??"top",u=i.dataZoom?.height??6,l=i.dataZoom?.start??0,v=i.dataZoom?.end??100;let g=8,S=92,k=-1;if(n)if(n==="main")k=0;else{const m=t.get(n);m&&(k=m.paneIndex)}if(k!==-1){const m=[],P=[],T=[],j=[],F=i.dataZoom?.start??50,w=i.dataZoom?.end??100;j.push({type:"inside",xAxisIndex:"all",start:F,end:w});const E=p?Math.max(...h):0,R=[];for(let N=0;N<=E;N++){const L=N===k;if(m.push({left:"10%",right:"10%",top:L?"5%":"0%",height:L?"90%":"0%",show:L,containLabel:!1}),P.push({type:"category",gridIndex:N,data:[],show:L,axisLabel:{show:L,color:"#94a3b8",fontFamily:i.fontFamily},axisLine:{show:L,lineStyle:{color:"#334155"}},splitLine:{show:L,lineStyle:{color:"#334155",opacity:.5}}}),T.push({position:"right",gridIndex:N,show:L,scale:!0,axisLabel:{show:L,color:"#94a3b8",fontFamily:i.fontFamily},splitLine:{show:L,lineStyle:{color:"#334155",opacity:.5}}}),N>0){const O=Array.from(t.values()).find(B=>B.paneIndex===N);O&&R.push({index:N,height:L?90:0,top:L?5:0,isCollapsed:!1,indicatorId:O.id,titleColor:O.titleColor,controls:O.controls})}}return{grid:m,xAxis:P,yAxis:T,dataZoom:j,paneLayout:R,mainPaneHeight:k===0?90:0,mainPaneTop:k===0?5:0,pixelToPercent:o}}d?b==="top"?(g=u+4,S=95):(S=100-u-2,g=8):(g=5,S=95);let f=5;e>0&&(f=20/e*100);let r=75,c=[];if(p){const m=h.map(w=>{const E=Array.from(t.values()).find(R=>R.paneIndex===w);return{index:w,requestedHeight:E?.height,isCollapsed:E?.collapsed??!1,indicatorId:E?.id,titleColor:E?.titleColor,controls:E?.controls}}).map(w=>({...w,height:w.isCollapsed?3:w.requestedHeight!==void 0?w.requestedHeight:15})),P=m.reduce((w,E)=>w+E.height,0),T=m.length*f,j=P+T;r=S-g-j,s?r=3:r<20&&(r=Math.max(r,10));let F=g+r+f;c=m.map(w=>{const E={index:w.index,height:w.height,top:F,isCollapsed:w.isCollapsed,indicatorId:w.indicatorId,titleColor:w.titleColor,controls:w.controls};return F+=w.height+f,E})}else r=S-g,s&&(r=3);const y=[];y.push({left:"10%",right:"10%",top:g+"%",height:r+"%",containLabel:!1}),c.forEach(m=>{y.push({left:"10%",right:"10%",top:m.top+"%",height:m.height+"%",containLabel:!1})});const I=[0,...c.map((m,P)=>P+1)],x=[],M=c.length===0;x.push({type:"category",data:[],gridIndex:0,scale:!0,axisLine:{onZero:!1,show:!s,lineStyle:{color:"#334155"}},splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"},axisTick:{show:!s},axisPointer:{label:{show:M,fontSize:11,backgroundColor:"#475569"}}}),c.forEach((m,P)=>{const T=P===c.length-1;x.push({type:"category",gridIndex:P+1,data:[],axisLabel:{show:!1},axisLine:{show:!m.isCollapsed,lineStyle:{color:"#334155"}},axisTick:{show:!1},splitLine:{show:!1},axisPointer:{label:{show:T,fontSize:11,backgroundColor:"#475569"}}})});const $=[];$.push({position:"right",scale:!0,gridIndex:0,splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLine:{show:!s,lineStyle:{color:"#334155"}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"}}),c.forEach((m,P)=>{$.push({position:"right",scale:!0,gridIndex:P+1,splitLine:{show:!m.isCollapsed,lineStyle:{color:"#334155",opacity:.3}},axisLabel:{show:!m.isCollapsed,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",fontSize:10},axisLine:{show:!m.isCollapsed,lineStyle:{color:"#334155"}}})});const Z=[];return d&&(Z.push({type:"inside",xAxisIndex:I,start:l,end:v}),b==="top"?Z.push({type:"slider",xAxisIndex:I,top:"1%",height:u+"%",start:l,end:v,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1}):Z.push({type:"slider",xAxisIndex:I,bottom:"1%",height:u+"%",start:l,end:v,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1})),{grid:y,xAxis:x,yAxis:$,dataZoom:Z,paneLayout:c,mainPaneHeight:r,mainPaneTop:g,pixelToPercent:o}}static calculateMaximized(e,t,i){return{grid:[],xAxis:[],yAxis:[],dataZoom:[],paneLayout:[],mainPaneHeight:0,mainPaneTop:0,pixelToPercent:0}}}const st=new Map;function mt(a,e="#00da3c",t="64px"){if(typeof document>"u")return"";const i=`${a}-${e}-${t}`;if(st.has(i))return st.get(i);const s=document.createElement("canvas"),n=s.getContext("2d");if(s.width=32,s.height=32,n){n.font="bold "+t+" Arial",n.fillStyle=e,n.textAlign="center",n.textBaseline="middle",n.fillText(a,16,16);const o=s.toDataURL("image/png");return st.set(i,o),o}return""}class nt{static buildCandlestickSeries(e,t,i){const s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=e.map(h=>[h.open,h.close,h.low,h.high]);if(i&&i>o.length){const h=i-o.length;for(let p=0;p<h;p++)o.push(null)}return{type:"candlestick",name:t.title||"Market",data:o,itemStyle:{color:s,color0:n,borderColor:s,borderColor0:n},xAxisIndex:0,yAxisIndex:0,z:5}}static buildIndicatorSeries(e,t,i,s,n=0){const o=[];return e.forEach((h,p)=>{if(h.collapsed)return;let d=0,b=0;if(h.paneIndex>0){const u=i.findIndex(l=>l.index===h.paneIndex);u!==-1&&(d=u+1,b=u+1)}Object.keys(h.plots).forEach(u=>{const l=h.plots[u],v=`${p}::${u}`,g=new Array(s).fill(null),S=new Array(s).fill(null);switch(l.data.forEach(k=>{const f=t.get(k.time);if(f!==void 0){const r=k.options?.offset??l.options.offset??0,c=f+n+r;if(c>=0&&c<s){let y=k.value;const I=k.options?.color;(I===null||I==="na"||I==="NaN"||typeof I=="number"&&isNaN(I))&&(y=null),g[c]=y,S[c]=I||l.options.color}}}),l.options.style){case"histogram":case"columns":o.push({name:v,type:"bar",xAxisIndex:d,yAxisIndex:b,data:g.map((f,r)=>({value:f,itemStyle:S[r]?{color:S[r]}:void 0})),itemStyle:{color:l.options.color}});break;case"circles":case"cross":const k=g.map((f,r)=>{if(f===null)return null;const c=S[r]||l.options.color,y={value:[r,f],itemStyle:{color:c}};return l.options.style==="cross"?(y.symbol=`image://${mt("+",c,"24px")}`,y.symbolSize=16):(y.symbol="circle",y.symbolSize=6),y}).filter(f=>f!==null);o.push({name:v,type:"scatter",xAxisIndex:d,yAxisIndex:b,data:k});break;case"background":o.push({name:v,type:"custom",xAxisIndex:d,yAxisIndex:b,z:-10,renderItem:(f,r)=>{const c=r.value(0);if(isNaN(c))return;const y=r.coord([c,0]),I=r.size([1,0])[0],x=f.coordSys,M=y[0]-I/2,$=S[f.dataIndex],Z=r.value(1);if(!(!$||!Z))return{type:"rect",shape:{x:M,y:x.y,width:I,height:x.height},style:{fill:$,opacity:.3},silent:!0}},data:g.map((f,r)=>[r,f])});break;case"step":o.push({name:v,type:"custom",xAxisIndex:d,yAxisIndex:b,renderItem:(f,r)=>{const c=r.value(0),y=r.value(1);if(isNaN(y)||y===null)return;const I=r.coord([c,y]),x=r.size([1,0])[0];return{type:"line",shape:{x1:I[0]-x/2,y1:I[1],x2:I[0]+x/2,y2:I[1]},style:{stroke:S[f.dataIndex]||l.options.color,lineWidth:l.options.linewidth||1},silent:!0}},data:g.map((f,r)=>[r,f])});break;case"line":default:o.push({name:v,type:"custom",xAxisIndex:d,yAxisIndex:b,renderItem:(f,r)=>{const c=f.dataIndex;if(c===0)return;const y=r.value(1),I=r.value(2);if(y===null||isNaN(y)||I===null||isNaN(I))return;const x=r.coord([c-1,I]),M=r.coord([c,y]);return{type:"line",shape:{x1:x[0],y1:x[1],x2:M[0],y2:M[1]},style:{stroke:S[c]||l.options.color,lineWidth:l.options.linewidth||1},silent:!0}},data:g.map((f,r)=>[r,f,r>0?g[r-1]:null])});break}})}),o}}class bt{static build(e,t,i,s=!1,n=null){const o=[],h=e.pixelToPercent,p=e.mainPaneTop;if(!n||n==="main"){const d=10*h;if(o.push({type:"text",left:"8.5%",top:p+d+"%",z:10,style:{text:t.title||"Market",fill:t.titleColor||"#fff",font:`bold 16px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}}),t.watermark!==!1){const u=e.mainPaneTop+e.mainPaneHeight;o.push({type:"text",right:"11%",top:u-3+"%",z:10,style:{text:"QFChart",fill:t.fontColor||"#cbd5e1",font:"bold 16px sans-serif",opacity:.1},cursor:"pointer",onclick:()=>{window.open("https://quantforge.org","_blank")}})}const b=[];if(t.controls?.collapse&&b.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","collapse")},{type:"text",style:{text:s?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),t.controls?.maximize){const u=n==="main",l=t.controls?.collapse?25:0;b.push({type:"group",x:l,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","maximize")},{type:"text",style:{text:u?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}if(t.controls?.fullscreen){let u=0;t.controls?.collapse&&(u+=25),t.controls?.maximize&&(u+=25),b.push({type:"group",x:u,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","fullscreen")},{type:"text",style:{text:"\u26F6",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}b.length>0&&o.push({type:"group",right:"10.5%",top:p+"%",children:b})}return e.paneLayout.forEach(d=>{if(n&&d.indicatorId!==n)return;o.push({type:"text",left:"8.5%",top:d.top+10*h+"%",z:10,style:{text:d.indicatorId||"",fill:d.titleColor||"#fff",font:`bold 12px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}});const b=[];if(d.controls?.collapse&&b.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>d.indicatorId&&i(d.indicatorId,"collapse")},{type:"text",style:{text:d.isCollapsed?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),d.controls?.maximize){const u=n===d.indicatorId,l=d.controls?.collapse?25:0;b.push({type:"group",x:l,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>d.indicatorId&&i(d.indicatorId,"maximize")},{type:"text",style:{text:u?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}b.length>0&&o.push({type:"group",right:"10.5%",top:d.top+"%",children:b})}),o}}class vt{static format(e,t){if(!e||e.length===0)return"";const i=t.title||"Market",s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=t.fontFamily||"sans-serif",h=e[0].axisValue;let p=`<div style="font-weight: bold; margin-bottom: 5px; color: #cbd5e1; font-family: ${o};">${h}</div>`;const d=e.find(u=>u.seriesType==="candlestick"),b=e.filter(u=>u.seriesType!=="candlestick");if(d){const[u,l,v,g,S]=d.value,k=v>=l?s:n;p+=`
17
+ (function(B,_){typeof exports=="object"&&typeof module<"u"?_(exports,require("echarts")):typeof define=="function"&&define.amd?define(["exports","echarts"],_):(B=typeof globalThis<"u"?globalThis:B||self,_(B.QFChart={},B.echarts))})(this,function(B,_){"use strict";function ft(a){var e=Object.create(null);return a&&Object.keys(a).forEach(function(t){if(t!=="default"){var i=Object.getOwnPropertyDescriptor(a,t);Object.defineProperty(e,t,i.get?i:{enumerable:!0,get:function(){return a[t]}})}}),e.default=a,Object.freeze(e)}var E=ft(_),yt=Object.defineProperty,xt=(a,e,t)=>e in a?yt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,U=(a,e,t)=>(xt(a,typeof e!="symbol"?e+"":e,t),t);class mt{constructor(e,t,i,s={}){U(this,"id"),U(this,"plots"),U(this,"paneIndex"),U(this,"height"),U(this,"collapsed"),U(this,"titleColor"),U(this,"controls"),this.id=e,this.plots=t,this.paneIndex=i,this.height=s.height,this.collapsed=s.collapsed||!1,this.titleColor=s.titleColor,this.controls=s.controls}toggleCollapse(){this.collapsed=!this.collapsed}isVisible(){return!this.collapsed}updateData(e){Object.keys(e).forEach(t=>{if(!this.plots[t])this.plots[t]=e[t];else{const i=this.plots[t],s=e[t];s.options&&(i.options={...i.options,...s.options});const n=new Map;i.data.forEach(o=>{n.set(o.time,o)}),s.data.forEach(o=>{n.set(o.time,o)}),i.data=Array.from(n.values()).sort((o,r)=>o.time-r.time)}})}}class ut{static calculate(e,t,i,s=!1,n=null){let o=0;e>0&&(o=1/e*100);const r=Array.from(t.values()).map(g=>g.paneIndex).filter(g=>g>0).sort((g,w)=>g-w).filter((g,w,z)=>z.indexOf(g)===w),p=r.length>0,u=i.dataZoom?.visible??!0,v=i.dataZoom?.position??"top",f=i.dataZoom?.height??6,m=i.dataZoom?.start??0,d=i.dataZoom?.end??100;let x=8,S=92,I=-1;if(n)if(n==="main")I=0;else{const g=t.get(n);g&&(I=g.paneIndex)}if(I!==-1){const g=[],w=[],z=[],O=[],W=i.dataZoom?.start??50,P=i.dataZoom?.end??100;O.push({type:"inside",xAxisIndex:"all",start:W,end:P});const M=p?Math.max(...r):0,Z=[];for(let N=0;N<=M;N++){const A=N===I;if(g.push({left:"10%",right:"10%",top:A?"5%":"0%",height:A?"90%":"0%",show:A,containLabel:!1}),w.push({type:"category",gridIndex:N,data:[],show:A,axisLabel:{show:A,color:"#94a3b8",fontFamily:i.fontFamily},axisLine:{show:A,lineStyle:{color:"#334155"}},splitLine:{show:A,lineStyle:{color:"#334155",opacity:.5}}}),z.push({position:"right",gridIndex:N,show:A,scale:!0,axisLabel:{show:A,color:"#94a3b8",fontFamily:i.fontFamily},splitLine:{show:A,lineStyle:{color:"#334155",opacity:.5}}}),N>0){const j=Array.from(t.values()).find(H=>H.paneIndex===N);j&&Z.push({index:N,height:A?90:0,top:A?5:0,isCollapsed:!1,indicatorId:j.id,titleColor:j.titleColor,controls:j.controls})}}return{grid:g,xAxis:w,yAxis:z,dataZoom:O,paneLayout:Z,mainPaneHeight:I===0?90:0,mainPaneTop:I===0?5:0,pixelToPercent:o}}u?v==="top"?(x=f+4,S=95):(S=100-f-2,x=8):(x=5,S=95);let L=5;e>0&&(L=20/e*100);let D=75,y=[];if(p){const g=r.map(P=>{const M=Array.from(t.values()).find(Z=>Z.paneIndex===P);return{index:P,requestedHeight:M?.height,isCollapsed:M?.collapsed??!1,indicatorId:M?.id,titleColor:M?.titleColor,controls:M?.controls}}).map(P=>({...P,height:P.isCollapsed?3:P.requestedHeight!==void 0?P.requestedHeight:15})),w=g.reduce((P,M)=>P+M.height,0),z=g.length*L,O=w+z;D=S-x-O,s?D=3:D<20&&(D=Math.max(D,10));let W=x+D+L;y=g.map(P=>{const M={index:P.index,height:P.height,top:W,isCollapsed:P.isCollapsed,indicatorId:P.indicatorId,titleColor:P.titleColor,controls:P.controls};return W+=P.height+L,M})}else D=S-x,s&&(D=3);const c=[];c.push({left:"10%",right:"10%",top:x+"%",height:D+"%",containLabel:!1}),y.forEach(g=>{c.push({left:"10%",right:"10%",top:g.top+"%",height:g.height+"%",containLabel:!1})});const l=[0,...y.map((g,w)=>w+1)],b=[],h=y.length===0;b.push({type:"category",data:[],gridIndex:0,scale:!0,axisLine:{onZero:!1,show:!s,lineStyle:{color:"#334155"}},splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"},axisTick:{show:!s},axisPointer:{label:{show:h,fontSize:11,backgroundColor:"#475569"}}}),y.forEach((g,w)=>{const z=w===y.length-1;b.push({type:"category",gridIndex:w+1,data:[],axisLabel:{show:!1},axisLine:{show:!g.isCollapsed,lineStyle:{color:"#334155"}},axisTick:{show:!1},splitLine:{show:!1},axisPointer:{label:{show:z,fontSize:11,backgroundColor:"#475569"}}})});const C=[];C.push({position:"right",scale:!0,gridIndex:0,splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLine:{show:!s,lineStyle:{color:"#334155"}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"}}),y.forEach((g,w)=>{C.push({position:"right",scale:!0,gridIndex:w+1,splitLine:{show:!g.isCollapsed,lineStyle:{color:"#334155",opacity:.3}},axisLabel:{show:!g.isCollapsed,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",fontSize:10},axisLine:{show:!g.isCollapsed,lineStyle:{color:"#334155"}}})});const T=[];return u&&(T.push({type:"inside",xAxisIndex:l,start:m,end:d}),v==="top"?T.push({type:"slider",xAxisIndex:l,top:"1%",height:f+"%",start:m,end:d,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1}):T.push({type:"slider",xAxisIndex:l,bottom:"1%",height:f+"%",start:m,end:d,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1})),{grid:c,xAxis:b,yAxis:C,dataZoom:T,paneLayout:y,mainPaneHeight:D,mainPaneTop:x,pixelToPercent:o}}static calculateMaximized(e,t,i){return{grid:[],xAxis:[],yAxis:[],dataZoom:[],paneLayout:[],mainPaneHeight:0,mainPaneTop:0,pixelToPercent:0}}}const ot=new Map;function bt(a,e="#00da3c",t="64px"){if(typeof document>"u")return"";const i=`${a}-${e}-${t}`;if(ot.has(i))return ot.get(i);const s=document.createElement("canvas"),n=s.getContext("2d");if(s.width=32,s.height=32,n){n.font="bold "+t+" Arial",n.fillStyle=e,n.textAlign="center",n.textBaseline="middle",n.fillText(a,16,16);const o=s.toDataURL("image/png");return ot.set(i,o),o}return""}class q{static buildCandlestickSeries(e,t,i){const s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=e.map(r=>[r.open,r.close,r.low,r.high]);if(i&&i>o.length){const r=i-o.length;for(let p=0;p<r;p++)o.push(null)}return{type:"candlestick",name:t.title||"Market",data:o,itemStyle:{color:s,color0:n,borderColor:s,borderColor0:n},xAxisIndex:0,yAxisIndex:0,z:5}}static getShapeSymbol(e){switch(e){case"arrowdown":return"path://M12 24l-12-12h8v-12h8v12h8z";case"arrowup":return"path://M12 0l12 12h-8v12h-8v-12h-8z";case"circle":return"circle";case"cross":return"path://M11 2h2v9h9v2h-9v9h-2v-9h-9v-2h9z";case"diamond":return"diamond";case"flag":return"path://M6 2v20h2v-8h12l-2-6 2-6h-12z";case"labeldown":return"path://M4 2h16a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-6l-2 4l-2 -4h-6a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2z";case"labelup":return"path://M12 2l2 4h6a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-16a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h6z";case"square":return"rect";case"triangledown":return"path://M12 21l-10-18h20z";case"triangleup":return"triangle";case"xcross":return"path://M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z";default:return"circle"}}static getShapeRotation(e){return 0}static getShapeSize(e,t,i){if(t!==void 0&&i!==void 0)return[t,i];let s;switch(e){case"tiny":s=8;break;case"small":s=12;break;case"normal":case"auto":s=16;break;case"large":s=24;break;case"huge":s=32;break;default:s=16}return t!==void 0?[t,t]:i!==void 0?[i,i]:s}static getLabelConfig(e,t){switch(t){case"abovebar":return{position:"top",distance:5};case"belowbar":return{position:"bottom",distance:5};case"top":return{position:"bottom",distance:5};case"bottom":return{position:"top",distance:5};case"absolute":default:return e==="labelup"||e==="labeldown"?{position:"inside",distance:0}:{position:"top",distance:5}}}static buildIndicatorSeries(e,t,i,s,n=0,o){const r=[];return e.forEach((p,u)=>{if(p.collapsed)return;let v=0,f=0;if(p.paneIndex>0){const m=i.findIndex(d=>d.index===p.paneIndex);m!==-1&&(v=m+1,f=m+1)}Object.keys(p.plots).forEach(m=>{const d=p.plots[m],x=`${u}::${m}`,S=new Array(s).fill(null),I=new Array(s).fill(null),L=new Array(s).fill(null);switch(d.data.forEach(D=>{const y=t.get(D.time);if(y!==void 0){const c=D.options?.offset??d.options.offset??0,l=y+n+c;if(l>=0&&l<s){let b=D.value;const h=D.options?.color;(h===null||h==="na"||h==="NaN"||typeof h=="number"&&isNaN(h))&&(b=null),S[l]=b,I[l]=h||d.options.color,L[l]=D.options||{}}}}),d.options.style){case"histogram":case"columns":r.push({name:x,type:"bar",xAxisIndex:v,yAxisIndex:f,data:S.map((c,l)=>({value:c,itemStyle:I[l]?{color:I[l]}:void 0})),itemStyle:{color:d.options.color}});break;case"circles":case"cross":const D=S.map((c,l)=>{if(c===null)return null;const b=I[l]||d.options.color,h={value:[l,c],itemStyle:{color:b}};return d.options.style==="cross"?(h.symbol=`image://${bt("+",b,"24px")}`,h.symbolSize=16):(h.symbol="circle",h.symbolSize=6),h}).filter(c=>c!==null);r.push({name:x,type:"scatter",xAxisIndex:v,yAxisIndex:f,data:D});break;case"shape":const y=S.map((c,l)=>{const b=L[l]||{},h=d.options,C=b.location||h.location||"absolute";if(C!=="absolute"&&!c||c==null)return null;const T=b.color||h.color||"blue",g=b.shape||h.shape||"circle",w=b.size||h.size||"normal",z=b.text||h.text,O=b.textcolor||h.textcolor||"white",W=b.width||h.width,P=b.height||h.height;let M=c,Z=[0,0];C==="abovebar"?(o&&o[l]&&(M=o[l].high),Z=[0,"-150%"]):C==="belowbar"?(o&&o[l]&&(M=o[l].low),Z=[0,"150%"]):C==="top"?(M=c,Z=[0,0]):C==="bottom"&&(M=c,Z=[0,0]);const N=q.getShapeSymbol(g),A=q.getShapeSize(w,W,P),j=q.getShapeRotation(g);let H=A;g.includes("label")&&(Array.isArray(A)?H=[A[0]*2.5,A[1]*2.5]:H=A*2.5);const R=q.getLabelConfig(g,C);return{value:[l,M],symbol:N,symbolSize:H,symbolRotate:j,symbolOffset:Z,itemStyle:{color:T},label:{show:!!z,position:R.position,distance:R.distance,formatter:z,color:O,fontSize:10,fontWeight:"bold"}}}).filter(c=>c!==null);r.push({name:x,type:"scatter",xAxisIndex:v,yAxisIndex:f,data:y});break;case"background":r.push({name:x,type:"custom",xAxisIndex:v,yAxisIndex:f,z:-10,renderItem:(c,l)=>{const b=l.value(0);if(isNaN(b))return;const h=l.coord([b,0]),C=l.size([1,0])[0],T=c.coordSys,g=h[0]-C/2,w=I[c.dataIndex],z=l.value(1);if(!(!w||!z))return{type:"rect",shape:{x:g,y:T.y,width:C,height:T.height},style:{fill:w,opacity:.3},silent:!0}},data:S.map((c,l)=>[l,c])});break;case"step":r.push({name:x,type:"custom",xAxisIndex:v,yAxisIndex:f,renderItem:(c,l)=>{const b=l.value(0),h=l.value(1);if(isNaN(h)||h===null)return;const C=l.coord([b,h]),T=l.size([1,0])[0];return{type:"line",shape:{x1:C[0]-T/2,y1:C[1],x2:C[0]+T/2,y2:C[1]},style:{stroke:I[c.dataIndex]||d.options.color,lineWidth:d.options.linewidth||1},silent:!0}},data:S.map((c,l)=>[l,c])});break;case"line":default:r.push({name:x,type:"custom",xAxisIndex:v,yAxisIndex:f,renderItem:(c,l)=>{const b=c.dataIndex;if(b===0)return;const h=l.value(1),C=l.value(2);if(h===null||isNaN(h)||C===null||isNaN(C))return;const T=l.coord([b-1,C]),g=l.coord([b,h]);return{type:"line",shape:{x1:T[0],y1:T[1],x2:g[0],y2:g[1]},style:{stroke:I[b]||d.options.color,lineWidth:d.options.linewidth||1},silent:!0}},data:S.map((c,l)=>[l,c,l>0?S[l-1]:null])});break}})}),r}}class vt{static build(e,t,i,s=!1,n=null){const o=[],r=e.pixelToPercent,p=e.mainPaneTop;if(!n||n==="main"){const u=10*r;if(o.push({type:"text",left:"8.5%",top:p+u+"%",z:10,style:{text:t.title||"Market",fill:t.titleColor||"#fff",font:`bold 16px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}}),t.watermark!==!1){const f=e.mainPaneTop+e.mainPaneHeight;o.push({type:"text",right:"11%",top:f-3+"%",z:10,style:{text:"QFChart",fill:t.fontColor||"#cbd5e1",font:"bold 16px sans-serif",opacity:.1},cursor:"pointer",onclick:()=>{window.open("https://quantforge.org","_blank")}})}const v=[];if(t.controls?.collapse&&v.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","collapse")},{type:"text",style:{text:s?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),t.controls?.maximize){const f=n==="main",m=t.controls?.collapse?25:0;v.push({type:"group",x:m,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","maximize")},{type:"text",style:{text:f?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}if(t.controls?.fullscreen){let f=0;t.controls?.collapse&&(f+=25),t.controls?.maximize&&(f+=25),v.push({type:"group",x:f,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","fullscreen")},{type:"text",style:{text:"\u26F6",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}v.length>0&&o.push({type:"group",right:"10.5%",top:p+"%",children:v})}return e.paneLayout.forEach(u=>{if(n&&u.indicatorId!==n)return;o.push({type:"text",left:"8.5%",top:u.top+10*r+"%",z:10,style:{text:u.indicatorId||"",fill:u.titleColor||"#fff",font:`bold 12px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}});const v=[];if(u.controls?.collapse&&v.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>u.indicatorId&&i(u.indicatorId,"collapse")},{type:"text",style:{text:u.isCollapsed?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),u.controls?.maximize){const f=n===u.indicatorId,m=u.controls?.collapse?25:0;v.push({type:"group",x:m,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>u.indicatorId&&i(u.indicatorId,"maximize")},{type:"text",style:{text:f?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}v.length>0&&o.push({type:"group",right:"10.5%",top:u.top+"%",children:v})}),o}}class wt{static format(e,t){if(!e||e.length===0)return"";const i=t.title||"Market",s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=t.fontFamily||"sans-serif",r=e[0].axisValue;let p=`<div style="font-weight: bold; margin-bottom: 5px; color: #cbd5e1; font-family: ${o};">${r}</div>`;const u=e.find(f=>f.seriesType==="candlestick"),v=e.filter(f=>f.seriesType!=="candlestick");if(u){const[f,m,d,x,S]=u.value,I=d>=m?s:n;p+=`
18
18
  <div style="margin-bottom: 8px; font-family: ${o};">
19
- <div style="display:flex; justify-content:space-between; color:${k}; font-weight:bold;">
19
+ <div style="display:flex; justify-content:space-between; color:${I}; font-weight:bold;">
20
20
  <span>${i}</span>
21
21
  </div>
22
22
  <div style="display: grid; grid-template-columns: auto auto; gap: 2px 15px; font-size: 0.9em; color: #cbd5e1;">
23
- <span>Open:</span> <span style="text-align: right; color: ${v>=l?s:n}">${l}</span>
23
+ <span>Open:</span> <span style="text-align: right; color: ${d>=m?s:n}">${m}</span>
24
24
  <span>High:</span> <span style="text-align: right; color: ${s}">${S}</span>
25
- <span>Low:</span> <span style="text-align: right; color: ${n}">${g}</span>
26
- <span>Close:</span> <span style="text-align: right; color: ${v>=l?s:n}">${v}</span>
25
+ <span>Low:</span> <span style="text-align: right; color: ${n}">${x}</span>
26
+ <span>Close:</span> <span style="text-align: right; color: ${d>=m?s:n}">${d}</span>
27
27
  </div>
28
28
  </div>
29
- `}if(b.length>0){p+='<div style="border-top: 1px solid #334155; margin: 5px 0; padding-top: 5px;"></div>';const u={};b.forEach(l=>{const v=l.seriesName.split("::"),g=v.length>1?v[0]:"Unknown",S=v.length>1?v[1]:l.seriesName;u[g]||(u[g]=[]),u[g].push({...l,displayName:S})}),Object.keys(u).forEach(l=>{p+=`
29
+ `}if(v.length>0){p+='<div style="border-top: 1px solid #334155; margin: 5px 0; padding-top: 5px;"></div>';const f={};v.forEach(m=>{const d=m.seriesName.split("::"),x=d.length>1?d[0]:"Unknown",S=d.length>1?d[1]:m.seriesName;f[x]||(f[x]=[]),f[x].push({...m,displayName:S})}),Object.keys(f).forEach(m=>{p+=`
30
30
  <div style="margin-top: 8px; font-family: ${o};">
31
- <div style="font-weight:bold; color: #fff; margin-bottom: 2px;">${l}</div>
32
- `,u[l].forEach(v=>{let g=v.value;if(Array.isArray(g)&&(g=g[1]),g==null)return;const S=typeof g=="number"?g.toLocaleString(void 0,{maximumFractionDigits:4}):g;p+=`
31
+ <div style="font-weight:bold; color: #fff; margin-bottom: 2px;">${m}</div>
32
+ `,f[m].forEach(d=>{let x=d.value;if(Array.isArray(x)&&(x=x[1]),x==null)return;const S=typeof x=="number"?x.toLocaleString(void 0,{maximumFractionDigits:4}):x;p+=`
33
33
  <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2px; padding-left: 8px;">
34
- <div>${v.marker} <span style="color: #cbd5e1;">${v.displayName}</span></div>
34
+ <div>${d.marker} <span style="color: #cbd5e1;">${d.displayName}</span></div>
35
35
  <div style="font-size: 10px; color: #fff;padding-left:10px;">${S}</div>
36
- </div>`}),p+="</div>"})}return p}}var wt=Object.defineProperty,Ct=(a,e,t)=>e in a?wt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,U=(a,e,t)=>(Ct(a,typeof e!="symbol"?e+"":e,t),t);class It{constructor(e,t){U(this,"plugins",new Map),U(this,"activePluginId",null),U(this,"context"),U(this,"toolbarContainer"),U(this,"tooltipElement",null),U(this,"hideTimeout",null),this.context=e,this.toolbarContainer=t,this.createTooltip(),this.renderToolbar()}createTooltip(){this.tooltipElement=document.createElement("div"),Object.assign(this.tooltipElement.style,{position:"fixed",display:"none",backgroundColor:"#1e293b",color:"#e2e8f0",padding:"6px 10px",borderRadius:"6px",fontSize:"13px",lineHeight:"1.4",fontWeight:"500",border:"1px solid #334155",zIndex:"9999",pointerEvents:"none",whiteSpace:"nowrap",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15)",fontFamily:this.context.getOptions().fontFamily||"sans-serif",transition:"opacity 0.15s ease-in-out, transform 0.15s ease-in-out",opacity:"0",transform:"translateX(-5px)"}),document.body.appendChild(this.tooltipElement)}destroy(){this.tooltipElement&&this.tooltipElement.parentNode&&this.tooltipElement.parentNode.removeChild(this.tooltipElement),this.tooltipElement=null}showTooltip(e,t){if(!this.tooltipElement)return;this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null);const i=e.getBoundingClientRect();this.tooltipElement.textContent=t,this.tooltipElement.style.display="block";const s=this.tooltipElement.getBoundingClientRect(),n=i.top+(i.height-s.height)/2,o=i.right+10;this.tooltipElement.style.top=`${n}px`,this.tooltipElement.style.left=`${o}px`,requestAnimationFrame(()=>{this.tooltipElement&&(this.tooltipElement.style.opacity="1",this.tooltipElement.style.transform="translateX(0)")})}hideTooltip(){this.tooltipElement&&(this.tooltipElement.style.opacity="0",this.tooltipElement.style.transform="translateX(-5px)",this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(()=>{this.tooltipElement&&(this.tooltipElement.style.display="none"),this.hideTimeout=null},150))}register(e){if(this.plugins.has(e.id)){console.warn(`Plugin with id ${e.id} is already registered.`);return}this.plugins.set(e.id,e),e.init(this.context),this.addButton(e)}unregister(e){const t=this.plugins.get(e);t&&(this.activePluginId===e&&this.deactivatePlugin(),t.destroy?.(),this.plugins.delete(e),this.removeButton(e))}activatePlugin(e){if(this.activePluginId===e){this.deactivatePlugin();return}this.activePluginId&&this.deactivatePlugin();const t=this.plugins.get(e);t&&(this.activePluginId=e,this.setButtonActive(e,!0),t.activate?.())}deactivatePlugin(){this.activePluginId&&(this.plugins.get(this.activePluginId)?.deactivate?.(),this.setButtonActive(this.activePluginId,!1),this.activePluginId=null)}renderToolbar(){this.toolbarContainer.innerHTML="",this.toolbarContainer.style.display="flex",this.toolbarContainer.style.flexDirection="column",this.toolbarContainer.style.width="40px",this.toolbarContainer.style.backgroundColor=this.context.getOptions().backgroundColor||"#1e293b",this.toolbarContainer.style.borderRight="1px solid #334155",this.toolbarContainer.style.padding="5px",this.toolbarContainer.style.boxSizing="border-box",this.toolbarContainer.style.gap="5px",this.toolbarContainer.style.flexShrink="0"}addButton(e){const t=document.createElement("button");t.id=`qfchart-plugin-btn-${e.id}`,t.style.width="30px",t.style.height="30px",t.style.padding="4px",t.style.border="1px solid transparent",t.style.borderRadius="4px",t.style.backgroundColor="transparent",t.style.cursor="pointer",t.style.color=this.context.getOptions().fontColor||"#cbd5e1",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",e.icon?t.innerHTML=e.icon:t.innerText=(e.name||e.id).substring(0,2).toUpperCase(),t.addEventListener("mouseenter",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="rgba(255, 255, 255, 0.1)"),this.showTooltip(t,e.name||e.id)}),t.addEventListener("mouseleave",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="transparent"),this.hideTooltip()}),t.onclick=()=>this.activatePlugin(e.id),this.toolbarContainer.appendChild(t)}removeButton(e){const t=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);t&&t.remove()}setButtonActive(e,t){const i=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);i&&(t?(i.style.backgroundColor="#2563eb",i.style.color="#ffffff"):(i.style.backgroundColor="transparent",i.style.color=this.context.getOptions().fontColor||"#cbd5e1"))}}var Pt=Object.defineProperty,St=(a,e,t)=>e in a?Pt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,A=(a,e,t)=>(St(a,typeof e!="symbol"?e+"":e,t),t);class kt{constructor(e){A(this,"context"),A(this,"isEditing",!1),A(this,"currentDrawing",null),A(this,"editingPointIndex",null),A(this,"zr"),A(this,"editGroup",null),A(this,"editLine",null),A(this,"editStartPoint",null),A(this,"editEndPoint",null),A(this,"isMovingShape",!1),A(this,"dragStart",null),A(this,"initialPixelPoints",[]),A(this,"onDrawingMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.isMovingShape=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.dragStart={x:t.x,y:t.y},this.initialPixelPoints=i.points.map(s=>{const n=this.context.coordinateConversion.dataToPixel(s);return n?{x:n.x,y:n.y}:{x:0,y:0}}),this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),A(this,"onPointMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.editingPointIndex=t.pointIndex,this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),A(this,"onMouseMove",t=>{if(!this.isEditing||!this.currentDrawing)return;const i=t.offsetX,s=t.offsetY;if(this.isMovingShape&&this.dragStart){const n=i-this.dragStart.x,o=s-this.dragStart.y,h={x:this.initialPixelPoints[0].x+n,y:this.initialPixelPoints[0].y+o},p={x:this.initialPixelPoints[1].x+n,y:this.initialPixelPoints[1].y+o};this.editLine.setShape({x1:h.x,y1:h.y,x2:p.x,y2:p.y}),this.editStartPoint.setShape({cx:h.x,cy:h.y}),this.editEndPoint.setShape({cx:p.x,cy:p.y})}else this.editingPointIndex!==null&&(this.editingPointIndex===0?(this.editLine.setShape({x1:i,y1:s}),this.editStartPoint.setShape({cx:i,cy:s})):(this.editLine.setShape({x2:i,y2:s}),this.editEndPoint.setShape({cx:i,cy:s})))}),A(this,"onMouseUp",t=>{this.isEditing&&this.finishEditing(t.offsetX,t.offsetY)}),this.context=e,this.zr=this.context.getChart().getZr(),this.bindEvents()}bindEvents(){this.context.events.on("drawing:point:mousedown",this.onPointMouseDown),this.context.events.on("drawing:mousedown",this.onDrawingMouseDown)}createEditGraphic(){if(!this.currentDrawing)return;this.editGroup=new D.graphic.Group;const e=this.currentDrawing.points[0],t=this.currentDrawing.points[1],i=this.context.coordinateConversion.dataToPixel(e),s=this.context.coordinateConversion.dataToPixel(t);!i||!s||(this.editLine=new D.graphic.Line({shape:{x1:i.x,y1:i.y,x2:s.x,y2:s.y},style:{stroke:this.currentDrawing.style?.color||"#3b82f6",lineWidth:this.currentDrawing.style?.lineWidth||2,lineDash:[4,4]},silent:!0}),this.editStartPoint=new D.graphic.Circle({shape:{cx:i.x,cy:i.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editEndPoint=new D.graphic.Circle({shape:{cx:s.x,cy:s.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editGroup.add(this.editLine),this.editGroup.add(this.editStartPoint),this.editGroup.add(this.editEndPoint),this.zr.add(this.editGroup))}finishEditing(e,t){if(this.currentDrawing){if(this.isMovingShape&&this.dragStart){const i=e-this.dragStart.x,s=t-this.dragStart.y,n=this.initialPixelPoints.map((o,h)=>{const p=o.x+i,d=o.y+s;return this.context.coordinateConversion.pixelToData({x:p,y:d})});n.every(o=>o!==null)&&n[0]&&n[1]&&(this.currentDrawing.points[0]=n[0],this.currentDrawing.points[1]=n[1],n[0].paneIndex!==void 0&&(this.currentDrawing.paneIndex=n[0].paneIndex),this.context.updateDrawing(this.currentDrawing))}else if(this.editingPointIndex!==null){const i=this.context.coordinateConversion.pixelToData({x:e,y:t});i&&(this.currentDrawing.points[this.editingPointIndex]=i,this.editingPointIndex===0&&i.paneIndex!==void 0&&(this.currentDrawing.paneIndex=i.paneIndex),this.context.updateDrawing(this.currentDrawing))}this.isEditing=!1,this.isMovingShape=!1,this.dragStart=null,this.initialPixelPoints=[],this.currentDrawing=null,this.editingPointIndex=null,this.editGroup&&(this.zr.remove(this.editGroup),this.editGroup=null),this.zr.off("mousemove",this.onMouseMove),this.zr.off("mouseup",this.onMouseUp),this.context.unlockChart()}}}var Dt=Object.defineProperty,Et=(a,e,t)=>e in a?Dt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,Mt=(a,e,t)=>(Et(a,typeof e!="symbol"?e+"":e,t),t);class zt{constructor(){Mt(this,"handlers",new Map)}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const i=this.handlers.get(e);i&&i.delete(t)}emit(e,t){const i=this.handlers.get(e);i&&i.forEach(s=>{try{s(t)}catch(n){console.error(`Error in EventBus handler for ${e}:`,n)}})}clear(){this.handlers.clear()}}var Tt=Object.defineProperty,Lt=(a,e,t)=>e in a?Tt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,C=(a,e,t)=>(Lt(a,typeof e!="symbol"?e+"":e,t),t);class At{constructor(e,t={}){C(this,"chart"),C(this,"options"),C(this,"marketData",[]),C(this,"indicators",new Map),C(this,"timeToIndex",new Map),C(this,"pluginManager"),C(this,"drawingEditor"),C(this,"events",new zt),C(this,"isMainCollapsed",!1),C(this,"maximizedPaneId",null),C(this,"selectedDrawingId",null),C(this,"drawings",[]),C(this,"coordinateConversion",{pixelToData:n=>{const o=this.chart.getOption();if(!o||!o.grid)return null;const h=o.grid.length;for(let p=0;p<h;p++)if(this.chart.containPixel({gridIndex:p},[n.x,n.y])){this.chart.convertFromPixel({seriesIndex:p},[n.x,n.y]);const d=this.chart.convertFromPixel({gridIndex:p},[n.x,n.y]);if(d)return{timeIndex:Math.round(d[0]),value:d[1],paneIndex:p}}return null},dataToPixel:n=>{const o=n.paneIndex||0,h=this.chart.convertToPixel({gridIndex:o},[n.timeIndex,n.value]);return h?{x:h[0],y:h[1]}:null}}),C(this,"upColor","#00da3c"),C(this,"downColor","#ec0000"),C(this,"defaultPadding",0),C(this,"padding"),C(this,"dataIndexOffset",0),C(this,"rootContainer"),C(this,"layoutContainer"),C(this,"toolbarContainer"),C(this,"leftSidebar"),C(this,"rightSidebar"),C(this,"chartContainer"),C(this,"onKeyDown",n=>{(n.key==="Delete"||n.key==="Backspace")&&this.selectedDrawingId&&(this.removeDrawing(this.selectedDrawingId),this.selectedDrawingId=null,this.render())}),C(this,"onFullscreenChange",()=>{this.render()}),C(this,"isLocked",!1),C(this,"lockedState",null),this.rootContainer=e,this.options={title:"Market",height:"600px",backgroundColor:"#1e293b",upColor:"#00da3c",downColor:"#ec0000",fontColor:"#cbd5e1",fontFamily:"sans-serif",padding:.01,dataZoom:{visible:!0,position:"top",height:6},layout:{mainPaneHeight:"50%",gap:13},watermark:!0,...t},this.options.upColor&&(this.upColor=this.options.upColor),this.options.downColor&&(this.downColor=this.options.downColor),this.padding=this.options.padding!==void 0?this.options.padding:this.defaultPadding,this.options.height&&(typeof this.options.height=="number"?this.rootContainer.style.height=`${this.options.height}px`:this.rootContainer.style.height=this.options.height),this.rootContainer.innerHTML="",this.layoutContainer=document.createElement("div"),this.layoutContainer.style.display="flex",this.layoutContainer.style.width="100%",this.layoutContainer.style.height="100%",this.layoutContainer.style.overflow="hidden",this.rootContainer.appendChild(this.layoutContainer),this.leftSidebar=document.createElement("div"),this.leftSidebar.style.display="none",this.leftSidebar.style.width="250px",this.leftSidebar.style.flexShrink="0",this.leftSidebar.style.overflowY="auto",this.leftSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.leftSidebar.style.borderRight="1px solid #334155",this.leftSidebar.style.padding="10px",this.leftSidebar.style.boxSizing="border-box",this.leftSidebar.style.color="#cbd5e1",this.leftSidebar.style.fontSize="12px",this.leftSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.leftSidebar),this.toolbarContainer=document.createElement("div"),this.layoutContainer.appendChild(this.toolbarContainer),this.chartContainer=document.createElement("div"),this.chartContainer.style.flexGrow="1",this.chartContainer.style.height="100%",this.chartContainer.style.overflow="hidden",this.layoutContainer.appendChild(this.chartContainer),this.rightSidebar=document.createElement("div"),this.rightSidebar.style.display="none",this.rightSidebar.style.width="250px",this.rightSidebar.style.flexShrink="0",this.rightSidebar.style.overflowY="auto",this.rightSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.rightSidebar.style.borderLeft="1px solid #334155",this.rightSidebar.style.padding="10px",this.rightSidebar.style.boxSizing="border-box",this.rightSidebar.style.color="#cbd5e1",this.rightSidebar.style.fontSize="12px",this.rightSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.rightSidebar),this.chart=D.init(this.chartContainer),this.pluginManager=new It(this,this.toolbarContainer),this.drawingEditor=new kt(this),this.chart.on("dataZoom",n=>this.events.emit("chart:dataZoom",n)),this.chart.on("finished",n=>this.events.emit("chart:updated",n)),this.chart.getZr().on("mousedown",n=>this.events.emit("mouse:down",n)),this.chart.getZr().on("mousemove",n=>this.events.emit("mouse:move",n)),this.chart.getZr().on("mouseup",n=>this.events.emit("mouse:up",n)),this.chart.getZr().on("click",n=>this.events.emit("mouse:click",n));const i=this.chart.getZr(),s=i.setCursorStyle;i.setCursorStyle=function(n){n==="grab"&&(n="crosshair"),s.call(this,n)},this.bindDrawingEvents(),window.addEventListener("resize",this.resize.bind(this)),document.addEventListener("fullscreenchange",this.onFullscreenChange),document.addEventListener("keydown",this.onKeyDown)}bindDrawingEvents(){let e=null;const t=i=>{if(!i||i.componentType!=="series"||!i.seriesName?.startsWith("drawings"))return null;i.seriesIndex;const s=i.seriesName.match(/drawings-pane-(\d+)/);if(!s)return null;const n=parseInt(s[1]),o=this.drawings.filter(p=>(p.paneIndex||0)===n)[i.dataIndex];if(!o)return null;const h=i.event?.target?.name;return{drawing:o,targetName:h,paneIdx:n}};this.chart.on("mouseover",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(n){const o=s.drawing.id===this.selectedDrawingId;e&&(clearTimeout(e),e=null),o||n.children().forEach(h=>{h.name&&h.name.startsWith("point")&&h.attr("style",{opacity:1})})}if(s.targetName==="line")this.events.emit("drawing:hover",{id:s.drawing.id,type:s.drawing.type}),this.chart.getZr().setCursorStyle("move");else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:hover",{id:s.drawing.id,pointIndex:o}),this.chart.getZr().setCursorStyle("pointer")}}),this.chart.on("mouseout",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(s.drawing.id!==this.selectedDrawingId){if(e=setTimeout(()=>{if(n){if(this.selectedDrawingId===s.drawing.id)return;n.children().forEach(o=>{o.name&&o.name.startsWith("point")&&o.attr("style",{opacity:0})})}},50),s.targetName==="line")this.events.emit("drawing:mouseout",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mouseout",{id:s.drawing.id,pointIndex:o})}this.chart.getZr().setCursorStyle("default")}}),this.chart.on("mousedown",i=>{const s=t(i);if(!s)return;const n=i.event?.event||i.event,o=n?.offsetX,h=n?.offsetY;if(s.targetName==="line")this.events.emit("drawing:mousedown",{id:s.drawing.id,x:o,y:h});else if(s.targetName?.startsWith("point")){const p=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mousedown",{id:s.drawing.id,pointIndex:p,x:o,y:h})}}),this.chart.on("click",i=>{const s=t(i);if(s){if(this.selectedDrawingId!==s.drawing.id&&(this.selectedDrawingId=s.drawing.id,this.events.emit("drawing:selected",{id:s.drawing.id}),this.render()),s.targetName==="line")this.events.emit("drawing:click",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const n=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:click",{id:s.drawing.id,pointIndex:n})}}}),this.chart.getZr().on("click",i=>{i.target||this.selectedDrawingId&&(this.events.emit("drawing:deselected",{id:this.selectedDrawingId}),this.selectedDrawingId=null,this.render())})}getChart(){return this.chart}getMarketData(){return this.marketData}getTimeToIndex(){return this.timeToIndex}getOptions(){return this.options}disableTools(){this.pluginManager.deactivatePlugin()}registerPlugin(e){this.pluginManager.register(e)}addDrawing(e){this.drawings.push(e),this.render()}removeDrawing(e){const t=this.drawings.findIndex(i=>i.id===e);if(t!==-1){const i=this.drawings[t];this.drawings.splice(t,1),this.events.emit("drawing:deleted",{id:i.id}),this.render()}}getDrawing(e){return this.drawings.find(t=>t.id===e)}updateDrawing(e){const t=this.drawings.findIndex(i=>i.id===e.id);t!==-1&&(this.drawings[t]=e,this.render())}lockChart(){if(this.isLocked)return;this.isLocked=!0;const e=this.chart.getOption();this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!0})),tooltip:{show:!1}})}unlockChart(){if(!this.isLocked)return;this.isLocked=!1;const e=this.chart.getOption();(this.options.dataZoom||{}).visible,e.dataZoom&&this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!1})),tooltip:{show:!0}})}setZoom(e,t){this.chart.dispatchAction({type:"dataZoom",start:e,end:t})}setMarketData(e){this.marketData=e,this.rebuildTimeIndex(),this.render()}updateData(e){if(e.length===0)return;const t=new Map;this.marketData.forEach(l=>{t.set(l.time,l)}),e.forEach(l=>{t.has(l.time),t.set(l.time,l)}),this.marketData=Array.from(t.values()).sort((l,v)=>l.time-v.time),this.rebuildTimeIndex();const i=this.dataIndexOffset,s=this.marketData.map(l=>[l.open,l.close,l.low,l.high]),n={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}},o=[...Array(i).fill(n),...s,...Array(i).fill(n)],h=[...Array(i).fill(""),...this.marketData.map(l=>new Date(l.time).toLocaleString()),...Array(i).fill("")],p=this.chart.getOption(),d=pt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId),b=nt.buildIndicatorSeries(this.indicators,this.timeToIndex,d.paneLayout,h.length,i),u={xAxis:p.xAxis.map((l,v)=>({data:h})),series:[{data:o},...b.map(l=>({data:l.data}))]};this.chart.setOption(u,{notMerge:!1})}addIndicator(e,t,i={isOverlay:!1}){const s=i.isOverlay??!1;let n=0;if(!s){let h=0;this.indicators.forEach(p=>{p.paneIndex>h&&(h=p.paneIndex)}),n=h+1}const o=new xt(e,t,n,{height:i.height,collapsed:!1,titleColor:i.titleColor,controls:i.controls});return this.indicators.set(e,o),this.render(),o}setIndicator(e,t,i=!1){this.addIndicator(e,{[e]:t},{isOverlay:i})}removeIndicator(e){this.indicators.delete(e),this.render()}toggleIndicator(e,t="collapse"){if(t==="fullscreen"){document.fullscreenElement?document.exitFullscreen():this.rootContainer.requestFullscreen();return}if(t==="maximize"){this.maximizedPaneId===e?this.maximizedPaneId=null:this.maximizedPaneId=e,this.render();return}if(e==="main"){this.isMainCollapsed=!this.isMainCollapsed,this.render();return}const i=this.indicators.get(e);i&&(i.toggleCollapse(),this.render())}resize(){this.chart.resize()}destroy(){window.removeEventListener("resize",this.resize.bind(this)),document.removeEventListener("fullscreenchange",this.onFullscreenChange),document.removeEventListener("keydown",this.onKeyDown),this.pluginManager.deactivatePlugin(),this.pluginManager.destroy(),this.chart.dispose()}rebuildTimeIndex(){this.timeToIndex.clear(),this.marketData.forEach((i,s)=>{this.timeToIndex.set(i.time,s)});const e=this.marketData.length,t=Math.ceil(e*this.padding);this.dataIndexOffset=t}render(){if(this.marketData.length===0)return;let e=null;try{const r=this.chart.getOption();if(r&&r.dataZoom&&r.dataZoom.length>0){const c=r.dataZoom.find(y=>y.type==="slider"||y.type==="inside");c&&(e={start:c.start,end:c.end})}}catch{}const t=this.options.databox?.position,i=this.leftSidebar.style.display,s=this.rightSidebar.style.display,n=t==="left"?"block":"none",o=t==="right"?"block":"none";(i!==n||s!==o)&&(this.leftSidebar.style.display=n,this.rightSidebar.style.display=o,this.chart.resize());const h=this.dataIndexOffset,p=[...Array(h).fill(""),...this.marketData.map(r=>new Date(r.time).toLocaleString()),...Array(h).fill("")],d=pt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId);e&&d.dataZoom&&d.dataZoom.forEach(r=>{r.start=e.start,r.end=e.end}),d.xAxis.forEach(r=>{r.data=p,r.boundaryGap=!1});const b=nt.buildCandlestickSeries(this.marketData,this.options),u={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}};b.data=[...Array(h).fill(u),...b.data,...Array(h).fill(u)];const l=nt.buildIndicatorSeries(this.indicators,this.timeToIndex,d.paneLayout,p.length,h),v=bt.build(d,this.options,this.toggleIndicator.bind(this),this.isMainCollapsed,this.maximizedPaneId),g=new Map;this.drawings.forEach(r=>{const c=r.paneIndex||0;g.has(c)||g.set(c,[]),g.get(c).push(r)});const S=[];g.forEach((r,c)=>{S.push({type:"custom",name:`drawings-pane-${c}`,xAxisIndex:c,yAxisIndex:c,clip:!0,renderItem:(y,I)=>{const x=r[y.dataIndex];if(!x)return;const M=x.points[0],$=x.points[1];if(!M||!$)return;const Z=I.coord([M.timeIndex,M.value]),m=I.coord([$.timeIndex,$.value]),P=x.id===this.selectedDrawingId;if(x.type==="line")return{type:"group",children:[{type:"line",name:"line",shape:{x1:Z[0],y1:Z[1],x2:m[0],y2:m[1]},style:{stroke:x.style?.color||"#3b82f6",lineWidth:x.style?.lineWidth||2}},{type:"circle",name:"point-start",shape:{cx:Z[0],cy:Z[1],r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:P?1:0}},{type:"circle",name:"point-end",shape:{cx:m[0],cy:m[1],r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:P?1:0}}]};if(x.type==="fibonacci"){const T=Z[0],j=Z[1],F=m[0],w=m[1],E=Math.min(T,F),R=Math.max(T,F),N=R-E,L=w-j,O=[0,.236,.382,.5,.618,.786,1],B=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"],Q=[];Q.push({type:"line",name:"line",shape:{x1:T,y1:j,x2:F,y2:w},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}}),Q.push({type:"circle",name:"point-start",shape:{cx:T,cy:j,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:P?1:0},z:100}),Q.push({type:"circle",name:"point-end",shape:{cx:F,cy:w,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:P?1:0},z:100}),O.forEach((V,X)=>{const W=w-L*V,_=B[X%B.length];Q.push({type:"line",name:"fib-line",shape:{x1:E,y1:W,x2:R,y2:W},style:{stroke:_,lineWidth:1},silent:!0});const at=x.points[0].value,tt=x.points[1].value,rt=tt-at,lt=tt-rt*V;if(Q.push({type:"text",style:{text:`${V} (${lt.toFixed(2)})`,x:E+5,y:W-10,fill:_,fontSize:10},silent:!0}),X<O.length-1){const ht=O[X+1],et=w-L*ht,dt=Math.abs(et-W),ct=Math.min(W,et);Q.push({type:"rect",shape:{x:E,y:ct,width:N,height:dt},style:{fill:B[(X+1)%B.length],opacity:.1},silent:!0})}});const ut=[],ot=[];return O.forEach((V,X)=>{const W=w-L*V,_=B[X%B.length];ot.push({type:"line",shape:{x1:E,y1:W,x2:R,y2:W},style:{stroke:_,lineWidth:1},silent:!0});const at=x.points[0].value,tt=x.points[1].value,rt=tt-at,lt=tt-rt*V;if(ot.push({type:"text",style:{text:`${V} (${lt.toFixed(2)})`,x:E+5,y:W-10,fill:_,fontSize:10},silent:!0}),X<O.length-1){const ht=O[X+1],et=w-L*ht,dt=Math.abs(et-W),ct=Math.min(W,et);ut.push({type:"rect",name:"line",shape:{x:E,y:ct,width:N,height:dt},style:{fill:B[(X+1)%B.length],opacity:.1}})}}),{type:"group",children:[...ut,...ot,{type:"line",name:"line",shape:{x1:T,y1:j,x2:F,y2:w},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}},{type:"circle",name:"point-start",shape:{cx:T,cy:j,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:P?1:0},z:100},{type:"circle",name:"point-end",shape:{cx:F,cy:w,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:P?1:0},z:100}]}}},data:r.map(y=>[y.points[0].timeIndex,y.points[0].value,y.points[1].timeIndex,y.points[1].value]),z:100,silent:!1})});const k=r=>{const c=vt.format(r,this.options),y=this.options.databox?.position;return y==="left"?(this.leftSidebar.innerHTML=c,""):y==="right"?(this.rightSidebar.innerHTML=c,""):this.options.databox?`<div style="min-width: 200px;">${c}</div>`:""},f={backgroundColor:this.options.backgroundColor,animation:!1,legend:{show:!1},tooltip:{show:!0,showContent:!!this.options.databox,trigger:"axis",axisPointer:{type:"cross",label:{backgroundColor:"#475569"}},backgroundColor:"rgba(30, 41, 59, 0.9)",borderWidth:1,borderColor:"#334155",padding:10,textStyle:{color:"#fff",fontFamily:this.options.fontFamily||"sans-serif"},formatter:k,extraCssText:t!=="floating"&&t!==void 0?"display: none !important;":void 0,position:(r,c,y,I,x)=>{if(this.options.databox?.position==="floating"){const M={top:10};return M[["left","right"][+(r[0]<x.viewSize[0]/2)]]=30,M}return null}},axisPointer:{link:{xAxisIndex:"all"},label:{backgroundColor:"#475569"}},graphic:v,grid:d.grid,xAxis:d.xAxis,yAxis:d.yAxis,dataZoom:d.dataZoom,series:[b,...l,...S]};this.chart.setOption(f,!0)}}var Zt=Object.defineProperty,Gt=(a,e,t)=>e in a?Zt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,K=(a,e,t)=>(Gt(a,typeof e!="symbol"?e+"":e,t),t);class it{constructor(e){K(this,"id"),K(this,"name"),K(this,"icon"),K(this,"context"),K(this,"eventListeners",[]),this.id=e.id,this.name=e.name,this.icon=e.icon}init(e){this.context=e,this.onInit()}onInit(){}activate(){this.onActivate(),this.context.events.emit("plugin:activated",this.id)}onActivate(){}deactivate(){this.onDeactivate(),this.context.events.emit("plugin:deactivated",this.id)}onDeactivate(){}destroy(){this.removeAllListeners(),this.onDestroy()}onDestroy(){}on(e,t){this.context.events.on(e,t),this.eventListeners.push({event:e,handler:t})}off(e,t){this.context.events.off(e,t),this.eventListeners=this.eventListeners.filter(i=>i.event!==e||i.handler!==t)}removeAllListeners(){this.eventListeners.forEach(({event:e,handler:t})=>{this.context.events.off(e,t)}),this.eventListeners=[]}get chart(){return this.context.getChart()}get marketData(){return this.context.getMarketData()}}var $t=Object.defineProperty,Ft=(a,e,t)=>e in a?$t(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,z=(a,e,t)=>(Ft(a,typeof e!="symbol"?e+"":e,t),t);class Nt extends it{constructor(e){super({id:"measure",name:e?.name||"Measure",icon:e?.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H680v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160H160v320Zm120-160h80-80Zm160 0h80-80Zm160 0h80-80Zm-120 0Z"/></svg>'}),z(this,"zr"),z(this,"state","idle"),z(this,"startPoint",null),z(this,"endPoint",null),z(this,"group",null),z(this,"rect",null),z(this,"labelRect",null),z(this,"labelText",null),z(this,"lineV",null),z(this,"lineH",null),z(this,"arrowStart",null),z(this,"arrowEnd",null),z(this,"onMouseDown",()=>{this.state==="finished"&&this.removeGraphic()}),z(this,"onChartInteraction",()=>{this.group&&this.removeGraphic()}),z(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.context.disableTools(),this.enableClearListeners())}),z(this,"clearHandlers",{}),z(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}enableClearListeners(){const e=()=>{this.removeGraphic()};setTimeout(()=>{this.zr.on("click",e)},10),this.zr.on("mousedown",this.onMouseDown),this.context.events.on("chart:dataZoom",this.onChartInteraction),this.clearHandlers={click:e,mousedown:this.onMouseDown,dataZoom:this.onChartInteraction}}disableClearListeners(){this.clearHandlers.click&&this.zr.off("click",this.clearHandlers.click),this.clearHandlers.mousedown&&this.zr.off("mousedown",this.clearHandlers.mousedown),this.clearHandlers.dataZoom&&this.context.events.off("chart:dataZoom",this.clearHandlers.dataZoom),this.clearHandlers={}}initGraphic(){this.group||(this.group=new D.graphic.Group,this.rect=new D.graphic.Rect({shape:{x:0,y:0,width:0,height:0},style:{fill:"rgba(0,0,0,0)",stroke:"transparent",lineWidth:0},z:100}),this.lineV=new D.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.lineH=new D.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.arrowStart=new D.graphic.Polygon({shape:{points:[[0,0],[-5,10],[5,10]]},style:{fill:"#fff"},z:102}),this.arrowEnd=new D.graphic.Polygon({shape:{points:[[0,0],[-5,-10],[5,-10]]},style:{fill:"#fff"},z:102}),this.labelRect=new D.graphic.Rect({shape:{x:0,y:0,width:0,height:0,r:4},style:{fill:"transparent",stroke:"transparent",lineWidth:0,shadowBlur:5,shadowColor:"rgba(0,0,0,0.3)"},z:102}),this.labelText=new D.graphic.Text({style:{x:0,y:0,text:"",fill:"#fff",font:"12px sans-serif",align:"center",verticalAlign:"middle"},z:103}),this.group.add(this.rect),this.group.add(this.lineV),this.group.add(this.lineH),this.group.add(this.arrowStart),this.group.add(this.arrowEnd),this.group.add(this.labelRect),this.group.add(this.labelText),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint,n=this.context.coordinateConversion.pixelToData({x:e,y:t}),o=this.context.coordinateConversion.pixelToData({x:i,y:s});if(!n||!o)return;const h=Math.round(n.timeIndex),p=Math.round(o.timeIndex),d=n.value,b=o.value,u=p-h,l=b-d,v=l/d*100,g=l>=0,S=g?"rgba(33, 150, 243, 0.2)":"rgba(236, 0, 0, 0.2)",k=g?"#2196F3":"#ec0000";this.rect.setShape({x:Math.min(e,i),y:Math.min(t,s),width:Math.abs(i-e),height:Math.abs(s-t)}),this.rect.setStyle({fill:S});const f=(e+i)/2,r=(t+s)/2;this.lineV.setShape({x1:f,y1:t,x2:f,y2:s}),this.lineV.setStyle({stroke:k}),this.lineH.setShape({x1:e,y1:r,x2:i,y2:r}),this.lineH.setStyle({stroke:k});const c=Math.min(t,s),y=Math.max(t,s);this.arrowStart.setStyle({fill:"none"}),this.arrowEnd.setStyle({fill:"none"}),g?(this.arrowStart.setShape({points:[[f,c],[f-4,c+6],[f+4,c+6]]}),this.arrowStart.setStyle({fill:k})):(this.arrowEnd.setShape({points:[[f,y],[f-4,y-6],[f+4,y-6]]}),this.arrowEnd.setStyle({fill:k}));const I=[`${l.toFixed(2)} (${v.toFixed(2)}%)`,`${u} bars, ${(u*0).toFixed(0)}d`].join(`
37
- `),x=140,M=40,$=Math.max(t,s),Z=Math.min(t,s);let m=(e+i)/2-x/2,P=$+10;const T=this.chart.getHeight();P+M>T&&(P=Z-M-10),this.labelRect.setShape({x:m,y:P,width:x,height:M}),this.labelRect.setStyle({fill:"#1e293b",stroke:k,lineWidth:1}),this.labelText.setStyle({x:m+x/2,y:P+M/2,text:I,fill:"#fff"})}}var Ot=Object.defineProperty,Wt=(a,e,t)=>e in a?Ot(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,G=(a,e,t)=>(Wt(a,typeof e!="symbol"?e+"":e,t),t);class Ht extends it{constructor(e){super({id:"trend-line",name:e?.name||"Trend Line",icon:e?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2" /></svg>'}),G(this,"zr"),G(this,"state","idle"),G(this,"startPoint",null),G(this,"endPoint",null),G(this,"group",null),G(this,"line",null),G(this,"startCircle",null),G(this,"endCircle",null),G(this,"onMouseDown",()=>{}),G(this,"onChartInteraction",()=>{}),G(this,"onClick",t=>{if(this.state==="idle")this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),s=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(i&&s){const n=i.paneIndex||0;this.context.addDrawing({id:`line-${Date.now()}`,type:"line",points:[i,s],paneIndex:n,style:{color:"#3b82f6",lineWidth:2}})}}this.removeGraphic(),this.context.disableTools()}}),G(this,"clearHandlers",{}),G(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}saveDataCoordinates(){}updateGraphicFromData(){}enableClearListeners(){}disableClearListeners(){}initGraphic(){this.group||(this.group=new D.graphic.Group,this.line=new D.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#3b82f6",lineWidth:2},z:100}),this.startCircle=new D.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.endCircle=new D.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint;this.line.setShape({x1:e,y1:t,x2:i,y2:s}),this.startCircle.setShape({cx:e,cy:t}),this.endCircle.setShape({cx:i,cy:s})}}var jt=Object.defineProperty,Bt=(a,e,t)=>e in a?jt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,Y=(a,e,t)=>(Bt(a,typeof e!="symbol"?e+"":e,t),t);class Xt extends it{constructor(e={}){super({id:"fibonacci-tool",name:e.name||"Fibonacci Retracement",icon:e.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Z"/></svg>'}),Y(this,"startPoint",null),Y(this,"endPoint",null),Y(this,"state","idle"),Y(this,"graphicGroup",null),Y(this,"levels",[0,.236,.382,.5,.618,.786,1]),Y(this,"colors",["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"]),Y(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),Y(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const e=this.context.getChart().getZr();e.on("click",this.onClick),e.on("mousemove",this.onMouseMove)}unbindEvents(){const e=this.context.getChart().getZr();e.off("click",this.onClick),e.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new D.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const e=this.startPoint[0],t=this.startPoint[1],i=this.endPoint[0],s=this.endPoint[1],n=new D.graphic.Line({shape:{x1:e,y1:t,x2:i,y2:s},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]},silent:!0});this.graphicGroup.add(n);const o=Math.min(e,i),h=Math.max(e,i),p=h-o,d=s-t;this.levels.forEach((b,u)=>{const l=s-d*b,v=this.colors[u%this.colors.length],g=new D.graphic.Line({shape:{x1:o,y1:l,x2:h,y2:l},style:{stroke:v,lineWidth:1},silent:!0});if(this.graphicGroup.add(g),u<this.levels.length-1){const S=this.levels[u+1],k=s-d*S,f=Math.abs(k-l),r=Math.min(l,k),c=new D.graphic.Rect({shape:{x:o,y:r,width:p,height:f},style:{fill:this.colors[(u+1)%this.colors.length],opacity:.1},silent:!0});this.graphicGroup.add(c)}})}saveDrawing(){if(!this.startPoint||!this.endPoint)return;const e=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),t=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(e&&t){const i=e.paneIndex||0;this.context.addDrawing({id:`fib-${Date.now()}`,type:"fibonacci",points:[e,t],paneIndex:i,style:{color:"#3b82f6",lineWidth:1}})}}}H.AbstractPlugin=it,H.FibonacciTool=Xt,H.LineTool=Ht,H.MeasureTool=Nt,H.QFChart=At});
36
+ </div>`}),p+="</div>"})}return p}}var Ct=Object.defineProperty,St=(a,e,t)=>e in a?Ct(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,J=(a,e,t)=>(St(a,typeof e!="symbol"?e+"":e,t),t);class kt{constructor(e,t){J(this,"plugins",new Map),J(this,"activePluginId",null),J(this,"context"),J(this,"toolbarContainer"),J(this,"tooltipElement",null),J(this,"hideTimeout",null),this.context=e,this.toolbarContainer=t,this.createTooltip(),this.renderToolbar()}createTooltip(){this.tooltipElement=document.createElement("div"),Object.assign(this.tooltipElement.style,{position:"fixed",display:"none",backgroundColor:"#1e293b",color:"#e2e8f0",padding:"6px 10px",borderRadius:"6px",fontSize:"13px",lineHeight:"1.4",fontWeight:"500",border:"1px solid #334155",zIndex:"9999",pointerEvents:"none",whiteSpace:"nowrap",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15)",fontFamily:this.context.getOptions().fontFamily||"sans-serif",transition:"opacity 0.15s ease-in-out, transform 0.15s ease-in-out",opacity:"0",transform:"translateX(-5px)"}),document.body.appendChild(this.tooltipElement)}destroy(){this.tooltipElement&&this.tooltipElement.parentNode&&this.tooltipElement.parentNode.removeChild(this.tooltipElement),this.tooltipElement=null}showTooltip(e,t){if(!this.tooltipElement)return;this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null);const i=e.getBoundingClientRect();this.tooltipElement.textContent=t,this.tooltipElement.style.display="block";const s=this.tooltipElement.getBoundingClientRect(),n=i.top+(i.height-s.height)/2,o=i.right+10;this.tooltipElement.style.top=`${n}px`,this.tooltipElement.style.left=`${o}px`,requestAnimationFrame(()=>{this.tooltipElement&&(this.tooltipElement.style.opacity="1",this.tooltipElement.style.transform="translateX(0)")})}hideTooltip(){this.tooltipElement&&(this.tooltipElement.style.opacity="0",this.tooltipElement.style.transform="translateX(-5px)",this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(()=>{this.tooltipElement&&(this.tooltipElement.style.display="none"),this.hideTimeout=null},150))}register(e){if(this.plugins.has(e.id)){console.warn(`Plugin with id ${e.id} is already registered.`);return}this.plugins.set(e.id,e),e.init(this.context),this.addButton(e)}unregister(e){const t=this.plugins.get(e);t&&(this.activePluginId===e&&this.deactivatePlugin(),t.destroy?.(),this.plugins.delete(e),this.removeButton(e))}activatePlugin(e){if(this.activePluginId===e){this.deactivatePlugin();return}this.activePluginId&&this.deactivatePlugin();const t=this.plugins.get(e);t&&(this.activePluginId=e,this.setButtonActive(e,!0),t.activate?.())}deactivatePlugin(){this.activePluginId&&(this.plugins.get(this.activePluginId)?.deactivate?.(),this.setButtonActive(this.activePluginId,!1),this.activePluginId=null)}renderToolbar(){this.toolbarContainer.innerHTML="",this.toolbarContainer.style.display="flex",this.toolbarContainer.style.flexDirection="column",this.toolbarContainer.style.width="40px",this.toolbarContainer.style.backgroundColor=this.context.getOptions().backgroundColor||"#1e293b",this.toolbarContainer.style.borderRight="1px solid #334155",this.toolbarContainer.style.padding="5px",this.toolbarContainer.style.boxSizing="border-box",this.toolbarContainer.style.gap="5px",this.toolbarContainer.style.flexShrink="0"}addButton(e){const t=document.createElement("button");t.id=`qfchart-plugin-btn-${e.id}`,t.style.width="30px",t.style.height="30px",t.style.padding="4px",t.style.border="1px solid transparent",t.style.borderRadius="4px",t.style.backgroundColor="transparent",t.style.cursor="pointer",t.style.color=this.context.getOptions().fontColor||"#cbd5e1",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",e.icon?t.innerHTML=e.icon:t.innerText=(e.name||e.id).substring(0,2).toUpperCase(),t.addEventListener("mouseenter",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="rgba(255, 255, 255, 0.1)"),this.showTooltip(t,e.name||e.id)}),t.addEventListener("mouseleave",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="transparent"),this.hideTooltip()}),t.onclick=()=>this.activatePlugin(e.id),this.toolbarContainer.appendChild(t)}removeButton(e){const t=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);t&&t.remove()}setButtonActive(e,t){const i=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);i&&(t?(i.style.backgroundColor="#2563eb",i.style.color="#ffffff"):(i.style.backgroundColor="transparent",i.style.color=this.context.getOptions().fontColor||"#cbd5e1"))}}var It=Object.defineProperty,Pt=(a,e,t)=>e in a?It(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,$=(a,e,t)=>(Pt(a,typeof e!="symbol"?e+"":e,t),t);class Mt{constructor(e){$(this,"context"),$(this,"isEditing",!1),$(this,"currentDrawing",null),$(this,"editingPointIndex",null),$(this,"zr"),$(this,"editGroup",null),$(this,"editLine",null),$(this,"editStartPoint",null),$(this,"editEndPoint",null),$(this,"isMovingShape",!1),$(this,"dragStart",null),$(this,"initialPixelPoints",[]),$(this,"onDrawingMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.isMovingShape=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.dragStart={x:t.x,y:t.y},this.initialPixelPoints=i.points.map(s=>{const n=this.context.coordinateConversion.dataToPixel(s);return n?{x:n.x,y:n.y}:{x:0,y:0}}),this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),$(this,"onPointMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.editingPointIndex=t.pointIndex,this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),$(this,"onMouseMove",t=>{if(!this.isEditing||!this.currentDrawing)return;const i=t.offsetX,s=t.offsetY;if(this.isMovingShape&&this.dragStart){const n=i-this.dragStart.x,o=s-this.dragStart.y,r={x:this.initialPixelPoints[0].x+n,y:this.initialPixelPoints[0].y+o},p={x:this.initialPixelPoints[1].x+n,y:this.initialPixelPoints[1].y+o};this.editLine.setShape({x1:r.x,y1:r.y,x2:p.x,y2:p.y}),this.editStartPoint.setShape({cx:r.x,cy:r.y}),this.editEndPoint.setShape({cx:p.x,cy:p.y})}else this.editingPointIndex!==null&&(this.editingPointIndex===0?(this.editLine.setShape({x1:i,y1:s}),this.editStartPoint.setShape({cx:i,cy:s})):(this.editLine.setShape({x2:i,y2:s}),this.editEndPoint.setShape({cx:i,cy:s})))}),$(this,"onMouseUp",t=>{this.isEditing&&this.finishEditing(t.offsetX,t.offsetY)}),this.context=e,this.zr=this.context.getChart().getZr(),this.bindEvents()}bindEvents(){this.context.events.on("drawing:point:mousedown",this.onPointMouseDown),this.context.events.on("drawing:mousedown",this.onDrawingMouseDown)}createEditGraphic(){if(!this.currentDrawing)return;this.editGroup=new E.graphic.Group;const e=this.currentDrawing.points[0],t=this.currentDrawing.points[1],i=this.context.coordinateConversion.dataToPixel(e),s=this.context.coordinateConversion.dataToPixel(t);!i||!s||(this.editLine=new E.graphic.Line({shape:{x1:i.x,y1:i.y,x2:s.x,y2:s.y},style:{stroke:this.currentDrawing.style?.color||"#3b82f6",lineWidth:this.currentDrawing.style?.lineWidth||2,lineDash:[4,4]},silent:!0}),this.editStartPoint=new E.graphic.Circle({shape:{cx:i.x,cy:i.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editEndPoint=new E.graphic.Circle({shape:{cx:s.x,cy:s.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editGroup.add(this.editLine),this.editGroup.add(this.editStartPoint),this.editGroup.add(this.editEndPoint),this.zr.add(this.editGroup))}finishEditing(e,t){if(this.currentDrawing){if(this.isMovingShape&&this.dragStart){const i=e-this.dragStart.x,s=t-this.dragStart.y,n=this.initialPixelPoints.map((o,r)=>{const p=o.x+i,u=o.y+s;return this.context.coordinateConversion.pixelToData({x:p,y:u})});n.every(o=>o!==null)&&n[0]&&n[1]&&(this.currentDrawing.points[0]=n[0],this.currentDrawing.points[1]=n[1],n[0].paneIndex!==void 0&&(this.currentDrawing.paneIndex=n[0].paneIndex),this.context.updateDrawing(this.currentDrawing))}else if(this.editingPointIndex!==null){const i=this.context.coordinateConversion.pixelToData({x:e,y:t});i&&(this.currentDrawing.points[this.editingPointIndex]=i,this.editingPointIndex===0&&i.paneIndex!==void 0&&(this.currentDrawing.paneIndex=i.paneIndex),this.context.updateDrawing(this.currentDrawing))}this.isEditing=!1,this.isMovingShape=!1,this.dragStart=null,this.initialPixelPoints=[],this.currentDrawing=null,this.editingPointIndex=null,this.editGroup&&(this.zr.remove(this.editGroup),this.editGroup=null),this.zr.off("mousemove",this.onMouseMove),this.zr.off("mouseup",this.onMouseUp),this.context.unlockChart()}}}var Dt=Object.defineProperty,zt=(a,e,t)=>e in a?Dt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,Et=(a,e,t)=>(zt(a,typeof e!="symbol"?e+"":e,t),t);class Tt{constructor(){Et(this,"handlers",new Map)}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const i=this.handlers.get(e);i&&i.delete(t)}emit(e,t){const i=this.handlers.get(e);i&&i.forEach(s=>{try{s(t)}catch(n){console.error(`Error in EventBus handler for ${e}:`,n)}})}clear(){this.handlers.clear()}}var At=Object.defineProperty,Lt=(a,e,t)=>e in a?At(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,k=(a,e,t)=>(Lt(a,typeof e!="symbol"?e+"":e,t),t);class Zt{constructor(e,t={}){k(this,"chart"),k(this,"options"),k(this,"marketData",[]),k(this,"indicators",new Map),k(this,"timeToIndex",new Map),k(this,"pluginManager"),k(this,"drawingEditor"),k(this,"events",new Tt),k(this,"isMainCollapsed",!1),k(this,"maximizedPaneId",null),k(this,"selectedDrawingId",null),k(this,"drawings",[]),k(this,"coordinateConversion",{pixelToData:n=>{const o=this.chart.getOption();if(!o||!o.grid)return null;const r=o.grid.length;for(let p=0;p<r;p++)if(this.chart.containPixel({gridIndex:p},[n.x,n.y])){this.chart.convertFromPixel({seriesIndex:p},[n.x,n.y]);const u=this.chart.convertFromPixel({gridIndex:p},[n.x,n.y]);if(u)return{timeIndex:Math.round(u[0]),value:u[1],paneIndex:p}}return null},dataToPixel:n=>{const o=n.paneIndex||0,r=this.chart.convertToPixel({gridIndex:o},[n.timeIndex,n.value]);return r?{x:r[0],y:r[1]}:null}}),k(this,"upColor","#00da3c"),k(this,"downColor","#ec0000"),k(this,"defaultPadding",0),k(this,"padding"),k(this,"dataIndexOffset",0),k(this,"rootContainer"),k(this,"layoutContainer"),k(this,"toolbarContainer"),k(this,"leftSidebar"),k(this,"rightSidebar"),k(this,"chartContainer"),k(this,"onKeyDown",n=>{(n.key==="Delete"||n.key==="Backspace")&&this.selectedDrawingId&&(this.removeDrawing(this.selectedDrawingId),this.selectedDrawingId=null,this.render())}),k(this,"onFullscreenChange",()=>{this.render()}),k(this,"isLocked",!1),k(this,"lockedState",null),this.rootContainer=e,this.options={title:"Market",height:"600px",backgroundColor:"#1e293b",upColor:"#00da3c",downColor:"#ec0000",fontColor:"#cbd5e1",fontFamily:"sans-serif",padding:.01,dataZoom:{visible:!0,position:"top",height:6},layout:{mainPaneHeight:"50%",gap:13},watermark:!0,...t},this.options.upColor&&(this.upColor=this.options.upColor),this.options.downColor&&(this.downColor=this.options.downColor),this.padding=this.options.padding!==void 0?this.options.padding:this.defaultPadding,this.options.height&&(typeof this.options.height=="number"?this.rootContainer.style.height=`${this.options.height}px`:this.rootContainer.style.height=this.options.height),this.rootContainer.innerHTML="",this.layoutContainer=document.createElement("div"),this.layoutContainer.style.display="flex",this.layoutContainer.style.width="100%",this.layoutContainer.style.height="100%",this.layoutContainer.style.overflow="hidden",this.rootContainer.appendChild(this.layoutContainer),this.leftSidebar=document.createElement("div"),this.leftSidebar.style.display="none",this.leftSidebar.style.width="250px",this.leftSidebar.style.flexShrink="0",this.leftSidebar.style.overflowY="auto",this.leftSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.leftSidebar.style.borderRight="1px solid #334155",this.leftSidebar.style.padding="10px",this.leftSidebar.style.boxSizing="border-box",this.leftSidebar.style.color="#cbd5e1",this.leftSidebar.style.fontSize="12px",this.leftSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.leftSidebar),this.toolbarContainer=document.createElement("div"),this.layoutContainer.appendChild(this.toolbarContainer),this.chartContainer=document.createElement("div"),this.chartContainer.style.flexGrow="1",this.chartContainer.style.height="100%",this.chartContainer.style.overflow="hidden",this.layoutContainer.appendChild(this.chartContainer),this.rightSidebar=document.createElement("div"),this.rightSidebar.style.display="none",this.rightSidebar.style.width="250px",this.rightSidebar.style.flexShrink="0",this.rightSidebar.style.overflowY="auto",this.rightSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.rightSidebar.style.borderLeft="1px solid #334155",this.rightSidebar.style.padding="10px",this.rightSidebar.style.boxSizing="border-box",this.rightSidebar.style.color="#cbd5e1",this.rightSidebar.style.fontSize="12px",this.rightSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.rightSidebar),this.chart=E.init(this.chartContainer),this.pluginManager=new kt(this,this.toolbarContainer),this.drawingEditor=new Mt(this),this.chart.on("dataZoom",n=>this.events.emit("chart:dataZoom",n)),this.chart.on("finished",n=>this.events.emit("chart:updated",n)),this.chart.getZr().on("mousedown",n=>this.events.emit("mouse:down",n)),this.chart.getZr().on("mousemove",n=>this.events.emit("mouse:move",n)),this.chart.getZr().on("mouseup",n=>this.events.emit("mouse:up",n)),this.chart.getZr().on("click",n=>this.events.emit("mouse:click",n));const i=this.chart.getZr(),s=i.setCursorStyle;i.setCursorStyle=function(n){n==="grab"&&(n="crosshair"),s.call(this,n)},this.bindDrawingEvents(),window.addEventListener("resize",this.resize.bind(this)),document.addEventListener("fullscreenchange",this.onFullscreenChange),document.addEventListener("keydown",this.onKeyDown)}bindDrawingEvents(){let e=null;const t=i=>{if(!i||i.componentType!=="series"||!i.seriesName?.startsWith("drawings"))return null;i.seriesIndex;const s=i.seriesName.match(/drawings-pane-(\d+)/);if(!s)return null;const n=parseInt(s[1]),o=this.drawings.filter(p=>(p.paneIndex||0)===n)[i.dataIndex];if(!o)return null;const r=i.event?.target?.name;return{drawing:o,targetName:r,paneIdx:n}};this.chart.on("mouseover",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(n){const o=s.drawing.id===this.selectedDrawingId;e&&(clearTimeout(e),e=null),o||n.children().forEach(r=>{r.name&&r.name.startsWith("point")&&r.attr("style",{opacity:1})})}if(s.targetName==="line")this.events.emit("drawing:hover",{id:s.drawing.id,type:s.drawing.type}),this.chart.getZr().setCursorStyle("move");else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:hover",{id:s.drawing.id,pointIndex:o}),this.chart.getZr().setCursorStyle("pointer")}}),this.chart.on("mouseout",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(s.drawing.id!==this.selectedDrawingId){if(e=setTimeout(()=>{if(n){if(this.selectedDrawingId===s.drawing.id)return;n.children().forEach(o=>{o.name&&o.name.startsWith("point")&&o.attr("style",{opacity:0})})}},50),s.targetName==="line")this.events.emit("drawing:mouseout",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mouseout",{id:s.drawing.id,pointIndex:o})}this.chart.getZr().setCursorStyle("default")}}),this.chart.on("mousedown",i=>{const s=t(i);if(!s)return;const n=i.event?.event||i.event,o=n?.offsetX,r=n?.offsetY;if(s.targetName==="line")this.events.emit("drawing:mousedown",{id:s.drawing.id,x:o,y:r});else if(s.targetName?.startsWith("point")){const p=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mousedown",{id:s.drawing.id,pointIndex:p,x:o,y:r})}}),this.chart.on("click",i=>{const s=t(i);if(s){if(this.selectedDrawingId!==s.drawing.id&&(this.selectedDrawingId=s.drawing.id,this.events.emit("drawing:selected",{id:s.drawing.id}),this.render()),s.targetName==="line")this.events.emit("drawing:click",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const n=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:click",{id:s.drawing.id,pointIndex:n})}}}),this.chart.getZr().on("click",i=>{i.target||this.selectedDrawingId&&(this.events.emit("drawing:deselected",{id:this.selectedDrawingId}),this.selectedDrawingId=null,this.render())})}getChart(){return this.chart}getMarketData(){return this.marketData}getTimeToIndex(){return this.timeToIndex}getOptions(){return this.options}disableTools(){this.pluginManager.deactivatePlugin()}registerPlugin(e){this.pluginManager.register(e)}addDrawing(e){this.drawings.push(e),this.render()}removeDrawing(e){const t=this.drawings.findIndex(i=>i.id===e);if(t!==-1){const i=this.drawings[t];this.drawings.splice(t,1),this.events.emit("drawing:deleted",{id:i.id}),this.render()}}getDrawing(e){return this.drawings.find(t=>t.id===e)}updateDrawing(e){const t=this.drawings.findIndex(i=>i.id===e.id);t!==-1&&(this.drawings[t]=e,this.render())}lockChart(){if(this.isLocked)return;this.isLocked=!0;const e=this.chart.getOption();this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!0})),tooltip:{show:!1}})}unlockChart(){if(!this.isLocked)return;this.isLocked=!1;const e=this.chart.getOption();(this.options.dataZoom||{}).visible,e.dataZoom&&this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!1})),tooltip:{show:!0}})}setZoom(e,t){this.chart.dispatchAction({type:"dataZoom",start:e,end:t})}setMarketData(e){this.marketData=e,this.rebuildTimeIndex(),this.render()}updateData(e){if(e.length===0)return;const t=new Map;this.marketData.forEach(d=>{t.set(d.time,d)}),e.forEach(d=>{t.has(d.time),t.set(d.time,d)}),this.marketData=Array.from(t.values()).sort((d,x)=>d.time-x.time),this.rebuildTimeIndex();const i=this.dataIndexOffset,s=this.marketData.map(d=>[d.open,d.close,d.low,d.high]),n={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}},o=[...Array(i).fill(n),...s,...Array(i).fill(n)],r=[...Array(i).fill(""),...this.marketData.map(d=>new Date(d.time).toLocaleString()),...Array(i).fill("")],p=this.chart.getOption(),u=ut.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId),v=[...Array(i).fill(null),...this.marketData,...Array(i).fill(null)],f=q.buildIndicatorSeries(this.indicators,this.timeToIndex,u.paneLayout,r.length,i,v),m={xAxis:p.xAxis.map((d,x)=>({data:r})),series:[{data:o},...f.map(d=>({data:d.data}))]};this.chart.setOption(m,{notMerge:!1})}addIndicator(e,t,i={isOverlay:!1}){const s=i.isOverlay??!1;let n=0;if(!s){let r=0;this.indicators.forEach(p=>{p.paneIndex>r&&(r=p.paneIndex)}),n=r+1}const o=new mt(e,t,n,{height:i.height,collapsed:!1,titleColor:i.titleColor,controls:i.controls});return this.indicators.set(e,o),this.render(),o}setIndicator(e,t,i=!1){this.addIndicator(e,{[e]:t},{isOverlay:i})}removeIndicator(e){this.indicators.delete(e),this.render()}toggleIndicator(e,t="collapse"){if(t==="fullscreen"){document.fullscreenElement?document.exitFullscreen():this.rootContainer.requestFullscreen();return}if(t==="maximize"){this.maximizedPaneId===e?this.maximizedPaneId=null:this.maximizedPaneId=e,this.render();return}if(e==="main"){this.isMainCollapsed=!this.isMainCollapsed,this.render();return}const i=this.indicators.get(e);i&&(i.toggleCollapse(),this.render())}resize(){this.chart.resize()}destroy(){window.removeEventListener("resize",this.resize.bind(this)),document.removeEventListener("fullscreenchange",this.onFullscreenChange),document.removeEventListener("keydown",this.onKeyDown),this.pluginManager.deactivatePlugin(),this.pluginManager.destroy(),this.chart.dispose()}rebuildTimeIndex(){this.timeToIndex.clear(),this.marketData.forEach((i,s)=>{this.timeToIndex.set(i.time,s)});const e=this.marketData.length,t=Math.ceil(e*this.padding);this.dataIndexOffset=t}render(){if(this.marketData.length===0)return;let e=null;try{const y=this.chart.getOption();if(y&&y.dataZoom&&y.dataZoom.length>0){const c=y.dataZoom.find(l=>l.type==="slider"||l.type==="inside");c&&(e={start:c.start,end:c.end})}}catch{}const t=this.options.databox?.position,i=this.leftSidebar.style.display,s=this.rightSidebar.style.display,n=t==="left"?"block":"none",o=t==="right"?"block":"none";(i!==n||s!==o)&&(this.leftSidebar.style.display=n,this.rightSidebar.style.display=o,this.chart.resize());const r=this.dataIndexOffset,p=[...Array(r).fill(""),...this.marketData.map(y=>new Date(y.time).toLocaleString()),...Array(r).fill("")],u=ut.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId);e&&u.dataZoom&&u.dataZoom.forEach(y=>{y.start=e.start,y.end=e.end}),u.xAxis.forEach(y=>{y.data=p,y.boundaryGap=!1});const v=q.buildCandlestickSeries(this.marketData,this.options),f={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}};v.data=[...Array(r).fill(f),...v.data,...Array(r).fill(f)];const m=[...Array(r).fill(null),...this.marketData,...Array(r).fill(null)],d=q.buildIndicatorSeries(this.indicators,this.timeToIndex,u.paneLayout,p.length,r,m),x=vt.build(u,this.options,this.toggleIndicator.bind(this),this.isMainCollapsed,this.maximizedPaneId),S=new Map;this.drawings.forEach(y=>{const c=y.paneIndex||0;S.has(c)||S.set(c,[]),S.get(c).push(y)});const I=[];S.forEach((y,c)=>{I.push({type:"custom",name:`drawings-pane-${c}`,xAxisIndex:c,yAxisIndex:c,clip:!0,renderItem:(l,b)=>{const h=y[l.dataIndex];if(!h)return;const C=h.points[0],T=h.points[1];if(!C||!T)return;const g=b.coord([C.timeIndex,C.value]),w=b.coord([T.timeIndex,T.value]),z=h.id===this.selectedDrawingId;if(h.type==="line")return{type:"group",children:[{type:"line",name:"line",shape:{x1:g[0],y1:g[1],x2:w[0],y2:w[1]},style:{stroke:h.style?.color||"#3b82f6",lineWidth:h.style?.lineWidth||2}},{type:"circle",name:"point-start",shape:{cx:g[0],cy:g[1],r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0}},{type:"circle",name:"point-end",shape:{cx:w[0],cy:w[1],r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0}}]};if(h.type==="fibonacci"){const O=g[0],W=g[1],P=w[0],M=w[1],Z=Math.min(O,P),N=Math.max(O,P),A=N-Z,j=M-W,H=[0,.236,.382,.5,.618,.786,1],R=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"],K=[];K.push({type:"line",name:"line",shape:{x1:O,y1:W,x2:P,y2:M},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}}),K.push({type:"circle",name:"point-start",shape:{cx:O,cy:W,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100}),K.push({type:"circle",name:"point-end",shape:{cx:P,cy:M,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100}),H.forEach((Q,Y)=>{const X=M-j*Q,et=R[Y%R.length];K.push({type:"line",name:"fib-line",shape:{x1:Z,y1:X,x2:N,y2:X},style:{stroke:et,lineWidth:1},silent:!0});const rt=h.points[0].value,it=h.points[1].value,lt=it-rt,ht=it-lt*Q;if(K.push({type:"text",style:{text:`${Q} (${ht.toFixed(2)})`,x:Z+5,y:X-10,fill:et,fontSize:10},silent:!0}),Y<H.length-1){const dt=H[Y+1],st=M-j*dt,ct=Math.abs(st-X),pt=Math.min(X,st);K.push({type:"rect",shape:{x:Z,y:pt,width:A,height:ct},style:{fill:R[(Y+1)%R.length],opacity:.1},silent:!0})}});const gt=[],at=[];return H.forEach((Q,Y)=>{const X=M-j*Q,et=R[Y%R.length];at.push({type:"line",shape:{x1:Z,y1:X,x2:N,y2:X},style:{stroke:et,lineWidth:1},silent:!0});const rt=h.points[0].value,it=h.points[1].value,lt=it-rt,ht=it-lt*Q;if(at.push({type:"text",style:{text:`${Q} (${ht.toFixed(2)})`,x:Z+5,y:X-10,fill:et,fontSize:10},silent:!0}),Y<H.length-1){const dt=H[Y+1],st=M-j*dt,ct=Math.abs(st-X),pt=Math.min(X,st);gt.push({type:"rect",name:"line",shape:{x:Z,y:pt,width:A,height:ct},style:{fill:R[(Y+1)%R.length],opacity:.1}})}}),{type:"group",children:[...gt,...at,{type:"line",name:"line",shape:{x1:O,y1:W,x2:P,y2:M},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}},{type:"circle",name:"point-start",shape:{cx:O,cy:W,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100},{type:"circle",name:"point-end",shape:{cx:P,cy:M,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100}]}}},data:y.map(l=>[l.points[0].timeIndex,l.points[0].value,l.points[1].timeIndex,l.points[1].value]),z:100,silent:!1})});const L=y=>{const c=wt.format(y,this.options),l=this.options.databox?.position;return l==="left"?(this.leftSidebar.innerHTML=c,""):l==="right"?(this.rightSidebar.innerHTML=c,""):this.options.databox?`<div style="min-width: 200px;">${c}</div>`:""},D={backgroundColor:this.options.backgroundColor,animation:!1,legend:{show:!1},tooltip:{show:!0,showContent:!!this.options.databox,trigger:"axis",axisPointer:{type:"cross",label:{backgroundColor:"#475569"}},backgroundColor:"rgba(30, 41, 59, 0.9)",borderWidth:1,borderColor:"#334155",padding:10,textStyle:{color:"#fff",fontFamily:this.options.fontFamily||"sans-serif"},formatter:L,extraCssText:t!=="floating"&&t!==void 0?"display: none !important;":void 0,position:(y,c,l,b,h)=>{if(this.options.databox?.position==="floating"){const C={top:10};return C[["left","right"][+(y[0]<h.viewSize[0]/2)]]=30,C}return null}},axisPointer:{link:{xAxisIndex:"all"},label:{backgroundColor:"#475569"}},graphic:x,grid:u.grid,xAxis:u.xAxis,yAxis:u.yAxis,dataZoom:u.dataZoom,series:[v,...d,...I]};this.chart.setOption(D,!0)}}var Gt=Object.defineProperty,$t=(a,e,t)=>e in a?Gt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,tt=(a,e,t)=>($t(a,typeof e!="symbol"?e+"":e,t),t);class nt{constructor(e){tt(this,"id"),tt(this,"name"),tt(this,"icon"),tt(this,"context"),tt(this,"eventListeners",[]),this.id=e.id,this.name=e.name,this.icon=e.icon}init(e){this.context=e,this.onInit()}onInit(){}activate(){this.onActivate(),this.context.events.emit("plugin:activated",this.id)}onActivate(){}deactivate(){this.onDeactivate(),this.context.events.emit("plugin:deactivated",this.id)}onDeactivate(){}destroy(){this.removeAllListeners(),this.onDestroy()}onDestroy(){}on(e,t){this.context.events.on(e,t),this.eventListeners.push({event:e,handler:t})}off(e,t){this.context.events.off(e,t),this.eventListeners=this.eventListeners.filter(i=>i.event!==e||i.handler!==t)}removeAllListeners(){this.eventListeners.forEach(({event:e,handler:t})=>{this.context.events.off(e,t)}),this.eventListeners=[]}get chart(){return this.context.getChart()}get marketData(){return this.context.getMarketData()}}var Nt=Object.defineProperty,Ft=(a,e,t)=>e in a?Nt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,G=(a,e,t)=>(Ft(a,typeof e!="symbol"?e+"":e,t),t);class Ot extends nt{constructor(e){super({id:"measure",name:e?.name||"Measure",icon:e?.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H680v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160H160v320Zm120-160h80-80Zm160 0h80-80Zm160 0h80-80Zm-120 0Z"/></svg>'}),G(this,"zr"),G(this,"state","idle"),G(this,"startPoint",null),G(this,"endPoint",null),G(this,"group",null),G(this,"rect",null),G(this,"labelRect",null),G(this,"labelText",null),G(this,"lineV",null),G(this,"lineH",null),G(this,"arrowStart",null),G(this,"arrowEnd",null),G(this,"onMouseDown",()=>{this.state==="finished"&&this.removeGraphic()}),G(this,"onChartInteraction",()=>{this.group&&this.removeGraphic()}),G(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.context.disableTools(),this.enableClearListeners())}),G(this,"clearHandlers",{}),G(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}enableClearListeners(){const e=()=>{this.removeGraphic()};setTimeout(()=>{this.zr.on("click",e)},10),this.zr.on("mousedown",this.onMouseDown),this.context.events.on("chart:dataZoom",this.onChartInteraction),this.clearHandlers={click:e,mousedown:this.onMouseDown,dataZoom:this.onChartInteraction}}disableClearListeners(){this.clearHandlers.click&&this.zr.off("click",this.clearHandlers.click),this.clearHandlers.mousedown&&this.zr.off("mousedown",this.clearHandlers.mousedown),this.clearHandlers.dataZoom&&this.context.events.off("chart:dataZoom",this.clearHandlers.dataZoom),this.clearHandlers={}}initGraphic(){this.group||(this.group=new E.graphic.Group,this.rect=new E.graphic.Rect({shape:{x:0,y:0,width:0,height:0},style:{fill:"rgba(0,0,0,0)",stroke:"transparent",lineWidth:0},z:100}),this.lineV=new E.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.lineH=new E.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.arrowStart=new E.graphic.Polygon({shape:{points:[[0,0],[-5,10],[5,10]]},style:{fill:"#fff"},z:102}),this.arrowEnd=new E.graphic.Polygon({shape:{points:[[0,0],[-5,-10],[5,-10]]},style:{fill:"#fff"},z:102}),this.labelRect=new E.graphic.Rect({shape:{x:0,y:0,width:0,height:0,r:4},style:{fill:"transparent",stroke:"transparent",lineWidth:0,shadowBlur:5,shadowColor:"rgba(0,0,0,0.3)"},z:102}),this.labelText=new E.graphic.Text({style:{x:0,y:0,text:"",fill:"#fff",font:"12px sans-serif",align:"center",verticalAlign:"middle"},z:103}),this.group.add(this.rect),this.group.add(this.lineV),this.group.add(this.lineH),this.group.add(this.arrowStart),this.group.add(this.arrowEnd),this.group.add(this.labelRect),this.group.add(this.labelText),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint,n=this.context.coordinateConversion.pixelToData({x:e,y:t}),o=this.context.coordinateConversion.pixelToData({x:i,y:s});if(!n||!o)return;const r=Math.round(n.timeIndex),p=Math.round(o.timeIndex),u=n.value,v=o.value,f=p-r,m=v-u,d=m/u*100,x=m>=0,S=x?"rgba(33, 150, 243, 0.2)":"rgba(236, 0, 0, 0.2)",I=x?"#2196F3":"#ec0000";this.rect.setShape({x:Math.min(e,i),y:Math.min(t,s),width:Math.abs(i-e),height:Math.abs(s-t)}),this.rect.setStyle({fill:S});const L=(e+i)/2,D=(t+s)/2;this.lineV.setShape({x1:L,y1:t,x2:L,y2:s}),this.lineV.setStyle({stroke:I}),this.lineH.setShape({x1:e,y1:D,x2:i,y2:D}),this.lineH.setStyle({stroke:I});const y=Math.min(t,s),c=Math.max(t,s);this.arrowStart.setStyle({fill:"none"}),this.arrowEnd.setStyle({fill:"none"}),x?(this.arrowStart.setShape({points:[[L,y],[L-4,y+6],[L+4,y+6]]}),this.arrowStart.setStyle({fill:I})):(this.arrowEnd.setShape({points:[[L,c],[L-4,c-6],[L+4,c-6]]}),this.arrowEnd.setStyle({fill:I}));const l=[`${m.toFixed(2)} (${d.toFixed(2)}%)`,`${f} bars, ${(f*0).toFixed(0)}d`].join(`
37
+ `),b=140,h=40,C=Math.max(t,s),T=Math.min(t,s);let g=(e+i)/2-b/2,w=C+10;const z=this.chart.getHeight();w+h>z&&(w=T-h-10),this.labelRect.setShape({x:g,y:w,width:b,height:h}),this.labelRect.setStyle({fill:"#1e293b",stroke:I,lineWidth:1}),this.labelText.setStyle({x:g+b/2,y:w+h/2,text:l,fill:"#fff"})}}var Wt=Object.defineProperty,Ht=(a,e,t)=>e in a?Wt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,F=(a,e,t)=>(Ht(a,typeof e!="symbol"?e+"":e,t),t);class jt extends nt{constructor(e){super({id:"trend-line",name:e?.name||"Trend Line",icon:e?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2" /></svg>'}),F(this,"zr"),F(this,"state","idle"),F(this,"startPoint",null),F(this,"endPoint",null),F(this,"group",null),F(this,"line",null),F(this,"startCircle",null),F(this,"endCircle",null),F(this,"onMouseDown",()=>{}),F(this,"onChartInteraction",()=>{}),F(this,"onClick",t=>{if(this.state==="idle")this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),s=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(i&&s){const n=i.paneIndex||0;this.context.addDrawing({id:`line-${Date.now()}`,type:"line",points:[i,s],paneIndex:n,style:{color:"#3b82f6",lineWidth:2}})}}this.removeGraphic(),this.context.disableTools()}}),F(this,"clearHandlers",{}),F(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}saveDataCoordinates(){}updateGraphicFromData(){}enableClearListeners(){}disableClearListeners(){}initGraphic(){this.group||(this.group=new E.graphic.Group,this.line=new E.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#3b82f6",lineWidth:2},z:100}),this.startCircle=new E.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.endCircle=new E.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint;this.line.setShape({x1:e,y1:t,x2:i,y2:s}),this.startCircle.setShape({cx:e,cy:t}),this.endCircle.setShape({cx:i,cy:s})}}var Rt=Object.defineProperty,Xt=(a,e,t)=>e in a?Rt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,V=(a,e,t)=>(Xt(a,typeof e!="symbol"?e+"":e,t),t);class Bt extends nt{constructor(e={}){super({id:"fibonacci-tool",name:e.name||"Fibonacci Retracement",icon:e.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Z"/></svg>'}),V(this,"startPoint",null),V(this,"endPoint",null),V(this,"state","idle"),V(this,"graphicGroup",null),V(this,"levels",[0,.236,.382,.5,.618,.786,1]),V(this,"colors",["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"]),V(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),V(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const e=this.context.getChart().getZr();e.on("click",this.onClick),e.on("mousemove",this.onMouseMove)}unbindEvents(){const e=this.context.getChart().getZr();e.off("click",this.onClick),e.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new E.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const e=this.startPoint[0],t=this.startPoint[1],i=this.endPoint[0],s=this.endPoint[1],n=new E.graphic.Line({shape:{x1:e,y1:t,x2:i,y2:s},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]},silent:!0});this.graphicGroup.add(n);const o=Math.min(e,i),r=Math.max(e,i),p=r-o,u=s-t;this.levels.forEach((v,f)=>{const m=s-u*v,d=this.colors[f%this.colors.length],x=new E.graphic.Line({shape:{x1:o,y1:m,x2:r,y2:m},style:{stroke:d,lineWidth:1},silent:!0});if(this.graphicGroup.add(x),f<this.levels.length-1){const S=this.levels[f+1],I=s-u*S,L=Math.abs(I-m),D=Math.min(m,I),y=new E.graphic.Rect({shape:{x:o,y:D,width:p,height:L},style:{fill:this.colors[(f+1)%this.colors.length],opacity:.1},silent:!0});this.graphicGroup.add(y)}})}saveDrawing(){if(!this.startPoint||!this.endPoint)return;const e=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),t=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(e&&t){const i=e.paneIndex||0;this.context.addDrawing({id:`fib-${Date.now()}`,type:"fibonacci",points:[e,t],paneIndex:i,style:{color:"#3b82f6",lineWidth:1}})}}}B.AbstractPlugin=nt,B.FibonacciTool=Bt,B.LineTool=jt,B.MeasureTool=Ot,B.QFChart=Zt});
@@ -14,24 +14,24 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import*as D from"echarts";var pt=Object.defineProperty,ut=(a,e,t)=>e in a?pt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,q=(a,e,t)=>(ut(a,typeof e!="symbol"?e+"":e,t),t);class gt{constructor(e,t,i,s={}){q(this,"id"),q(this,"plots"),q(this,"paneIndex"),q(this,"height"),q(this,"collapsed"),q(this,"titleColor"),q(this,"controls"),this.id=e,this.plots=t,this.paneIndex=i,this.height=s.height,this.collapsed=s.collapsed||!1,this.titleColor=s.titleColor,this.controls=s.controls}toggleCollapse(){this.collapsed=!this.collapsed}isVisible(){return!this.collapsed}updateData(e){Object.keys(e).forEach(t=>{if(!this.plots[t])this.plots[t]=e[t];else{const i=this.plots[t],s=e[t];s.options&&(i.options={...i.options,...s.options});const n=new Map;i.data.forEach(o=>{n.set(o.time,o)}),s.data.forEach(o=>{n.set(o.time,o)}),i.data=Array.from(n.values()).sort((o,h)=>o.time-h.time)}})}}class ct{static calculate(e,t,i,s=!1,n=null){let o=0;e>0&&(o=1/e*100);const h=Array.from(t.values()).map(m=>m.paneIndex).filter(m=>m>0).sort((m,k)=>m-k).filter((m,k,z)=>z.indexOf(m)===k),p=h.length>0,d=i.dataZoom?.visible??!0,b=i.dataZoom?.position??"top",u=i.dataZoom?.height??6,l=i.dataZoom?.start??0,v=i.dataZoom?.end??100;let g=8,P=92,S=-1;if(n)if(n==="main")S=0;else{const m=t.get(n);m&&(S=m.paneIndex)}if(S!==-1){const m=[],k=[],z=[],O=[],N=i.dataZoom?.start??50,w=i.dataZoom?.end??100;O.push({type:"inside",xAxisIndex:"all",start:N,end:w});const E=p?Math.max(...h):0,Y=[];for(let F=0;F<=E;F++){const T=F===S;if(m.push({left:"10%",right:"10%",top:T?"5%":"0%",height:T?"90%":"0%",show:T,containLabel:!1}),k.push({type:"category",gridIndex:F,data:[],show:T,axisLabel:{show:T,color:"#94a3b8",fontFamily:i.fontFamily},axisLine:{show:T,lineStyle:{color:"#334155"}},splitLine:{show:T,lineStyle:{color:"#334155",opacity:.5}}}),z.push({position:"right",gridIndex:F,show:T,scale:!0,axisLabel:{show:T,color:"#94a3b8",fontFamily:i.fontFamily},splitLine:{show:T,lineStyle:{color:"#334155",opacity:.5}}}),F>0){const W=Array.from(t.values()).find(B=>B.paneIndex===F);W&&Y.push({index:F,height:T?90:0,top:T?5:0,isCollapsed:!1,indicatorId:W.id,titleColor:W.titleColor,controls:W.controls})}}return{grid:m,xAxis:k,yAxis:z,dataZoom:O,paneLayout:Y,mainPaneHeight:S===0?90:0,mainPaneTop:S===0?5:0,pixelToPercent:o}}d?b==="top"?(g=u+4,P=95):(P=100-u-2,g=8):(g=5,P=95);let f=5;e>0&&(f=20/e*100);let r=75,c=[];if(p){const m=h.map(w=>{const E=Array.from(t.values()).find(Y=>Y.paneIndex===w);return{index:w,requestedHeight:E?.height,isCollapsed:E?.collapsed??!1,indicatorId:E?.id,titleColor:E?.titleColor,controls:E?.controls}}).map(w=>({...w,height:w.isCollapsed?3:w.requestedHeight!==void 0?w.requestedHeight:15})),k=m.reduce((w,E)=>w+E.height,0),z=m.length*f,O=k+z;r=P-g-O,s?r=3:r<20&&(r=Math.max(r,10));let N=g+r+f;c=m.map(w=>{const E={index:w.index,height:w.height,top:N,isCollapsed:w.isCollapsed,indicatorId:w.indicatorId,titleColor:w.titleColor,controls:w.controls};return N+=w.height+f,E})}else r=P-g,s&&(r=3);const y=[];y.push({left:"10%",right:"10%",top:g+"%",height:r+"%",containLabel:!1}),c.forEach(m=>{y.push({left:"10%",right:"10%",top:m.top+"%",height:m.height+"%",containLabel:!1})});const C=[0,...c.map((m,k)=>k+1)],x=[],M=c.length===0;x.push({type:"category",data:[],gridIndex:0,scale:!0,axisLine:{onZero:!1,show:!s,lineStyle:{color:"#334155"}},splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"},axisTick:{show:!s},axisPointer:{label:{show:M,fontSize:11,backgroundColor:"#475569"}}}),c.forEach((m,k)=>{const z=k===c.length-1;x.push({type:"category",gridIndex:k+1,data:[],axisLabel:{show:!1},axisLine:{show:!m.isCollapsed,lineStyle:{color:"#334155"}},axisTick:{show:!1},splitLine:{show:!1},axisPointer:{label:{show:z,fontSize:11,backgroundColor:"#475569"}}})});const $=[];$.push({position:"right",scale:!0,gridIndex:0,splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLine:{show:!s,lineStyle:{color:"#334155"}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"}}),c.forEach((m,k)=>{$.push({position:"right",scale:!0,gridIndex:k+1,splitLine:{show:!m.isCollapsed,lineStyle:{color:"#334155",opacity:.3}},axisLabel:{show:!m.isCollapsed,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",fontSize:10},axisLine:{show:!m.isCollapsed,lineStyle:{color:"#334155"}}})});const Z=[];return d&&(Z.push({type:"inside",xAxisIndex:C,start:l,end:v}),b==="top"?Z.push({type:"slider",xAxisIndex:C,top:"1%",height:u+"%",start:l,end:v,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1}):Z.push({type:"slider",xAxisIndex:C,bottom:"1%",height:u+"%",start:l,end:v,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1})),{grid:y,xAxis:x,yAxis:$,dataZoom:Z,paneLayout:c,mainPaneHeight:r,mainPaneTop:g,pixelToPercent:o}}static calculateMaximized(e,t,i){return{grid:[],xAxis:[],yAxis:[],dataZoom:[],paneLayout:[],mainPaneHeight:0,mainPaneTop:0,pixelToPercent:0}}}const lt=new Map;function ft(a,e="#00da3c",t="64px"){if(typeof document>"u")return"";const i=`${a}-${e}-${t}`;if(lt.has(i))return lt.get(i);const s=document.createElement("canvas"),n=s.getContext("2d");if(s.width=32,s.height=32,n){n.font="bold "+t+" Arial",n.fillStyle=e,n.textAlign="center",n.textBaseline="middle",n.fillText(a,16,16);const o=s.toDataURL("image/png");return lt.set(i,o),o}return""}class ht{static buildCandlestickSeries(e,t,i){const s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=e.map(h=>[h.open,h.close,h.low,h.high]);if(i&&i>o.length){const h=i-o.length;for(let p=0;p<h;p++)o.push(null)}return{type:"candlestick",name:t.title||"Market",data:o,itemStyle:{color:s,color0:n,borderColor:s,borderColor0:n},xAxisIndex:0,yAxisIndex:0,z:5}}static buildIndicatorSeries(e,t,i,s,n=0){const o=[];return e.forEach((h,p)=>{if(h.collapsed)return;let d=0,b=0;if(h.paneIndex>0){const u=i.findIndex(l=>l.index===h.paneIndex);u!==-1&&(d=u+1,b=u+1)}Object.keys(h.plots).forEach(u=>{const l=h.plots[u],v=`${p}::${u}`,g=new Array(s).fill(null),P=new Array(s).fill(null);switch(l.data.forEach(S=>{const f=t.get(S.time);if(f!==void 0){const r=S.options?.offset??l.options.offset??0,c=f+n+r;if(c>=0&&c<s){let y=S.value;const C=S.options?.color;(C===null||C==="na"||C==="NaN"||typeof C=="number"&&isNaN(C))&&(y=null),g[c]=y,P[c]=C||l.options.color}}}),l.options.style){case"histogram":case"columns":o.push({name:v,type:"bar",xAxisIndex:d,yAxisIndex:b,data:g.map((f,r)=>({value:f,itemStyle:P[r]?{color:P[r]}:void 0})),itemStyle:{color:l.options.color}});break;case"circles":case"cross":const S=g.map((f,r)=>{if(f===null)return null;const c=P[r]||l.options.color,y={value:[r,f],itemStyle:{color:c}};return l.options.style==="cross"?(y.symbol=`image://${ft("+",c,"24px")}`,y.symbolSize=16):(y.symbol="circle",y.symbolSize=6),y}).filter(f=>f!==null);o.push({name:v,type:"scatter",xAxisIndex:d,yAxisIndex:b,data:S});break;case"background":o.push({name:v,type:"custom",xAxisIndex:d,yAxisIndex:b,z:-10,renderItem:(f,r)=>{const c=r.value(0);if(isNaN(c))return;const y=r.coord([c,0]),C=r.size([1,0])[0],x=f.coordSys,M=y[0]-C/2,$=P[f.dataIndex],Z=r.value(1);if(!(!$||!Z))return{type:"rect",shape:{x:M,y:x.y,width:C,height:x.height},style:{fill:$,opacity:.3},silent:!0}},data:g.map((f,r)=>[r,f])});break;case"step":o.push({name:v,type:"custom",xAxisIndex:d,yAxisIndex:b,renderItem:(f,r)=>{const c=r.value(0),y=r.value(1);if(isNaN(y)||y===null)return;const C=r.coord([c,y]),x=r.size([1,0])[0];return{type:"line",shape:{x1:C[0]-x/2,y1:C[1],x2:C[0]+x/2,y2:C[1]},style:{stroke:P[f.dataIndex]||l.options.color,lineWidth:l.options.linewidth||1},silent:!0}},data:g.map((f,r)=>[r,f])});break;case"line":default:o.push({name:v,type:"custom",xAxisIndex:d,yAxisIndex:b,renderItem:(f,r)=>{const c=f.dataIndex;if(c===0)return;const y=r.value(1),C=r.value(2);if(y===null||isNaN(y)||C===null||isNaN(C))return;const x=r.coord([c-1,C]),M=r.coord([c,y]);return{type:"line",shape:{x1:x[0],y1:x[1],x2:M[0],y2:M[1]},style:{stroke:P[c]||l.options.color,lineWidth:l.options.linewidth||1},silent:!0}},data:g.map((f,r)=>[r,f,r>0?g[r-1]:null])});break}})}),o}}class yt{static build(e,t,i,s=!1,n=null){const o=[],h=e.pixelToPercent,p=e.mainPaneTop;if(!n||n==="main"){const d=10*h;if(o.push({type:"text",left:"8.5%",top:p+d+"%",z:10,style:{text:t.title||"Market",fill:t.titleColor||"#fff",font:`bold 16px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}}),t.watermark!==!1){const u=e.mainPaneTop+e.mainPaneHeight;o.push({type:"text",right:"11%",top:u-3+"%",z:10,style:{text:"QFChart",fill:t.fontColor||"#cbd5e1",font:"bold 16px sans-serif",opacity:.1},cursor:"pointer",onclick:()=>{window.open("https://quantforge.org","_blank")}})}const b=[];if(t.controls?.collapse&&b.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","collapse")},{type:"text",style:{text:s?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),t.controls?.maximize){const u=n==="main",l=t.controls?.collapse?25:0;b.push({type:"group",x:l,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","maximize")},{type:"text",style:{text:u?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}if(t.controls?.fullscreen){let u=0;t.controls?.collapse&&(u+=25),t.controls?.maximize&&(u+=25),b.push({type:"group",x:u,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","fullscreen")},{type:"text",style:{text:"\u26F6",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}b.length>0&&o.push({type:"group",right:"10.5%",top:p+"%",children:b})}return e.paneLayout.forEach(d=>{if(n&&d.indicatorId!==n)return;o.push({type:"text",left:"8.5%",top:d.top+10*h+"%",z:10,style:{text:d.indicatorId||"",fill:d.titleColor||"#fff",font:`bold 12px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}});const b=[];if(d.controls?.collapse&&b.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>d.indicatorId&&i(d.indicatorId,"collapse")},{type:"text",style:{text:d.isCollapsed?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),d.controls?.maximize){const u=n===d.indicatorId,l=d.controls?.collapse?25:0;b.push({type:"group",x:l,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>d.indicatorId&&i(d.indicatorId,"maximize")},{type:"text",style:{text:u?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}b.length>0&&o.push({type:"group",right:"10.5%",top:d.top+"%",children:b})}),o}}class xt{static format(e,t){if(!e||e.length===0)return"";const i=t.title||"Market",s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=t.fontFamily||"sans-serif",h=e[0].axisValue;let p=`<div style="font-weight: bold; margin-bottom: 5px; color: #cbd5e1; font-family: ${o};">${h}</div>`;const d=e.find(u=>u.seriesType==="candlestick"),b=e.filter(u=>u.seriesType!=="candlestick");if(d){const[u,l,v,g,P]=d.value,S=v>=l?s:n;p+=`
17
+ import*as T from"echarts";var ut=Object.defineProperty,gt=(a,e,t)=>e in a?ut(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,U=(a,e,t)=>(gt(a,typeof e!="symbol"?e+"":e,t),t);class ft{constructor(e,t,i,s={}){U(this,"id"),U(this,"plots"),U(this,"paneIndex"),U(this,"height"),U(this,"collapsed"),U(this,"titleColor"),U(this,"controls"),this.id=e,this.plots=t,this.paneIndex=i,this.height=s.height,this.collapsed=s.collapsed||!1,this.titleColor=s.titleColor,this.controls=s.controls}toggleCollapse(){this.collapsed=!this.collapsed}isVisible(){return!this.collapsed}updateData(e){Object.keys(e).forEach(t=>{if(!this.plots[t])this.plots[t]=e[t];else{const i=this.plots[t],s=e[t];s.options&&(i.options={...i.options,...s.options});const n=new Map;i.data.forEach(o=>{n.set(o.time,o)}),s.data.forEach(o=>{n.set(o.time,o)}),i.data=Array.from(n.values()).sort((o,r)=>o.time-r.time)}})}}class pt{static calculate(e,t,i,s=!1,n=null){let o=0;e>0&&(o=1/e*100);const r=Array.from(t.values()).map(g=>g.paneIndex).filter(g=>g>0).sort((g,w)=>g-w).filter((g,w,z)=>z.indexOf(g)===w),p=r.length>0,u=i.dataZoom?.visible??!0,v=i.dataZoom?.position??"top",f=i.dataZoom?.height??6,m=i.dataZoom?.start??0,d=i.dataZoom?.end??100;let x=8,S=92,k=-1;if(n)if(n==="main")k=0;else{const g=t.get(n);g&&(k=g.paneIndex)}if(k!==-1){const g=[],w=[],z=[],F=[],H=i.dataZoom?.start??50,I=i.dataZoom?.end??100;F.push({type:"inside",xAxisIndex:"all",start:H,end:I});const M=p?Math.max(...r):0,Z=[];for(let N=0;N<=M;N++){const A=N===k;if(g.push({left:"10%",right:"10%",top:A?"5%":"0%",height:A?"90%":"0%",show:A,containLabel:!1}),w.push({type:"category",gridIndex:N,data:[],show:A,axisLabel:{show:A,color:"#94a3b8",fontFamily:i.fontFamily},axisLine:{show:A,lineStyle:{color:"#334155"}},splitLine:{show:A,lineStyle:{color:"#334155",opacity:.5}}}),z.push({position:"right",gridIndex:N,show:A,scale:!0,axisLabel:{show:A,color:"#94a3b8",fontFamily:i.fontFamily},splitLine:{show:A,lineStyle:{color:"#334155",opacity:.5}}}),N>0){const R=Array.from(t.values()).find(O=>O.paneIndex===N);R&&Z.push({index:N,height:A?90:0,top:A?5:0,isCollapsed:!1,indicatorId:R.id,titleColor:R.titleColor,controls:R.controls})}}return{grid:g,xAxis:w,yAxis:z,dataZoom:F,paneLayout:Z,mainPaneHeight:k===0?90:0,mainPaneTop:k===0?5:0,pixelToPercent:o}}u?v==="top"?(x=f+4,S=95):(S=100-f-2,x=8):(x=5,S=95);let L=5;e>0&&(L=20/e*100);let D=75,y=[];if(p){const g=r.map(I=>{const M=Array.from(t.values()).find(Z=>Z.paneIndex===I);return{index:I,requestedHeight:M?.height,isCollapsed:M?.collapsed??!1,indicatorId:M?.id,titleColor:M?.titleColor,controls:M?.controls}}).map(I=>({...I,height:I.isCollapsed?3:I.requestedHeight!==void 0?I.requestedHeight:15})),w=g.reduce((I,M)=>I+M.height,0),z=g.length*L,F=w+z;D=S-x-F,s?D=3:D<20&&(D=Math.max(D,10));let H=x+D+L;y=g.map(I=>{const M={index:I.index,height:I.height,top:H,isCollapsed:I.isCollapsed,indicatorId:I.indicatorId,titleColor:I.titleColor,controls:I.controls};return H+=I.height+L,M})}else D=S-x,s&&(D=3);const c=[];c.push({left:"10%",right:"10%",top:x+"%",height:D+"%",containLabel:!1}),y.forEach(g=>{c.push({left:"10%",right:"10%",top:g.top+"%",height:g.height+"%",containLabel:!1})});const l=[0,...y.map((g,w)=>w+1)],b=[],h=y.length===0;b.push({type:"category",data:[],gridIndex:0,scale:!0,axisLine:{onZero:!1,show:!s,lineStyle:{color:"#334155"}},splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"},axisTick:{show:!s},axisPointer:{label:{show:h,fontSize:11,backgroundColor:"#475569"}}}),y.forEach((g,w)=>{const z=w===y.length-1;b.push({type:"category",gridIndex:w+1,data:[],axisLabel:{show:!1},axisLine:{show:!g.isCollapsed,lineStyle:{color:"#334155"}},axisTick:{show:!1},splitLine:{show:!1},axisPointer:{label:{show:z,fontSize:11,backgroundColor:"#475569"}}})});const C=[];C.push({position:"right",scale:!0,gridIndex:0,splitLine:{show:!s,lineStyle:{color:"#334155",opacity:.5}},axisLine:{show:!s,lineStyle:{color:"#334155"}},axisLabel:{show:!s,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"}}),y.forEach((g,w)=>{C.push({position:"right",scale:!0,gridIndex:w+1,splitLine:{show:!g.isCollapsed,lineStyle:{color:"#334155",opacity:.3}},axisLabel:{show:!g.isCollapsed,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",fontSize:10},axisLine:{show:!g.isCollapsed,lineStyle:{color:"#334155"}}})});const E=[];return u&&(E.push({type:"inside",xAxisIndex:l,start:m,end:d}),v==="top"?E.push({type:"slider",xAxisIndex:l,top:"1%",height:f+"%",start:m,end:d,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1}):E.push({type:"slider",xAxisIndex:l,bottom:"1%",height:f+"%",start:m,end:d,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1})),{grid:c,xAxis:b,yAxis:C,dataZoom:E,paneLayout:y,mainPaneHeight:D,mainPaneTop:x,pixelToPercent:o}}static calculateMaximized(e,t,i){return{grid:[],xAxis:[],yAxis:[],dataZoom:[],paneLayout:[],mainPaneHeight:0,mainPaneTop:0,pixelToPercent:0}}}const dt=new Map;function yt(a,e="#00da3c",t="64px"){if(typeof document>"u")return"";const i=`${a}-${e}-${t}`;if(dt.has(i))return dt.get(i);const s=document.createElement("canvas"),n=s.getContext("2d");if(s.width=32,s.height=32,n){n.font="bold "+t+" Arial",n.fillStyle=e,n.textAlign="center",n.textBaseline="middle",n.fillText(a,16,16);const o=s.toDataURL("image/png");return dt.set(i,o),o}return""}class V{static buildCandlestickSeries(e,t,i){const s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=e.map(r=>[r.open,r.close,r.low,r.high]);if(i&&i>o.length){const r=i-o.length;for(let p=0;p<r;p++)o.push(null)}return{type:"candlestick",name:t.title||"Market",data:o,itemStyle:{color:s,color0:n,borderColor:s,borderColor0:n},xAxisIndex:0,yAxisIndex:0,z:5}}static getShapeSymbol(e){switch(e){case"arrowdown":return"path://M12 24l-12-12h8v-12h8v12h8z";case"arrowup":return"path://M12 0l12 12h-8v12h-8v-12h-8z";case"circle":return"circle";case"cross":return"path://M11 2h2v9h9v2h-9v9h-2v-9h-9v-2h9z";case"diamond":return"diamond";case"flag":return"path://M6 2v20h2v-8h12l-2-6 2-6h-12z";case"labeldown":return"path://M4 2h16a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-6l-2 4l-2 -4h-6a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2z";case"labelup":return"path://M12 2l2 4h6a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-16a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h6z";case"square":return"rect";case"triangledown":return"path://M12 21l-10-18h20z";case"triangleup":return"triangle";case"xcross":return"path://M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z";default:return"circle"}}static getShapeRotation(e){return 0}static getShapeSize(e,t,i){if(t!==void 0&&i!==void 0)return[t,i];let s;switch(e){case"tiny":s=8;break;case"small":s=12;break;case"normal":case"auto":s=16;break;case"large":s=24;break;case"huge":s=32;break;default:s=16}return t!==void 0?[t,t]:i!==void 0?[i,i]:s}static getLabelConfig(e,t){switch(t){case"abovebar":return{position:"top",distance:5};case"belowbar":return{position:"bottom",distance:5};case"top":return{position:"bottom",distance:5};case"bottom":return{position:"top",distance:5};case"absolute":default:return e==="labelup"||e==="labeldown"?{position:"inside",distance:0}:{position:"top",distance:5}}}static buildIndicatorSeries(e,t,i,s,n=0,o){const r=[];return e.forEach((p,u)=>{if(p.collapsed)return;let v=0,f=0;if(p.paneIndex>0){const m=i.findIndex(d=>d.index===p.paneIndex);m!==-1&&(v=m+1,f=m+1)}Object.keys(p.plots).forEach(m=>{const d=p.plots[m],x=`${u}::${m}`,S=new Array(s).fill(null),k=new Array(s).fill(null),L=new Array(s).fill(null);switch(d.data.forEach(D=>{const y=t.get(D.time);if(y!==void 0){const c=D.options?.offset??d.options.offset??0,l=y+n+c;if(l>=0&&l<s){let b=D.value;const h=D.options?.color;(h===null||h==="na"||h==="NaN"||typeof h=="number"&&isNaN(h))&&(b=null),S[l]=b,k[l]=h||d.options.color,L[l]=D.options||{}}}}),d.options.style){case"histogram":case"columns":r.push({name:x,type:"bar",xAxisIndex:v,yAxisIndex:f,data:S.map((c,l)=>({value:c,itemStyle:k[l]?{color:k[l]}:void 0})),itemStyle:{color:d.options.color}});break;case"circles":case"cross":const D=S.map((c,l)=>{if(c===null)return null;const b=k[l]||d.options.color,h={value:[l,c],itemStyle:{color:b}};return d.options.style==="cross"?(h.symbol=`image://${yt("+",b,"24px")}`,h.symbolSize=16):(h.symbol="circle",h.symbolSize=6),h}).filter(c=>c!==null);r.push({name:x,type:"scatter",xAxisIndex:v,yAxisIndex:f,data:D});break;case"shape":const y=S.map((c,l)=>{const b=L[l]||{},h=d.options,C=b.location||h.location||"absolute";if(C!=="absolute"&&!c||c==null)return null;const E=b.color||h.color||"blue",g=b.shape||h.shape||"circle",w=b.size||h.size||"normal",z=b.text||h.text,F=b.textcolor||h.textcolor||"white",H=b.width||h.width,I=b.height||h.height;let M=c,Z=[0,0];C==="abovebar"?(o&&o[l]&&(M=o[l].high),Z=[0,"-150%"]):C==="belowbar"?(o&&o[l]&&(M=o[l].low),Z=[0,"150%"]):C==="top"?(M=c,Z=[0,0]):C==="bottom"&&(M=c,Z=[0,0]);const N=V.getShapeSymbol(g),A=V.getShapeSize(w,H,I),R=V.getShapeRotation(g);let O=A;g.includes("label")&&(Array.isArray(A)?O=[A[0]*2.5,A[1]*2.5]:O=A*2.5);const X=V.getLabelConfig(g,C);return{value:[l,M],symbol:N,symbolSize:O,symbolRotate:R,symbolOffset:Z,itemStyle:{color:E},label:{show:!!z,position:X.position,distance:X.distance,formatter:z,color:F,fontSize:10,fontWeight:"bold"}}}).filter(c=>c!==null);r.push({name:x,type:"scatter",xAxisIndex:v,yAxisIndex:f,data:y});break;case"background":r.push({name:x,type:"custom",xAxisIndex:v,yAxisIndex:f,z:-10,renderItem:(c,l)=>{const b=l.value(0);if(isNaN(b))return;const h=l.coord([b,0]),C=l.size([1,0])[0],E=c.coordSys,g=h[0]-C/2,w=k[c.dataIndex],z=l.value(1);if(!(!w||!z))return{type:"rect",shape:{x:g,y:E.y,width:C,height:E.height},style:{fill:w,opacity:.3},silent:!0}},data:S.map((c,l)=>[l,c])});break;case"step":r.push({name:x,type:"custom",xAxisIndex:v,yAxisIndex:f,renderItem:(c,l)=>{const b=l.value(0),h=l.value(1);if(isNaN(h)||h===null)return;const C=l.coord([b,h]),E=l.size([1,0])[0];return{type:"line",shape:{x1:C[0]-E/2,y1:C[1],x2:C[0]+E/2,y2:C[1]},style:{stroke:k[c.dataIndex]||d.options.color,lineWidth:d.options.linewidth||1},silent:!0}},data:S.map((c,l)=>[l,c])});break;case"line":default:r.push({name:x,type:"custom",xAxisIndex:v,yAxisIndex:f,renderItem:(c,l)=>{const b=c.dataIndex;if(b===0)return;const h=l.value(1),C=l.value(2);if(h===null||isNaN(h)||C===null||isNaN(C))return;const E=l.coord([b-1,C]),g=l.coord([b,h]);return{type:"line",shape:{x1:E[0],y1:E[1],x2:g[0],y2:g[1]},style:{stroke:k[b]||d.options.color,lineWidth:d.options.linewidth||1},silent:!0}},data:S.map((c,l)=>[l,c,l>0?S[l-1]:null])});break}})}),r}}class xt{static build(e,t,i,s=!1,n=null){const o=[],r=e.pixelToPercent,p=e.mainPaneTop;if(!n||n==="main"){const u=10*r;if(o.push({type:"text",left:"8.5%",top:p+u+"%",z:10,style:{text:t.title||"Market",fill:t.titleColor||"#fff",font:`bold 16px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}}),t.watermark!==!1){const f=e.mainPaneTop+e.mainPaneHeight;o.push({type:"text",right:"11%",top:f-3+"%",z:10,style:{text:"QFChart",fill:t.fontColor||"#cbd5e1",font:"bold 16px sans-serif",opacity:.1},cursor:"pointer",onclick:()=>{window.open("https://quantforge.org","_blank")}})}const v=[];if(t.controls?.collapse&&v.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","collapse")},{type:"text",style:{text:s?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),t.controls?.maximize){const f=n==="main",m=t.controls?.collapse?25:0;v.push({type:"group",x:m,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","maximize")},{type:"text",style:{text:f?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}if(t.controls?.fullscreen){let f=0;t.controls?.collapse&&(f+=25),t.controls?.maximize&&(f+=25),v.push({type:"group",x:f,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","fullscreen")},{type:"text",style:{text:"\u26F6",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}v.length>0&&o.push({type:"group",right:"10.5%",top:p+"%",children:v})}return e.paneLayout.forEach(u=>{if(n&&u.indicatorId!==n)return;o.push({type:"text",left:"8.5%",top:u.top+10*r+"%",z:10,style:{text:u.indicatorId||"",fill:u.titleColor||"#fff",font:`bold 12px ${t.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}});const v=[];if(u.controls?.collapse&&v.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>u.indicatorId&&i(u.indicatorId,"collapse")},{type:"text",style:{text:u.isCollapsed?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),u.controls?.maximize){const f=n===u.indicatorId,m=u.controls?.collapse?25:0;v.push({type:"group",x:m,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>u.indicatorId&&i(u.indicatorId,"maximize")},{type:"text",style:{text:f?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${t.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}v.length>0&&o.push({type:"group",right:"10.5%",top:u.top+"%",children:v})}),o}}class mt{static format(e,t){if(!e||e.length===0)return"";const i=t.title||"Market",s=t.upColor||"#00da3c",n=t.downColor||"#ec0000",o=t.fontFamily||"sans-serif",r=e[0].axisValue;let p=`<div style="font-weight: bold; margin-bottom: 5px; color: #cbd5e1; font-family: ${o};">${r}</div>`;const u=e.find(f=>f.seriesType==="candlestick"),v=e.filter(f=>f.seriesType!=="candlestick");if(u){const[f,m,d,x,S]=u.value,k=d>=m?s:n;p+=`
18
18
  <div style="margin-bottom: 8px; font-family: ${o};">
19
- <div style="display:flex; justify-content:space-between; color:${S}; font-weight:bold;">
19
+ <div style="display:flex; justify-content:space-between; color:${k}; font-weight:bold;">
20
20
  <span>${i}</span>
21
21
  </div>
22
22
  <div style="display: grid; grid-template-columns: auto auto; gap: 2px 15px; font-size: 0.9em; color: #cbd5e1;">
23
- <span>Open:</span> <span style="text-align: right; color: ${v>=l?s:n}">${l}</span>
24
- <span>High:</span> <span style="text-align: right; color: ${s}">${P}</span>
25
- <span>Low:</span> <span style="text-align: right; color: ${n}">${g}</span>
26
- <span>Close:</span> <span style="text-align: right; color: ${v>=l?s:n}">${v}</span>
23
+ <span>Open:</span> <span style="text-align: right; color: ${d>=m?s:n}">${m}</span>
24
+ <span>High:</span> <span style="text-align: right; color: ${s}">${S}</span>
25
+ <span>Low:</span> <span style="text-align: right; color: ${n}">${x}</span>
26
+ <span>Close:</span> <span style="text-align: right; color: ${d>=m?s:n}">${d}</span>
27
27
  </div>
28
28
  </div>
29
- `}if(b.length>0){p+='<div style="border-top: 1px solid #334155; margin: 5px 0; padding-top: 5px;"></div>';const u={};b.forEach(l=>{const v=l.seriesName.split("::"),g=v.length>1?v[0]:"Unknown",P=v.length>1?v[1]:l.seriesName;u[g]||(u[g]=[]),u[g].push({...l,displayName:P})}),Object.keys(u).forEach(l=>{p+=`
29
+ `}if(v.length>0){p+='<div style="border-top: 1px solid #334155; margin: 5px 0; padding-top: 5px;"></div>';const f={};v.forEach(m=>{const d=m.seriesName.split("::"),x=d.length>1?d[0]:"Unknown",S=d.length>1?d[1]:m.seriesName;f[x]||(f[x]=[]),f[x].push({...m,displayName:S})}),Object.keys(f).forEach(m=>{p+=`
30
30
  <div style="margin-top: 8px; font-family: ${o};">
31
- <div style="font-weight:bold; color: #fff; margin-bottom: 2px;">${l}</div>
32
- `,u[l].forEach(v=>{let g=v.value;if(Array.isArray(g)&&(g=g[1]),g==null)return;const P=typeof g=="number"?g.toLocaleString(void 0,{maximumFractionDigits:4}):g;p+=`
31
+ <div style="font-weight:bold; color: #fff; margin-bottom: 2px;">${m}</div>
32
+ `,f[m].forEach(d=>{let x=d.value;if(Array.isArray(x)&&(x=x[1]),x==null)return;const S=typeof x=="number"?x.toLocaleString(void 0,{maximumFractionDigits:4}):x;p+=`
33
33
  <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2px; padding-left: 8px;">
34
- <div>${v.marker} <span style="color: #cbd5e1;">${v.displayName}</span></div>
35
- <div style="font-size: 10px; color: #fff;padding-left:10px;">${P}</div>
36
- </div>`}),p+="</div>"})}return p}}var mt=Object.defineProperty,bt=(a,e,t)=>e in a?mt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,U=(a,e,t)=>(bt(a,typeof e!="symbol"?e+"":e,t),t);class vt{constructor(e,t){U(this,"plugins",new Map),U(this,"activePluginId",null),U(this,"context"),U(this,"toolbarContainer"),U(this,"tooltipElement",null),U(this,"hideTimeout",null),this.context=e,this.toolbarContainer=t,this.createTooltip(),this.renderToolbar()}createTooltip(){this.tooltipElement=document.createElement("div"),Object.assign(this.tooltipElement.style,{position:"fixed",display:"none",backgroundColor:"#1e293b",color:"#e2e8f0",padding:"6px 10px",borderRadius:"6px",fontSize:"13px",lineHeight:"1.4",fontWeight:"500",border:"1px solid #334155",zIndex:"9999",pointerEvents:"none",whiteSpace:"nowrap",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15)",fontFamily:this.context.getOptions().fontFamily||"sans-serif",transition:"opacity 0.15s ease-in-out, transform 0.15s ease-in-out",opacity:"0",transform:"translateX(-5px)"}),document.body.appendChild(this.tooltipElement)}destroy(){this.tooltipElement&&this.tooltipElement.parentNode&&this.tooltipElement.parentNode.removeChild(this.tooltipElement),this.tooltipElement=null}showTooltip(e,t){if(!this.tooltipElement)return;this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null);const i=e.getBoundingClientRect();this.tooltipElement.textContent=t,this.tooltipElement.style.display="block";const s=this.tooltipElement.getBoundingClientRect(),n=i.top+(i.height-s.height)/2,o=i.right+10;this.tooltipElement.style.top=`${n}px`,this.tooltipElement.style.left=`${o}px`,requestAnimationFrame(()=>{this.tooltipElement&&(this.tooltipElement.style.opacity="1",this.tooltipElement.style.transform="translateX(0)")})}hideTooltip(){this.tooltipElement&&(this.tooltipElement.style.opacity="0",this.tooltipElement.style.transform="translateX(-5px)",this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(()=>{this.tooltipElement&&(this.tooltipElement.style.display="none"),this.hideTimeout=null},150))}register(e){if(this.plugins.has(e.id)){console.warn(`Plugin with id ${e.id} is already registered.`);return}this.plugins.set(e.id,e),e.init(this.context),this.addButton(e)}unregister(e){const t=this.plugins.get(e);t&&(this.activePluginId===e&&this.deactivatePlugin(),t.destroy?.(),this.plugins.delete(e),this.removeButton(e))}activatePlugin(e){if(this.activePluginId===e){this.deactivatePlugin();return}this.activePluginId&&this.deactivatePlugin();const t=this.plugins.get(e);t&&(this.activePluginId=e,this.setButtonActive(e,!0),t.activate?.())}deactivatePlugin(){this.activePluginId&&(this.plugins.get(this.activePluginId)?.deactivate?.(),this.setButtonActive(this.activePluginId,!1),this.activePluginId=null)}renderToolbar(){this.toolbarContainer.innerHTML="",this.toolbarContainer.style.display="flex",this.toolbarContainer.style.flexDirection="column",this.toolbarContainer.style.width="40px",this.toolbarContainer.style.backgroundColor=this.context.getOptions().backgroundColor||"#1e293b",this.toolbarContainer.style.borderRight="1px solid #334155",this.toolbarContainer.style.padding="5px",this.toolbarContainer.style.boxSizing="border-box",this.toolbarContainer.style.gap="5px",this.toolbarContainer.style.flexShrink="0"}addButton(e){const t=document.createElement("button");t.id=`qfchart-plugin-btn-${e.id}`,t.style.width="30px",t.style.height="30px",t.style.padding="4px",t.style.border="1px solid transparent",t.style.borderRadius="4px",t.style.backgroundColor="transparent",t.style.cursor="pointer",t.style.color=this.context.getOptions().fontColor||"#cbd5e1",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",e.icon?t.innerHTML=e.icon:t.innerText=(e.name||e.id).substring(0,2).toUpperCase(),t.addEventListener("mouseenter",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="rgba(255, 255, 255, 0.1)"),this.showTooltip(t,e.name||e.id)}),t.addEventListener("mouseleave",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="transparent"),this.hideTooltip()}),t.onclick=()=>this.activatePlugin(e.id),this.toolbarContainer.appendChild(t)}removeButton(e){const t=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);t&&t.remove()}setButtonActive(e,t){const i=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);i&&(t?(i.style.backgroundColor="#2563eb",i.style.color="#ffffff"):(i.style.backgroundColor="transparent",i.style.color=this.context.getOptions().fontColor||"#cbd5e1"))}}var wt=Object.defineProperty,Ct=(a,e,t)=>e in a?wt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,A=(a,e,t)=>(Ct(a,typeof e!="symbol"?e+"":e,t),t);class It{constructor(e){A(this,"context"),A(this,"isEditing",!1),A(this,"currentDrawing",null),A(this,"editingPointIndex",null),A(this,"zr"),A(this,"editGroup",null),A(this,"editLine",null),A(this,"editStartPoint",null),A(this,"editEndPoint",null),A(this,"isMovingShape",!1),A(this,"dragStart",null),A(this,"initialPixelPoints",[]),A(this,"onDrawingMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.isMovingShape=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.dragStart={x:t.x,y:t.y},this.initialPixelPoints=i.points.map(s=>{const n=this.context.coordinateConversion.dataToPixel(s);return n?{x:n.x,y:n.y}:{x:0,y:0}}),this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),A(this,"onPointMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.editingPointIndex=t.pointIndex,this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),A(this,"onMouseMove",t=>{if(!this.isEditing||!this.currentDrawing)return;const i=t.offsetX,s=t.offsetY;if(this.isMovingShape&&this.dragStart){const n=i-this.dragStart.x,o=s-this.dragStart.y,h={x:this.initialPixelPoints[0].x+n,y:this.initialPixelPoints[0].y+o},p={x:this.initialPixelPoints[1].x+n,y:this.initialPixelPoints[1].y+o};this.editLine.setShape({x1:h.x,y1:h.y,x2:p.x,y2:p.y}),this.editStartPoint.setShape({cx:h.x,cy:h.y}),this.editEndPoint.setShape({cx:p.x,cy:p.y})}else this.editingPointIndex!==null&&(this.editingPointIndex===0?(this.editLine.setShape({x1:i,y1:s}),this.editStartPoint.setShape({cx:i,cy:s})):(this.editLine.setShape({x2:i,y2:s}),this.editEndPoint.setShape({cx:i,cy:s})))}),A(this,"onMouseUp",t=>{this.isEditing&&this.finishEditing(t.offsetX,t.offsetY)}),this.context=e,this.zr=this.context.getChart().getZr(),this.bindEvents()}bindEvents(){this.context.events.on("drawing:point:mousedown",this.onPointMouseDown),this.context.events.on("drawing:mousedown",this.onDrawingMouseDown)}createEditGraphic(){if(!this.currentDrawing)return;this.editGroup=new D.graphic.Group;const e=this.currentDrawing.points[0],t=this.currentDrawing.points[1],i=this.context.coordinateConversion.dataToPixel(e),s=this.context.coordinateConversion.dataToPixel(t);!i||!s||(this.editLine=new D.graphic.Line({shape:{x1:i.x,y1:i.y,x2:s.x,y2:s.y},style:{stroke:this.currentDrawing.style?.color||"#3b82f6",lineWidth:this.currentDrawing.style?.lineWidth||2,lineDash:[4,4]},silent:!0}),this.editStartPoint=new D.graphic.Circle({shape:{cx:i.x,cy:i.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editEndPoint=new D.graphic.Circle({shape:{cx:s.x,cy:s.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editGroup.add(this.editLine),this.editGroup.add(this.editStartPoint),this.editGroup.add(this.editEndPoint),this.zr.add(this.editGroup))}finishEditing(e,t){if(this.currentDrawing){if(this.isMovingShape&&this.dragStart){const i=e-this.dragStart.x,s=t-this.dragStart.y,n=this.initialPixelPoints.map((o,h)=>{const p=o.x+i,d=o.y+s;return this.context.coordinateConversion.pixelToData({x:p,y:d})});n.every(o=>o!==null)&&n[0]&&n[1]&&(this.currentDrawing.points[0]=n[0],this.currentDrawing.points[1]=n[1],n[0].paneIndex!==void 0&&(this.currentDrawing.paneIndex=n[0].paneIndex),this.context.updateDrawing(this.currentDrawing))}else if(this.editingPointIndex!==null){const i=this.context.coordinateConversion.pixelToData({x:e,y:t});i&&(this.currentDrawing.points[this.editingPointIndex]=i,this.editingPointIndex===0&&i.paneIndex!==void 0&&(this.currentDrawing.paneIndex=i.paneIndex),this.context.updateDrawing(this.currentDrawing))}this.isEditing=!1,this.isMovingShape=!1,this.dragStart=null,this.initialPixelPoints=[],this.currentDrawing=null,this.editingPointIndex=null,this.editGroup&&(this.zr.remove(this.editGroup),this.editGroup=null),this.zr.off("mousemove",this.onMouseMove),this.zr.off("mouseup",this.onMouseUp),this.context.unlockChart()}}}var kt=Object.defineProperty,Pt=(a,e,t)=>e in a?kt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,St=(a,e,t)=>(Pt(a,typeof e!="symbol"?e+"":e,t),t);class Dt{constructor(){St(this,"handlers",new Map)}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const i=this.handlers.get(e);i&&i.delete(t)}emit(e,t){const i=this.handlers.get(e);i&&i.forEach(s=>{try{s(t)}catch(n){console.error(`Error in EventBus handler for ${e}:`,n)}})}clear(){this.handlers.clear()}}var Et=Object.defineProperty,Mt=(a,e,t)=>e in a?Et(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,I=(a,e,t)=>(Mt(a,typeof e!="symbol"?e+"":e,t),t);class zt{constructor(e,t={}){I(this,"chart"),I(this,"options"),I(this,"marketData",[]),I(this,"indicators",new Map),I(this,"timeToIndex",new Map),I(this,"pluginManager"),I(this,"drawingEditor"),I(this,"events",new Dt),I(this,"isMainCollapsed",!1),I(this,"maximizedPaneId",null),I(this,"selectedDrawingId",null),I(this,"drawings",[]),I(this,"coordinateConversion",{pixelToData:n=>{const o=this.chart.getOption();if(!o||!o.grid)return null;const h=o.grid.length;for(let p=0;p<h;p++)if(this.chart.containPixel({gridIndex:p},[n.x,n.y])){this.chart.convertFromPixel({seriesIndex:p},[n.x,n.y]);const d=this.chart.convertFromPixel({gridIndex:p},[n.x,n.y]);if(d)return{timeIndex:Math.round(d[0]),value:d[1],paneIndex:p}}return null},dataToPixel:n=>{const o=n.paneIndex||0,h=this.chart.convertToPixel({gridIndex:o},[n.timeIndex,n.value]);return h?{x:h[0],y:h[1]}:null}}),I(this,"upColor","#00da3c"),I(this,"downColor","#ec0000"),I(this,"defaultPadding",0),I(this,"padding"),I(this,"dataIndexOffset",0),I(this,"rootContainer"),I(this,"layoutContainer"),I(this,"toolbarContainer"),I(this,"leftSidebar"),I(this,"rightSidebar"),I(this,"chartContainer"),I(this,"onKeyDown",n=>{(n.key==="Delete"||n.key==="Backspace")&&this.selectedDrawingId&&(this.removeDrawing(this.selectedDrawingId),this.selectedDrawingId=null,this.render())}),I(this,"onFullscreenChange",()=>{this.render()}),I(this,"isLocked",!1),I(this,"lockedState",null),this.rootContainer=e,this.options={title:"Market",height:"600px",backgroundColor:"#1e293b",upColor:"#00da3c",downColor:"#ec0000",fontColor:"#cbd5e1",fontFamily:"sans-serif",padding:.01,dataZoom:{visible:!0,position:"top",height:6},layout:{mainPaneHeight:"50%",gap:13},watermark:!0,...t},this.options.upColor&&(this.upColor=this.options.upColor),this.options.downColor&&(this.downColor=this.options.downColor),this.padding=this.options.padding!==void 0?this.options.padding:this.defaultPadding,this.options.height&&(typeof this.options.height=="number"?this.rootContainer.style.height=`${this.options.height}px`:this.rootContainer.style.height=this.options.height),this.rootContainer.innerHTML="",this.layoutContainer=document.createElement("div"),this.layoutContainer.style.display="flex",this.layoutContainer.style.width="100%",this.layoutContainer.style.height="100%",this.layoutContainer.style.overflow="hidden",this.rootContainer.appendChild(this.layoutContainer),this.leftSidebar=document.createElement("div"),this.leftSidebar.style.display="none",this.leftSidebar.style.width="250px",this.leftSidebar.style.flexShrink="0",this.leftSidebar.style.overflowY="auto",this.leftSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.leftSidebar.style.borderRight="1px solid #334155",this.leftSidebar.style.padding="10px",this.leftSidebar.style.boxSizing="border-box",this.leftSidebar.style.color="#cbd5e1",this.leftSidebar.style.fontSize="12px",this.leftSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.leftSidebar),this.toolbarContainer=document.createElement("div"),this.layoutContainer.appendChild(this.toolbarContainer),this.chartContainer=document.createElement("div"),this.chartContainer.style.flexGrow="1",this.chartContainer.style.height="100%",this.chartContainer.style.overflow="hidden",this.layoutContainer.appendChild(this.chartContainer),this.rightSidebar=document.createElement("div"),this.rightSidebar.style.display="none",this.rightSidebar.style.width="250px",this.rightSidebar.style.flexShrink="0",this.rightSidebar.style.overflowY="auto",this.rightSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.rightSidebar.style.borderLeft="1px solid #334155",this.rightSidebar.style.padding="10px",this.rightSidebar.style.boxSizing="border-box",this.rightSidebar.style.color="#cbd5e1",this.rightSidebar.style.fontSize="12px",this.rightSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.rightSidebar),this.chart=D.init(this.chartContainer),this.pluginManager=new vt(this,this.toolbarContainer),this.drawingEditor=new It(this),this.chart.on("dataZoom",n=>this.events.emit("chart:dataZoom",n)),this.chart.on("finished",n=>this.events.emit("chart:updated",n)),this.chart.getZr().on("mousedown",n=>this.events.emit("mouse:down",n)),this.chart.getZr().on("mousemove",n=>this.events.emit("mouse:move",n)),this.chart.getZr().on("mouseup",n=>this.events.emit("mouse:up",n)),this.chart.getZr().on("click",n=>this.events.emit("mouse:click",n));const i=this.chart.getZr(),s=i.setCursorStyle;i.setCursorStyle=function(n){n==="grab"&&(n="crosshair"),s.call(this,n)},this.bindDrawingEvents(),window.addEventListener("resize",this.resize.bind(this)),document.addEventListener("fullscreenchange",this.onFullscreenChange),document.addEventListener("keydown",this.onKeyDown)}bindDrawingEvents(){let e=null;const t=i=>{if(!i||i.componentType!=="series"||!i.seriesName?.startsWith("drawings"))return null;i.seriesIndex;const s=i.seriesName.match(/drawings-pane-(\d+)/);if(!s)return null;const n=parseInt(s[1]),o=this.drawings.filter(p=>(p.paneIndex||0)===n)[i.dataIndex];if(!o)return null;const h=i.event?.target?.name;return{drawing:o,targetName:h,paneIdx:n}};this.chart.on("mouseover",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(n){const o=s.drawing.id===this.selectedDrawingId;e&&(clearTimeout(e),e=null),o||n.children().forEach(h=>{h.name&&h.name.startsWith("point")&&h.attr("style",{opacity:1})})}if(s.targetName==="line")this.events.emit("drawing:hover",{id:s.drawing.id,type:s.drawing.type}),this.chart.getZr().setCursorStyle("move");else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:hover",{id:s.drawing.id,pointIndex:o}),this.chart.getZr().setCursorStyle("pointer")}}),this.chart.on("mouseout",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(s.drawing.id!==this.selectedDrawingId){if(e=setTimeout(()=>{if(n){if(this.selectedDrawingId===s.drawing.id)return;n.children().forEach(o=>{o.name&&o.name.startsWith("point")&&o.attr("style",{opacity:0})})}},50),s.targetName==="line")this.events.emit("drawing:mouseout",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mouseout",{id:s.drawing.id,pointIndex:o})}this.chart.getZr().setCursorStyle("default")}}),this.chart.on("mousedown",i=>{const s=t(i);if(!s)return;const n=i.event?.event||i.event,o=n?.offsetX,h=n?.offsetY;if(s.targetName==="line")this.events.emit("drawing:mousedown",{id:s.drawing.id,x:o,y:h});else if(s.targetName?.startsWith("point")){const p=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mousedown",{id:s.drawing.id,pointIndex:p,x:o,y:h})}}),this.chart.on("click",i=>{const s=t(i);if(s){if(this.selectedDrawingId!==s.drawing.id&&(this.selectedDrawingId=s.drawing.id,this.events.emit("drawing:selected",{id:s.drawing.id}),this.render()),s.targetName==="line")this.events.emit("drawing:click",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const n=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:click",{id:s.drawing.id,pointIndex:n})}}}),this.chart.getZr().on("click",i=>{i.target||this.selectedDrawingId&&(this.events.emit("drawing:deselected",{id:this.selectedDrawingId}),this.selectedDrawingId=null,this.render())})}getChart(){return this.chart}getMarketData(){return this.marketData}getTimeToIndex(){return this.timeToIndex}getOptions(){return this.options}disableTools(){this.pluginManager.deactivatePlugin()}registerPlugin(e){this.pluginManager.register(e)}addDrawing(e){this.drawings.push(e),this.render()}removeDrawing(e){const t=this.drawings.findIndex(i=>i.id===e);if(t!==-1){const i=this.drawings[t];this.drawings.splice(t,1),this.events.emit("drawing:deleted",{id:i.id}),this.render()}}getDrawing(e){return this.drawings.find(t=>t.id===e)}updateDrawing(e){const t=this.drawings.findIndex(i=>i.id===e.id);t!==-1&&(this.drawings[t]=e,this.render())}lockChart(){if(this.isLocked)return;this.isLocked=!0;const e=this.chart.getOption();this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!0})),tooltip:{show:!1}})}unlockChart(){if(!this.isLocked)return;this.isLocked=!1;const e=this.chart.getOption();(this.options.dataZoom||{}).visible,e.dataZoom&&this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!1})),tooltip:{show:!0}})}setZoom(e,t){this.chart.dispatchAction({type:"dataZoom",start:e,end:t})}setMarketData(e){this.marketData=e,this.rebuildTimeIndex(),this.render()}updateData(e){if(e.length===0)return;const t=new Map;this.marketData.forEach(l=>{t.set(l.time,l)}),e.forEach(l=>{t.has(l.time),t.set(l.time,l)}),this.marketData=Array.from(t.values()).sort((l,v)=>l.time-v.time),this.rebuildTimeIndex();const i=this.dataIndexOffset,s=this.marketData.map(l=>[l.open,l.close,l.low,l.high]),n={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}},o=[...Array(i).fill(n),...s,...Array(i).fill(n)],h=[...Array(i).fill(""),...this.marketData.map(l=>new Date(l.time).toLocaleString()),...Array(i).fill("")],p=this.chart.getOption(),d=ct.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId),b=ht.buildIndicatorSeries(this.indicators,this.timeToIndex,d.paneLayout,h.length,i),u={xAxis:p.xAxis.map((l,v)=>({data:h})),series:[{data:o},...b.map(l=>({data:l.data}))]};this.chart.setOption(u,{notMerge:!1})}addIndicator(e,t,i={isOverlay:!1}){const s=i.isOverlay??!1;let n=0;if(!s){let h=0;this.indicators.forEach(p=>{p.paneIndex>h&&(h=p.paneIndex)}),n=h+1}const o=new gt(e,t,n,{height:i.height,collapsed:!1,titleColor:i.titleColor,controls:i.controls});return this.indicators.set(e,o),this.render(),o}setIndicator(e,t,i=!1){this.addIndicator(e,{[e]:t},{isOverlay:i})}removeIndicator(e){this.indicators.delete(e),this.render()}toggleIndicator(e,t="collapse"){if(t==="fullscreen"){document.fullscreenElement?document.exitFullscreen():this.rootContainer.requestFullscreen();return}if(t==="maximize"){this.maximizedPaneId===e?this.maximizedPaneId=null:this.maximizedPaneId=e,this.render();return}if(e==="main"){this.isMainCollapsed=!this.isMainCollapsed,this.render();return}const i=this.indicators.get(e);i&&(i.toggleCollapse(),this.render())}resize(){this.chart.resize()}destroy(){window.removeEventListener("resize",this.resize.bind(this)),document.removeEventListener("fullscreenchange",this.onFullscreenChange),document.removeEventListener("keydown",this.onKeyDown),this.pluginManager.deactivatePlugin(),this.pluginManager.destroy(),this.chart.dispose()}rebuildTimeIndex(){this.timeToIndex.clear(),this.marketData.forEach((i,s)=>{this.timeToIndex.set(i.time,s)});const e=this.marketData.length,t=Math.ceil(e*this.padding);this.dataIndexOffset=t}render(){if(this.marketData.length===0)return;let e=null;try{const r=this.chart.getOption();if(r&&r.dataZoom&&r.dataZoom.length>0){const c=r.dataZoom.find(y=>y.type==="slider"||y.type==="inside");c&&(e={start:c.start,end:c.end})}}catch{}const t=this.options.databox?.position,i=this.leftSidebar.style.display,s=this.rightSidebar.style.display,n=t==="left"?"block":"none",o=t==="right"?"block":"none";(i!==n||s!==o)&&(this.leftSidebar.style.display=n,this.rightSidebar.style.display=o,this.chart.resize());const h=this.dataIndexOffset,p=[...Array(h).fill(""),...this.marketData.map(r=>new Date(r.time).toLocaleString()),...Array(h).fill("")],d=ct.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId);e&&d.dataZoom&&d.dataZoom.forEach(r=>{r.start=e.start,r.end=e.end}),d.xAxis.forEach(r=>{r.data=p,r.boundaryGap=!1});const b=ht.buildCandlestickSeries(this.marketData,this.options),u={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}};b.data=[...Array(h).fill(u),...b.data,...Array(h).fill(u)];const l=ht.buildIndicatorSeries(this.indicators,this.timeToIndex,d.paneLayout,p.length,h),v=yt.build(d,this.options,this.toggleIndicator.bind(this),this.isMainCollapsed,this.maximizedPaneId),g=new Map;this.drawings.forEach(r=>{const c=r.paneIndex||0;g.has(c)||g.set(c,[]),g.get(c).push(r)});const P=[];g.forEach((r,c)=>{P.push({type:"custom",name:`drawings-pane-${c}`,xAxisIndex:c,yAxisIndex:c,clip:!0,renderItem:(y,C)=>{const x=r[y.dataIndex];if(!x)return;const M=x.points[0],$=x.points[1];if(!M||!$)return;const Z=C.coord([M.timeIndex,M.value]),m=C.coord([$.timeIndex,$.value]),k=x.id===this.selectedDrawingId;if(x.type==="line")return{type:"group",children:[{type:"line",name:"line",shape:{x1:Z[0],y1:Z[1],x2:m[0],y2:m[1]},style:{stroke:x.style?.color||"#3b82f6",lineWidth:x.style?.lineWidth||2}},{type:"circle",name:"point-start",shape:{cx:Z[0],cy:Z[1],r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:k?1:0}},{type:"circle",name:"point-end",shape:{cx:m[0],cy:m[1],r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:k?1:0}}]};if(x.type==="fibonacci"){const z=Z[0],O=Z[1],N=m[0],w=m[1],E=Math.min(z,N),Y=Math.max(z,N),F=Y-E,T=w-O,W=[0,.236,.382,.5,.618,.786,1],B=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"],V=[];V.push({type:"line",name:"line",shape:{x1:z,y1:O,x2:N,y2:w},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}}),V.push({type:"circle",name:"point-start",shape:{cx:z,cy:O,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:k?1:0},z:100}),V.push({type:"circle",name:"point-end",shape:{cx:N,cy:w,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:k?1:0},z:100}),W.forEach((j,X)=>{const H=w-T*j,J=B[X%B.length];V.push({type:"line",name:"fib-line",shape:{x1:E,y1:H,x2:Y,y2:H},style:{stroke:J,lineWidth:1},silent:!0});const it=x.points[0].value,K=x.points[1].value,st=K-it,nt=K-st*j;if(V.push({type:"text",style:{text:`${j} (${nt.toFixed(2)})`,x:E+5,y:H-10,fill:J,fontSize:10},silent:!0}),X<W.length-1){const ot=W[X+1],Q=w-T*ot,at=Math.abs(Q-H),rt=Math.min(H,Q);V.push({type:"rect",shape:{x:E,y:rt,width:F,height:at},style:{fill:B[(X+1)%B.length],opacity:.1},silent:!0})}});const dt=[],et=[];return W.forEach((j,X)=>{const H=w-T*j,J=B[X%B.length];et.push({type:"line",shape:{x1:E,y1:H,x2:Y,y2:H},style:{stroke:J,lineWidth:1},silent:!0});const it=x.points[0].value,K=x.points[1].value,st=K-it,nt=K-st*j;if(et.push({type:"text",style:{text:`${j} (${nt.toFixed(2)})`,x:E+5,y:H-10,fill:J,fontSize:10},silent:!0}),X<W.length-1){const ot=W[X+1],Q=w-T*ot,at=Math.abs(Q-H),rt=Math.min(H,Q);dt.push({type:"rect",name:"line",shape:{x:E,y:rt,width:F,height:at},style:{fill:B[(X+1)%B.length],opacity:.1}})}}),{type:"group",children:[...dt,...et,{type:"line",name:"line",shape:{x1:z,y1:O,x2:N,y2:w},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}},{type:"circle",name:"point-start",shape:{cx:z,cy:O,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:k?1:0},z:100},{type:"circle",name:"point-end",shape:{cx:N,cy:w,r:4},style:{fill:"#fff",stroke:x.style?.color||"#3b82f6",lineWidth:1,opacity:k?1:0},z:100}]}}},data:r.map(y=>[y.points[0].timeIndex,y.points[0].value,y.points[1].timeIndex,y.points[1].value]),z:100,silent:!1})});const S=r=>{const c=xt.format(r,this.options),y=this.options.databox?.position;return y==="left"?(this.leftSidebar.innerHTML=c,""):y==="right"?(this.rightSidebar.innerHTML=c,""):this.options.databox?`<div style="min-width: 200px;">${c}</div>`:""},f={backgroundColor:this.options.backgroundColor,animation:!1,legend:{show:!1},tooltip:{show:!0,showContent:!!this.options.databox,trigger:"axis",axisPointer:{type:"cross",label:{backgroundColor:"#475569"}},backgroundColor:"rgba(30, 41, 59, 0.9)",borderWidth:1,borderColor:"#334155",padding:10,textStyle:{color:"#fff",fontFamily:this.options.fontFamily||"sans-serif"},formatter:S,extraCssText:t!=="floating"&&t!==void 0?"display: none !important;":void 0,position:(r,c,y,C,x)=>{if(this.options.databox?.position==="floating"){const M={top:10};return M[["left","right"][+(r[0]<x.viewSize[0]/2)]]=30,M}return null}},axisPointer:{link:{xAxisIndex:"all"},label:{backgroundColor:"#475569"}},graphic:v,grid:d.grid,xAxis:d.xAxis,yAxis:d.yAxis,dataZoom:d.dataZoom,series:[b,...l,...P]};this.chart.setOption(f,!0)}}var Tt=Object.defineProperty,Lt=(a,e,t)=>e in a?Tt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,_=(a,e,t)=>(Lt(a,typeof e!="symbol"?e+"":e,t),t);class tt{constructor(e){_(this,"id"),_(this,"name"),_(this,"icon"),_(this,"context"),_(this,"eventListeners",[]),this.id=e.id,this.name=e.name,this.icon=e.icon}init(e){this.context=e,this.onInit()}onInit(){}activate(){this.onActivate(),this.context.events.emit("plugin:activated",this.id)}onActivate(){}deactivate(){this.onDeactivate(),this.context.events.emit("plugin:deactivated",this.id)}onDeactivate(){}destroy(){this.removeAllListeners(),this.onDestroy()}onDestroy(){}on(e,t){this.context.events.on(e,t),this.eventListeners.push({event:e,handler:t})}off(e,t){this.context.events.off(e,t),this.eventListeners=this.eventListeners.filter(i=>i.event!==e||i.handler!==t)}removeAllListeners(){this.eventListeners.forEach(({event:e,handler:t})=>{this.context.events.off(e,t)}),this.eventListeners=[]}get chart(){return this.context.getChart()}get marketData(){return this.context.getMarketData()}}var At=Object.defineProperty,Zt=(a,e,t)=>e in a?At(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,L=(a,e,t)=>(Zt(a,typeof e!="symbol"?e+"":e,t),t);class Gt extends tt{constructor(e){super({id:"measure",name:e?.name||"Measure",icon:e?.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H680v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160H160v320Zm120-160h80-80Zm160 0h80-80Zm160 0h80-80Zm-120 0Z"/></svg>'}),L(this,"zr"),L(this,"state","idle"),L(this,"startPoint",null),L(this,"endPoint",null),L(this,"group",null),L(this,"rect",null),L(this,"labelRect",null),L(this,"labelText",null),L(this,"lineV",null),L(this,"lineH",null),L(this,"arrowStart",null),L(this,"arrowEnd",null),L(this,"onMouseDown",()=>{this.state==="finished"&&this.removeGraphic()}),L(this,"onChartInteraction",()=>{this.group&&this.removeGraphic()}),L(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.context.disableTools(),this.enableClearListeners())}),L(this,"clearHandlers",{}),L(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}enableClearListeners(){const e=()=>{this.removeGraphic()};setTimeout(()=>{this.zr.on("click",e)},10),this.zr.on("mousedown",this.onMouseDown),this.context.events.on("chart:dataZoom",this.onChartInteraction),this.clearHandlers={click:e,mousedown:this.onMouseDown,dataZoom:this.onChartInteraction}}disableClearListeners(){this.clearHandlers.click&&this.zr.off("click",this.clearHandlers.click),this.clearHandlers.mousedown&&this.zr.off("mousedown",this.clearHandlers.mousedown),this.clearHandlers.dataZoom&&this.context.events.off("chart:dataZoom",this.clearHandlers.dataZoom),this.clearHandlers={}}initGraphic(){this.group||(this.group=new D.graphic.Group,this.rect=new D.graphic.Rect({shape:{x:0,y:0,width:0,height:0},style:{fill:"rgba(0,0,0,0)",stroke:"transparent",lineWidth:0},z:100}),this.lineV=new D.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.lineH=new D.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.arrowStart=new D.graphic.Polygon({shape:{points:[[0,0],[-5,10],[5,10]]},style:{fill:"#fff"},z:102}),this.arrowEnd=new D.graphic.Polygon({shape:{points:[[0,0],[-5,-10],[5,-10]]},style:{fill:"#fff"},z:102}),this.labelRect=new D.graphic.Rect({shape:{x:0,y:0,width:0,height:0,r:4},style:{fill:"transparent",stroke:"transparent",lineWidth:0,shadowBlur:5,shadowColor:"rgba(0,0,0,0.3)"},z:102}),this.labelText=new D.graphic.Text({style:{x:0,y:0,text:"",fill:"#fff",font:"12px sans-serif",align:"center",verticalAlign:"middle"},z:103}),this.group.add(this.rect),this.group.add(this.lineV),this.group.add(this.lineH),this.group.add(this.arrowStart),this.group.add(this.arrowEnd),this.group.add(this.labelRect),this.group.add(this.labelText),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint,n=this.context.coordinateConversion.pixelToData({x:e,y:t}),o=this.context.coordinateConversion.pixelToData({x:i,y:s});if(!n||!o)return;const h=Math.round(n.timeIndex),p=Math.round(o.timeIndex),d=n.value,b=o.value,u=p-h,l=b-d,v=l/d*100,g=l>=0,P=g?"rgba(33, 150, 243, 0.2)":"rgba(236, 0, 0, 0.2)",S=g?"#2196F3":"#ec0000";this.rect.setShape({x:Math.min(e,i),y:Math.min(t,s),width:Math.abs(i-e),height:Math.abs(s-t)}),this.rect.setStyle({fill:P});const f=(e+i)/2,r=(t+s)/2;this.lineV.setShape({x1:f,y1:t,x2:f,y2:s}),this.lineV.setStyle({stroke:S}),this.lineH.setShape({x1:e,y1:r,x2:i,y2:r}),this.lineH.setStyle({stroke:S});const c=Math.min(t,s),y=Math.max(t,s);this.arrowStart.setStyle({fill:"none"}),this.arrowEnd.setStyle({fill:"none"}),g?(this.arrowStart.setShape({points:[[f,c],[f-4,c+6],[f+4,c+6]]}),this.arrowStart.setStyle({fill:S})):(this.arrowEnd.setShape({points:[[f,y],[f-4,y-6],[f+4,y-6]]}),this.arrowEnd.setStyle({fill:S}));const C=[`${l.toFixed(2)} (${v.toFixed(2)}%)`,`${u} bars, ${(u*0).toFixed(0)}d`].join(`
37
- `),x=140,M=40,$=Math.max(t,s),Z=Math.min(t,s);let m=(e+i)/2-x/2,k=$+10;const z=this.chart.getHeight();k+M>z&&(k=Z-M-10),this.labelRect.setShape({x:m,y:k,width:x,height:M}),this.labelRect.setStyle({fill:"#1e293b",stroke:S,lineWidth:1}),this.labelText.setStyle({x:m+x/2,y:k+M/2,text:C,fill:"#fff"})}}var $t=Object.defineProperty,Nt=(a,e,t)=>e in a?$t(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,G=(a,e,t)=>(Nt(a,typeof e!="symbol"?e+"":e,t),t);class Ft extends tt{constructor(e){super({id:"trend-line",name:e?.name||"Trend Line",icon:e?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2" /></svg>'}),G(this,"zr"),G(this,"state","idle"),G(this,"startPoint",null),G(this,"endPoint",null),G(this,"group",null),G(this,"line",null),G(this,"startCircle",null),G(this,"endCircle",null),G(this,"onMouseDown",()=>{}),G(this,"onChartInteraction",()=>{}),G(this,"onClick",t=>{if(this.state==="idle")this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),s=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(i&&s){const n=i.paneIndex||0;this.context.addDrawing({id:`line-${Date.now()}`,type:"line",points:[i,s],paneIndex:n,style:{color:"#3b82f6",lineWidth:2}})}}this.removeGraphic(),this.context.disableTools()}}),G(this,"clearHandlers",{}),G(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}saveDataCoordinates(){}updateGraphicFromData(){}enableClearListeners(){}disableClearListeners(){}initGraphic(){this.group||(this.group=new D.graphic.Group,this.line=new D.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#3b82f6",lineWidth:2},z:100}),this.startCircle=new D.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.endCircle=new D.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint;this.line.setShape({x1:e,y1:t,x2:i,y2:s}),this.startCircle.setShape({cx:e,cy:t}),this.endCircle.setShape({cx:i,cy:s})}}var Wt=Object.defineProperty,Ht=(a,e,t)=>e in a?Wt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,R=(a,e,t)=>(Ht(a,typeof e!="symbol"?e+"":e,t),t);class Ot extends tt{constructor(e={}){super({id:"fibonacci-tool",name:e.name||"Fibonacci Retracement",icon:e.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Z"/></svg>'}),R(this,"startPoint",null),R(this,"endPoint",null),R(this,"state","idle"),R(this,"graphicGroup",null),R(this,"levels",[0,.236,.382,.5,.618,.786,1]),R(this,"colors",["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"]),R(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),R(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const e=this.context.getChart().getZr();e.on("click",this.onClick),e.on("mousemove",this.onMouseMove)}unbindEvents(){const e=this.context.getChart().getZr();e.off("click",this.onClick),e.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new D.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const e=this.startPoint[0],t=this.startPoint[1],i=this.endPoint[0],s=this.endPoint[1],n=new D.graphic.Line({shape:{x1:e,y1:t,x2:i,y2:s},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]},silent:!0});this.graphicGroup.add(n);const o=Math.min(e,i),h=Math.max(e,i),p=h-o,d=s-t;this.levels.forEach((b,u)=>{const l=s-d*b,v=this.colors[u%this.colors.length],g=new D.graphic.Line({shape:{x1:o,y1:l,x2:h,y2:l},style:{stroke:v,lineWidth:1},silent:!0});if(this.graphicGroup.add(g),u<this.levels.length-1){const P=this.levels[u+1],S=s-d*P,f=Math.abs(S-l),r=Math.min(l,S),c=new D.graphic.Rect({shape:{x:o,y:r,width:p,height:f},style:{fill:this.colors[(u+1)%this.colors.length],opacity:.1},silent:!0});this.graphicGroup.add(c)}})}saveDrawing(){if(!this.startPoint||!this.endPoint)return;const e=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),t=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(e&&t){const i=e.paneIndex||0;this.context.addDrawing({id:`fib-${Date.now()}`,type:"fibonacci",points:[e,t],paneIndex:i,style:{color:"#3b82f6",lineWidth:1}})}}}export{tt as AbstractPlugin,Ot as FibonacciTool,Ft as LineTool,Gt as MeasureTool,zt as QFChart};
34
+ <div>${d.marker} <span style="color: #cbd5e1;">${d.displayName}</span></div>
35
+ <div style="font-size: 10px; color: #fff;padding-left:10px;">${S}</div>
36
+ </div>`}),p+="</div>"})}return p}}var bt=Object.defineProperty,vt=(a,e,t)=>e in a?bt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,K=(a,e,t)=>(vt(a,typeof e!="symbol"?e+"":e,t),t);class wt{constructor(e,t){K(this,"plugins",new Map),K(this,"activePluginId",null),K(this,"context"),K(this,"toolbarContainer"),K(this,"tooltipElement",null),K(this,"hideTimeout",null),this.context=e,this.toolbarContainer=t,this.createTooltip(),this.renderToolbar()}createTooltip(){this.tooltipElement=document.createElement("div"),Object.assign(this.tooltipElement.style,{position:"fixed",display:"none",backgroundColor:"#1e293b",color:"#e2e8f0",padding:"6px 10px",borderRadius:"6px",fontSize:"13px",lineHeight:"1.4",fontWeight:"500",border:"1px solid #334155",zIndex:"9999",pointerEvents:"none",whiteSpace:"nowrap",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15)",fontFamily:this.context.getOptions().fontFamily||"sans-serif",transition:"opacity 0.15s ease-in-out, transform 0.15s ease-in-out",opacity:"0",transform:"translateX(-5px)"}),document.body.appendChild(this.tooltipElement)}destroy(){this.tooltipElement&&this.tooltipElement.parentNode&&this.tooltipElement.parentNode.removeChild(this.tooltipElement),this.tooltipElement=null}showTooltip(e,t){if(!this.tooltipElement)return;this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null);const i=e.getBoundingClientRect();this.tooltipElement.textContent=t,this.tooltipElement.style.display="block";const s=this.tooltipElement.getBoundingClientRect(),n=i.top+(i.height-s.height)/2,o=i.right+10;this.tooltipElement.style.top=`${n}px`,this.tooltipElement.style.left=`${o}px`,requestAnimationFrame(()=>{this.tooltipElement&&(this.tooltipElement.style.opacity="1",this.tooltipElement.style.transform="translateX(0)")})}hideTooltip(){this.tooltipElement&&(this.tooltipElement.style.opacity="0",this.tooltipElement.style.transform="translateX(-5px)",this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(()=>{this.tooltipElement&&(this.tooltipElement.style.display="none"),this.hideTimeout=null},150))}register(e){if(this.plugins.has(e.id)){console.warn(`Plugin with id ${e.id} is already registered.`);return}this.plugins.set(e.id,e),e.init(this.context),this.addButton(e)}unregister(e){const t=this.plugins.get(e);t&&(this.activePluginId===e&&this.deactivatePlugin(),t.destroy?.(),this.plugins.delete(e),this.removeButton(e))}activatePlugin(e){if(this.activePluginId===e){this.deactivatePlugin();return}this.activePluginId&&this.deactivatePlugin();const t=this.plugins.get(e);t&&(this.activePluginId=e,this.setButtonActive(e,!0),t.activate?.())}deactivatePlugin(){this.activePluginId&&(this.plugins.get(this.activePluginId)?.deactivate?.(),this.setButtonActive(this.activePluginId,!1),this.activePluginId=null)}renderToolbar(){this.toolbarContainer.innerHTML="",this.toolbarContainer.style.display="flex",this.toolbarContainer.style.flexDirection="column",this.toolbarContainer.style.width="40px",this.toolbarContainer.style.backgroundColor=this.context.getOptions().backgroundColor||"#1e293b",this.toolbarContainer.style.borderRight="1px solid #334155",this.toolbarContainer.style.padding="5px",this.toolbarContainer.style.boxSizing="border-box",this.toolbarContainer.style.gap="5px",this.toolbarContainer.style.flexShrink="0"}addButton(e){const t=document.createElement("button");t.id=`qfchart-plugin-btn-${e.id}`,t.style.width="30px",t.style.height="30px",t.style.padding="4px",t.style.border="1px solid transparent",t.style.borderRadius="4px",t.style.backgroundColor="transparent",t.style.cursor="pointer",t.style.color=this.context.getOptions().fontColor||"#cbd5e1",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",e.icon?t.innerHTML=e.icon:t.innerText=(e.name||e.id).substring(0,2).toUpperCase(),t.addEventListener("mouseenter",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="rgba(255, 255, 255, 0.1)"),this.showTooltip(t,e.name||e.id)}),t.addEventListener("mouseleave",()=>{this.activePluginId!==e.id&&(t.style.backgroundColor="transparent"),this.hideTooltip()}),t.onclick=()=>this.activatePlugin(e.id),this.toolbarContainer.appendChild(t)}removeButton(e){const t=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);t&&t.remove()}setButtonActive(e,t){const i=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${e}`);i&&(t?(i.style.backgroundColor="#2563eb",i.style.color="#ffffff"):(i.style.backgroundColor="transparent",i.style.color=this.context.getOptions().fontColor||"#cbd5e1"))}}var Ct=Object.defineProperty,St=(a,e,t)=>e in a?Ct(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,$=(a,e,t)=>(St(a,typeof e!="symbol"?e+"":e,t),t);class kt{constructor(e){$(this,"context"),$(this,"isEditing",!1),$(this,"currentDrawing",null),$(this,"editingPointIndex",null),$(this,"zr"),$(this,"editGroup",null),$(this,"editLine",null),$(this,"editStartPoint",null),$(this,"editEndPoint",null),$(this,"isMovingShape",!1),$(this,"dragStart",null),$(this,"initialPixelPoints",[]),$(this,"onDrawingMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.isMovingShape=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.dragStart={x:t.x,y:t.y},this.initialPixelPoints=i.points.map(s=>{const n=this.context.coordinateConversion.dataToPixel(s);return n?{x:n.x,y:n.y}:{x:0,y:0}}),this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),$(this,"onPointMouseDown",t=>{if(this.isEditing)return;const i=this.context.getDrawing(t.id);i&&(this.isEditing=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.editingPointIndex=t.pointIndex,this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp))}),$(this,"onMouseMove",t=>{if(!this.isEditing||!this.currentDrawing)return;const i=t.offsetX,s=t.offsetY;if(this.isMovingShape&&this.dragStart){const n=i-this.dragStart.x,o=s-this.dragStart.y,r={x:this.initialPixelPoints[0].x+n,y:this.initialPixelPoints[0].y+o},p={x:this.initialPixelPoints[1].x+n,y:this.initialPixelPoints[1].y+o};this.editLine.setShape({x1:r.x,y1:r.y,x2:p.x,y2:p.y}),this.editStartPoint.setShape({cx:r.x,cy:r.y}),this.editEndPoint.setShape({cx:p.x,cy:p.y})}else this.editingPointIndex!==null&&(this.editingPointIndex===0?(this.editLine.setShape({x1:i,y1:s}),this.editStartPoint.setShape({cx:i,cy:s})):(this.editLine.setShape({x2:i,y2:s}),this.editEndPoint.setShape({cx:i,cy:s})))}),$(this,"onMouseUp",t=>{this.isEditing&&this.finishEditing(t.offsetX,t.offsetY)}),this.context=e,this.zr=this.context.getChart().getZr(),this.bindEvents()}bindEvents(){this.context.events.on("drawing:point:mousedown",this.onPointMouseDown),this.context.events.on("drawing:mousedown",this.onDrawingMouseDown)}createEditGraphic(){if(!this.currentDrawing)return;this.editGroup=new T.graphic.Group;const e=this.currentDrawing.points[0],t=this.currentDrawing.points[1],i=this.context.coordinateConversion.dataToPixel(e),s=this.context.coordinateConversion.dataToPixel(t);!i||!s||(this.editLine=new T.graphic.Line({shape:{x1:i.x,y1:i.y,x2:s.x,y2:s.y},style:{stroke:this.currentDrawing.style?.color||"#3b82f6",lineWidth:this.currentDrawing.style?.lineWidth||2,lineDash:[4,4]},silent:!0}),this.editStartPoint=new T.graphic.Circle({shape:{cx:i.x,cy:i.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editEndPoint=new T.graphic.Circle({shape:{cx:s.x,cy:s.y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3}),this.editGroup.add(this.editLine),this.editGroup.add(this.editStartPoint),this.editGroup.add(this.editEndPoint),this.zr.add(this.editGroup))}finishEditing(e,t){if(this.currentDrawing){if(this.isMovingShape&&this.dragStart){const i=e-this.dragStart.x,s=t-this.dragStart.y,n=this.initialPixelPoints.map((o,r)=>{const p=o.x+i,u=o.y+s;return this.context.coordinateConversion.pixelToData({x:p,y:u})});n.every(o=>o!==null)&&n[0]&&n[1]&&(this.currentDrawing.points[0]=n[0],this.currentDrawing.points[1]=n[1],n[0].paneIndex!==void 0&&(this.currentDrawing.paneIndex=n[0].paneIndex),this.context.updateDrawing(this.currentDrawing))}else if(this.editingPointIndex!==null){const i=this.context.coordinateConversion.pixelToData({x:e,y:t});i&&(this.currentDrawing.points[this.editingPointIndex]=i,this.editingPointIndex===0&&i.paneIndex!==void 0&&(this.currentDrawing.paneIndex=i.paneIndex),this.context.updateDrawing(this.currentDrawing))}this.isEditing=!1,this.isMovingShape=!1,this.dragStart=null,this.initialPixelPoints=[],this.currentDrawing=null,this.editingPointIndex=null,this.editGroup&&(this.zr.remove(this.editGroup),this.editGroup=null),this.zr.off("mousemove",this.onMouseMove),this.zr.off("mouseup",this.onMouseUp),this.context.unlockChart()}}}var It=Object.defineProperty,Pt=(a,e,t)=>e in a?It(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,Mt=(a,e,t)=>(Pt(a,typeof e!="symbol"?e+"":e,t),t);class Dt{constructor(){Mt(this,"handlers",new Map)}on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){const i=this.handlers.get(e);i&&i.delete(t)}emit(e,t){const i=this.handlers.get(e);i&&i.forEach(s=>{try{s(t)}catch(n){console.error(`Error in EventBus handler for ${e}:`,n)}})}clear(){this.handlers.clear()}}var zt=Object.defineProperty,Et=(a,e,t)=>e in a?zt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,P=(a,e,t)=>(Et(a,typeof e!="symbol"?e+"":e,t),t);class At{constructor(e,t={}){P(this,"chart"),P(this,"options"),P(this,"marketData",[]),P(this,"indicators",new Map),P(this,"timeToIndex",new Map),P(this,"pluginManager"),P(this,"drawingEditor"),P(this,"events",new Dt),P(this,"isMainCollapsed",!1),P(this,"maximizedPaneId",null),P(this,"selectedDrawingId",null),P(this,"drawings",[]),P(this,"coordinateConversion",{pixelToData:n=>{const o=this.chart.getOption();if(!o||!o.grid)return null;const r=o.grid.length;for(let p=0;p<r;p++)if(this.chart.containPixel({gridIndex:p},[n.x,n.y])){this.chart.convertFromPixel({seriesIndex:p},[n.x,n.y]);const u=this.chart.convertFromPixel({gridIndex:p},[n.x,n.y]);if(u)return{timeIndex:Math.round(u[0]),value:u[1],paneIndex:p}}return null},dataToPixel:n=>{const o=n.paneIndex||0,r=this.chart.convertToPixel({gridIndex:o},[n.timeIndex,n.value]);return r?{x:r[0],y:r[1]}:null}}),P(this,"upColor","#00da3c"),P(this,"downColor","#ec0000"),P(this,"defaultPadding",0),P(this,"padding"),P(this,"dataIndexOffset",0),P(this,"rootContainer"),P(this,"layoutContainer"),P(this,"toolbarContainer"),P(this,"leftSidebar"),P(this,"rightSidebar"),P(this,"chartContainer"),P(this,"onKeyDown",n=>{(n.key==="Delete"||n.key==="Backspace")&&this.selectedDrawingId&&(this.removeDrawing(this.selectedDrawingId),this.selectedDrawingId=null,this.render())}),P(this,"onFullscreenChange",()=>{this.render()}),P(this,"isLocked",!1),P(this,"lockedState",null),this.rootContainer=e,this.options={title:"Market",height:"600px",backgroundColor:"#1e293b",upColor:"#00da3c",downColor:"#ec0000",fontColor:"#cbd5e1",fontFamily:"sans-serif",padding:.01,dataZoom:{visible:!0,position:"top",height:6},layout:{mainPaneHeight:"50%",gap:13},watermark:!0,...t},this.options.upColor&&(this.upColor=this.options.upColor),this.options.downColor&&(this.downColor=this.options.downColor),this.padding=this.options.padding!==void 0?this.options.padding:this.defaultPadding,this.options.height&&(typeof this.options.height=="number"?this.rootContainer.style.height=`${this.options.height}px`:this.rootContainer.style.height=this.options.height),this.rootContainer.innerHTML="",this.layoutContainer=document.createElement("div"),this.layoutContainer.style.display="flex",this.layoutContainer.style.width="100%",this.layoutContainer.style.height="100%",this.layoutContainer.style.overflow="hidden",this.rootContainer.appendChild(this.layoutContainer),this.leftSidebar=document.createElement("div"),this.leftSidebar.style.display="none",this.leftSidebar.style.width="250px",this.leftSidebar.style.flexShrink="0",this.leftSidebar.style.overflowY="auto",this.leftSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.leftSidebar.style.borderRight="1px solid #334155",this.leftSidebar.style.padding="10px",this.leftSidebar.style.boxSizing="border-box",this.leftSidebar.style.color="#cbd5e1",this.leftSidebar.style.fontSize="12px",this.leftSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.leftSidebar),this.toolbarContainer=document.createElement("div"),this.layoutContainer.appendChild(this.toolbarContainer),this.chartContainer=document.createElement("div"),this.chartContainer.style.flexGrow="1",this.chartContainer.style.height="100%",this.chartContainer.style.overflow="hidden",this.layoutContainer.appendChild(this.chartContainer),this.rightSidebar=document.createElement("div"),this.rightSidebar.style.display="none",this.rightSidebar.style.width="250px",this.rightSidebar.style.flexShrink="0",this.rightSidebar.style.overflowY="auto",this.rightSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.rightSidebar.style.borderLeft="1px solid #334155",this.rightSidebar.style.padding="10px",this.rightSidebar.style.boxSizing="border-box",this.rightSidebar.style.color="#cbd5e1",this.rightSidebar.style.fontSize="12px",this.rightSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.rightSidebar),this.chart=T.init(this.chartContainer),this.pluginManager=new wt(this,this.toolbarContainer),this.drawingEditor=new kt(this),this.chart.on("dataZoom",n=>this.events.emit("chart:dataZoom",n)),this.chart.on("finished",n=>this.events.emit("chart:updated",n)),this.chart.getZr().on("mousedown",n=>this.events.emit("mouse:down",n)),this.chart.getZr().on("mousemove",n=>this.events.emit("mouse:move",n)),this.chart.getZr().on("mouseup",n=>this.events.emit("mouse:up",n)),this.chart.getZr().on("click",n=>this.events.emit("mouse:click",n));const i=this.chart.getZr(),s=i.setCursorStyle;i.setCursorStyle=function(n){n==="grab"&&(n="crosshair"),s.call(this,n)},this.bindDrawingEvents(),window.addEventListener("resize",this.resize.bind(this)),document.addEventListener("fullscreenchange",this.onFullscreenChange),document.addEventListener("keydown",this.onKeyDown)}bindDrawingEvents(){let e=null;const t=i=>{if(!i||i.componentType!=="series"||!i.seriesName?.startsWith("drawings"))return null;i.seriesIndex;const s=i.seriesName.match(/drawings-pane-(\d+)/);if(!s)return null;const n=parseInt(s[1]),o=this.drawings.filter(p=>(p.paneIndex||0)===n)[i.dataIndex];if(!o)return null;const r=i.event?.target?.name;return{drawing:o,targetName:r,paneIdx:n}};this.chart.on("mouseover",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(n){const o=s.drawing.id===this.selectedDrawingId;e&&(clearTimeout(e),e=null),o||n.children().forEach(r=>{r.name&&r.name.startsWith("point")&&r.attr("style",{opacity:1})})}if(s.targetName==="line")this.events.emit("drawing:hover",{id:s.drawing.id,type:s.drawing.type}),this.chart.getZr().setCursorStyle("move");else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:hover",{id:s.drawing.id,pointIndex:o}),this.chart.getZr().setCursorStyle("pointer")}}),this.chart.on("mouseout",i=>{const s=t(i);if(!s)return;const n=i.event?.target?.parent;if(s.drawing.id!==this.selectedDrawingId){if(e=setTimeout(()=>{if(n){if(this.selectedDrawingId===s.drawing.id)return;n.children().forEach(o=>{o.name&&o.name.startsWith("point")&&o.attr("style",{opacity:0})})}},50),s.targetName==="line")this.events.emit("drawing:mouseout",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const o=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mouseout",{id:s.drawing.id,pointIndex:o})}this.chart.getZr().setCursorStyle("default")}}),this.chart.on("mousedown",i=>{const s=t(i);if(!s)return;const n=i.event?.event||i.event,o=n?.offsetX,r=n?.offsetY;if(s.targetName==="line")this.events.emit("drawing:mousedown",{id:s.drawing.id,x:o,y:r});else if(s.targetName?.startsWith("point")){const p=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:mousedown",{id:s.drawing.id,pointIndex:p,x:o,y:r})}}),this.chart.on("click",i=>{const s=t(i);if(s){if(this.selectedDrawingId!==s.drawing.id&&(this.selectedDrawingId=s.drawing.id,this.events.emit("drawing:selected",{id:s.drawing.id}),this.render()),s.targetName==="line")this.events.emit("drawing:click",{id:s.drawing.id});else if(s.targetName?.startsWith("point")){const n=s.targetName==="point-start"?0:1;this.events.emit("drawing:point:click",{id:s.drawing.id,pointIndex:n})}}}),this.chart.getZr().on("click",i=>{i.target||this.selectedDrawingId&&(this.events.emit("drawing:deselected",{id:this.selectedDrawingId}),this.selectedDrawingId=null,this.render())})}getChart(){return this.chart}getMarketData(){return this.marketData}getTimeToIndex(){return this.timeToIndex}getOptions(){return this.options}disableTools(){this.pluginManager.deactivatePlugin()}registerPlugin(e){this.pluginManager.register(e)}addDrawing(e){this.drawings.push(e),this.render()}removeDrawing(e){const t=this.drawings.findIndex(i=>i.id===e);if(t!==-1){const i=this.drawings[t];this.drawings.splice(t,1),this.events.emit("drawing:deleted",{id:i.id}),this.render()}}getDrawing(e){return this.drawings.find(t=>t.id===e)}updateDrawing(e){const t=this.drawings.findIndex(i=>i.id===e.id);t!==-1&&(this.drawings[t]=e,this.render())}lockChart(){if(this.isLocked)return;this.isLocked=!0;const e=this.chart.getOption();this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!0})),tooltip:{show:!1}})}unlockChart(){if(!this.isLocked)return;this.isLocked=!1;const e=this.chart.getOption();(this.options.dataZoom||{}).visible,e.dataZoom&&this.chart.setOption({dataZoom:e.dataZoom.map(t=>({...t,disabled:!1})),tooltip:{show:!0}})}setZoom(e,t){this.chart.dispatchAction({type:"dataZoom",start:e,end:t})}setMarketData(e){this.marketData=e,this.rebuildTimeIndex(),this.render()}updateData(e){if(e.length===0)return;const t=new Map;this.marketData.forEach(d=>{t.set(d.time,d)}),e.forEach(d=>{t.has(d.time),t.set(d.time,d)}),this.marketData=Array.from(t.values()).sort((d,x)=>d.time-x.time),this.rebuildTimeIndex();const i=this.dataIndexOffset,s=this.marketData.map(d=>[d.open,d.close,d.low,d.high]),n={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}},o=[...Array(i).fill(n),...s,...Array(i).fill(n)],r=[...Array(i).fill(""),...this.marketData.map(d=>new Date(d.time).toLocaleString()),...Array(i).fill("")],p=this.chart.getOption(),u=pt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId),v=[...Array(i).fill(null),...this.marketData,...Array(i).fill(null)],f=V.buildIndicatorSeries(this.indicators,this.timeToIndex,u.paneLayout,r.length,i,v),m={xAxis:p.xAxis.map((d,x)=>({data:r})),series:[{data:o},...f.map(d=>({data:d.data}))]};this.chart.setOption(m,{notMerge:!1})}addIndicator(e,t,i={isOverlay:!1}){const s=i.isOverlay??!1;let n=0;if(!s){let r=0;this.indicators.forEach(p=>{p.paneIndex>r&&(r=p.paneIndex)}),n=r+1}const o=new ft(e,t,n,{height:i.height,collapsed:!1,titleColor:i.titleColor,controls:i.controls});return this.indicators.set(e,o),this.render(),o}setIndicator(e,t,i=!1){this.addIndicator(e,{[e]:t},{isOverlay:i})}removeIndicator(e){this.indicators.delete(e),this.render()}toggleIndicator(e,t="collapse"){if(t==="fullscreen"){document.fullscreenElement?document.exitFullscreen():this.rootContainer.requestFullscreen();return}if(t==="maximize"){this.maximizedPaneId===e?this.maximizedPaneId=null:this.maximizedPaneId=e,this.render();return}if(e==="main"){this.isMainCollapsed=!this.isMainCollapsed,this.render();return}const i=this.indicators.get(e);i&&(i.toggleCollapse(),this.render())}resize(){this.chart.resize()}destroy(){window.removeEventListener("resize",this.resize.bind(this)),document.removeEventListener("fullscreenchange",this.onFullscreenChange),document.removeEventListener("keydown",this.onKeyDown),this.pluginManager.deactivatePlugin(),this.pluginManager.destroy(),this.chart.dispose()}rebuildTimeIndex(){this.timeToIndex.clear(),this.marketData.forEach((i,s)=>{this.timeToIndex.set(i.time,s)});const e=this.marketData.length,t=Math.ceil(e*this.padding);this.dataIndexOffset=t}render(){if(this.marketData.length===0)return;let e=null;try{const y=this.chart.getOption();if(y&&y.dataZoom&&y.dataZoom.length>0){const c=y.dataZoom.find(l=>l.type==="slider"||l.type==="inside");c&&(e={start:c.start,end:c.end})}}catch{}const t=this.options.databox?.position,i=this.leftSidebar.style.display,s=this.rightSidebar.style.display,n=t==="left"?"block":"none",o=t==="right"?"block":"none";(i!==n||s!==o)&&(this.leftSidebar.style.display=n,this.rightSidebar.style.display=o,this.chart.resize());const r=this.dataIndexOffset,p=[...Array(r).fill(""),...this.marketData.map(y=>new Date(y.time).toLocaleString()),...Array(r).fill("")],u=pt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId);e&&u.dataZoom&&u.dataZoom.forEach(y=>{y.start=e.start,y.end=e.end}),u.xAxis.forEach(y=>{y.data=p,y.boundaryGap=!1});const v=V.buildCandlestickSeries(this.marketData,this.options),f={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}};v.data=[...Array(r).fill(f),...v.data,...Array(r).fill(f)];const m=[...Array(r).fill(null),...this.marketData,...Array(r).fill(null)],d=V.buildIndicatorSeries(this.indicators,this.timeToIndex,u.paneLayout,p.length,r,m),x=xt.build(u,this.options,this.toggleIndicator.bind(this),this.isMainCollapsed,this.maximizedPaneId),S=new Map;this.drawings.forEach(y=>{const c=y.paneIndex||0;S.has(c)||S.set(c,[]),S.get(c).push(y)});const k=[];S.forEach((y,c)=>{k.push({type:"custom",name:`drawings-pane-${c}`,xAxisIndex:c,yAxisIndex:c,clip:!0,renderItem:(l,b)=>{const h=y[l.dataIndex];if(!h)return;const C=h.points[0],E=h.points[1];if(!C||!E)return;const g=b.coord([C.timeIndex,C.value]),w=b.coord([E.timeIndex,E.value]),z=h.id===this.selectedDrawingId;if(h.type==="line")return{type:"group",children:[{type:"line",name:"line",shape:{x1:g[0],y1:g[1],x2:w[0],y2:w[1]},style:{stroke:h.style?.color||"#3b82f6",lineWidth:h.style?.lineWidth||2}},{type:"circle",name:"point-start",shape:{cx:g[0],cy:g[1],r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0}},{type:"circle",name:"point-end",shape:{cx:w[0],cy:w[1],r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0}}]};if(h.type==="fibonacci"){const F=g[0],H=g[1],I=w[0],M=w[1],Z=Math.min(F,I),N=Math.max(F,I),A=N-Z,R=M-H,O=[0,.236,.382,.5,.618,.786,1],X=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"],J=[];J.push({type:"line",name:"line",shape:{x1:F,y1:H,x2:I,y2:M},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}}),J.push({type:"circle",name:"point-start",shape:{cx:F,cy:H,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100}),J.push({type:"circle",name:"point-end",shape:{cx:I,cy:M,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100}),O.forEach((q,B)=>{const j=M-R*q,Q=X[B%X.length];J.push({type:"line",name:"fib-line",shape:{x1:Z,y1:j,x2:N,y2:j},style:{stroke:Q,lineWidth:1},silent:!0});const nt=h.points[0].value,_=h.points[1].value,ot=_-nt,at=_-ot*q;if(J.push({type:"text",style:{text:`${q} (${at.toFixed(2)})`,x:Z+5,y:j-10,fill:Q,fontSize:10},silent:!0}),B<O.length-1){const rt=O[B+1],tt=M-R*rt,lt=Math.abs(tt-j),ht=Math.min(j,tt);J.push({type:"rect",shape:{x:Z,y:ht,width:A,height:lt},style:{fill:X[(B+1)%X.length],opacity:.1},silent:!0})}});const ct=[],st=[];return O.forEach((q,B)=>{const j=M-R*q,Q=X[B%X.length];st.push({type:"line",shape:{x1:Z,y1:j,x2:N,y2:j},style:{stroke:Q,lineWidth:1},silent:!0});const nt=h.points[0].value,_=h.points[1].value,ot=_-nt,at=_-ot*q;if(st.push({type:"text",style:{text:`${q} (${at.toFixed(2)})`,x:Z+5,y:j-10,fill:Q,fontSize:10},silent:!0}),B<O.length-1){const rt=O[B+1],tt=M-R*rt,lt=Math.abs(tt-j),ht=Math.min(j,tt);ct.push({type:"rect",name:"line",shape:{x:Z,y:ht,width:A,height:lt},style:{fill:X[(B+1)%X.length],opacity:.1}})}}),{type:"group",children:[...ct,...st,{type:"line",name:"line",shape:{x1:F,y1:H,x2:I,y2:M},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}},{type:"circle",name:"point-start",shape:{cx:F,cy:H,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100},{type:"circle",name:"point-end",shape:{cx:I,cy:M,r:4},style:{fill:"#fff",stroke:h.style?.color||"#3b82f6",lineWidth:1,opacity:z?1:0},z:100}]}}},data:y.map(l=>[l.points[0].timeIndex,l.points[0].value,l.points[1].timeIndex,l.points[1].value]),z:100,silent:!1})});const L=y=>{const c=mt.format(y,this.options),l=this.options.databox?.position;return l==="left"?(this.leftSidebar.innerHTML=c,""):l==="right"?(this.rightSidebar.innerHTML=c,""):this.options.databox?`<div style="min-width: 200px;">${c}</div>`:""},D={backgroundColor:this.options.backgroundColor,animation:!1,legend:{show:!1},tooltip:{show:!0,showContent:!!this.options.databox,trigger:"axis",axisPointer:{type:"cross",label:{backgroundColor:"#475569"}},backgroundColor:"rgba(30, 41, 59, 0.9)",borderWidth:1,borderColor:"#334155",padding:10,textStyle:{color:"#fff",fontFamily:this.options.fontFamily||"sans-serif"},formatter:L,extraCssText:t!=="floating"&&t!==void 0?"display: none !important;":void 0,position:(y,c,l,b,h)=>{if(this.options.databox?.position==="floating"){const C={top:10};return C[["left","right"][+(y[0]<h.viewSize[0]/2)]]=30,C}return null}},axisPointer:{link:{xAxisIndex:"all"},label:{backgroundColor:"#475569"}},graphic:x,grid:u.grid,xAxis:u.xAxis,yAxis:u.yAxis,dataZoom:u.dataZoom,series:[v,...d,...k]};this.chart.setOption(D,!0)}}var Tt=Object.defineProperty,Lt=(a,e,t)=>e in a?Tt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,et=(a,e,t)=>(Lt(a,typeof e!="symbol"?e+"":e,t),t);class it{constructor(e){et(this,"id"),et(this,"name"),et(this,"icon"),et(this,"context"),et(this,"eventListeners",[]),this.id=e.id,this.name=e.name,this.icon=e.icon}init(e){this.context=e,this.onInit()}onInit(){}activate(){this.onActivate(),this.context.events.emit("plugin:activated",this.id)}onActivate(){}deactivate(){this.onDeactivate(),this.context.events.emit("plugin:deactivated",this.id)}onDeactivate(){}destroy(){this.removeAllListeners(),this.onDestroy()}onDestroy(){}on(e,t){this.context.events.on(e,t),this.eventListeners.push({event:e,handler:t})}off(e,t){this.context.events.off(e,t),this.eventListeners=this.eventListeners.filter(i=>i.event!==e||i.handler!==t)}removeAllListeners(){this.eventListeners.forEach(({event:e,handler:t})=>{this.context.events.off(e,t)}),this.eventListeners=[]}get chart(){return this.context.getChart()}get marketData(){return this.context.getMarketData()}}var Zt=Object.defineProperty,Gt=(a,e,t)=>e in a?Zt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,G=(a,e,t)=>(Gt(a,typeof e!="symbol"?e+"":e,t),t);class $t extends it{constructor(e){super({id:"measure",name:e?.name||"Measure",icon:e?.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H680v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160H160v320Zm120-160h80-80Zm160 0h80-80Zm160 0h80-80Zm-120 0Z"/></svg>'}),G(this,"zr"),G(this,"state","idle"),G(this,"startPoint",null),G(this,"endPoint",null),G(this,"group",null),G(this,"rect",null),G(this,"labelRect",null),G(this,"labelText",null),G(this,"lineV",null),G(this,"lineH",null),G(this,"arrowStart",null),G(this,"arrowEnd",null),G(this,"onMouseDown",()=>{this.state==="finished"&&this.removeGraphic()}),G(this,"onChartInteraction",()=>{this.group&&this.removeGraphic()}),G(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.context.disableTools(),this.enableClearListeners())}),G(this,"clearHandlers",{}),G(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}enableClearListeners(){const e=()=>{this.removeGraphic()};setTimeout(()=>{this.zr.on("click",e)},10),this.zr.on("mousedown",this.onMouseDown),this.context.events.on("chart:dataZoom",this.onChartInteraction),this.clearHandlers={click:e,mousedown:this.onMouseDown,dataZoom:this.onChartInteraction}}disableClearListeners(){this.clearHandlers.click&&this.zr.off("click",this.clearHandlers.click),this.clearHandlers.mousedown&&this.zr.off("mousedown",this.clearHandlers.mousedown),this.clearHandlers.dataZoom&&this.context.events.off("chart:dataZoom",this.clearHandlers.dataZoom),this.clearHandlers={}}initGraphic(){this.group||(this.group=new T.graphic.Group,this.rect=new T.graphic.Rect({shape:{x:0,y:0,width:0,height:0},style:{fill:"rgba(0,0,0,0)",stroke:"transparent",lineWidth:0},z:100}),this.lineV=new T.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.lineH=new T.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.arrowStart=new T.graphic.Polygon({shape:{points:[[0,0],[-5,10],[5,10]]},style:{fill:"#fff"},z:102}),this.arrowEnd=new T.graphic.Polygon({shape:{points:[[0,0],[-5,-10],[5,-10]]},style:{fill:"#fff"},z:102}),this.labelRect=new T.graphic.Rect({shape:{x:0,y:0,width:0,height:0,r:4},style:{fill:"transparent",stroke:"transparent",lineWidth:0,shadowBlur:5,shadowColor:"rgba(0,0,0,0.3)"},z:102}),this.labelText=new T.graphic.Text({style:{x:0,y:0,text:"",fill:"#fff",font:"12px sans-serif",align:"center",verticalAlign:"middle"},z:103}),this.group.add(this.rect),this.group.add(this.lineV),this.group.add(this.lineH),this.group.add(this.arrowStart),this.group.add(this.arrowEnd),this.group.add(this.labelRect),this.group.add(this.labelText),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint,n=this.context.coordinateConversion.pixelToData({x:e,y:t}),o=this.context.coordinateConversion.pixelToData({x:i,y:s});if(!n||!o)return;const r=Math.round(n.timeIndex),p=Math.round(o.timeIndex),u=n.value,v=o.value,f=p-r,m=v-u,d=m/u*100,x=m>=0,S=x?"rgba(33, 150, 243, 0.2)":"rgba(236, 0, 0, 0.2)",k=x?"#2196F3":"#ec0000";this.rect.setShape({x:Math.min(e,i),y:Math.min(t,s),width:Math.abs(i-e),height:Math.abs(s-t)}),this.rect.setStyle({fill:S});const L=(e+i)/2,D=(t+s)/2;this.lineV.setShape({x1:L,y1:t,x2:L,y2:s}),this.lineV.setStyle({stroke:k}),this.lineH.setShape({x1:e,y1:D,x2:i,y2:D}),this.lineH.setStyle({stroke:k});const y=Math.min(t,s),c=Math.max(t,s);this.arrowStart.setStyle({fill:"none"}),this.arrowEnd.setStyle({fill:"none"}),x?(this.arrowStart.setShape({points:[[L,y],[L-4,y+6],[L+4,y+6]]}),this.arrowStart.setStyle({fill:k})):(this.arrowEnd.setShape({points:[[L,c],[L-4,c-6],[L+4,c-6]]}),this.arrowEnd.setStyle({fill:k}));const l=[`${m.toFixed(2)} (${d.toFixed(2)}%)`,`${f} bars, ${(f*0).toFixed(0)}d`].join(`
37
+ `),b=140,h=40,C=Math.max(t,s),E=Math.min(t,s);let g=(e+i)/2-b/2,w=C+10;const z=this.chart.getHeight();w+h>z&&(w=E-h-10),this.labelRect.setShape({x:g,y:w,width:b,height:h}),this.labelRect.setStyle({fill:"#1e293b",stroke:k,lineWidth:1}),this.labelText.setStyle({x:g+b/2,y:w+h/2,text:l,fill:"#fff"})}}var Nt=Object.defineProperty,Ft=(a,e,t)=>e in a?Nt(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,W=(a,e,t)=>(Ft(a,typeof e!="symbol"?e+"":e,t),t);class Wt extends it{constructor(e){super({id:"trend-line",name:e?.name||"Trend Line",icon:e?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2" /></svg>'}),W(this,"zr"),W(this,"state","idle"),W(this,"startPoint",null),W(this,"endPoint",null),W(this,"group",null),W(this,"line",null),W(this,"startCircle",null),W(this,"endCircle",null),W(this,"onMouseDown",()=>{}),W(this,"onChartInteraction",()=>{}),W(this,"onClick",t=>{if(this.state==="idle")this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),s=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(i&&s){const n=i.paneIndex||0;this.context.addDrawing({id:`line-${Date.now()}`,type:"line",points:[i,s],paneIndex:n,style:{color:"#3b82f6",lineWidth:2}})}}this.removeGraphic(),this.context.disableTools()}}),W(this,"clearHandlers",{}),W(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}saveDataCoordinates(){}updateGraphicFromData(){}enableClearListeners(){}disableClearListeners(){}initGraphic(){this.group||(this.group=new T.graphic.Group,this.line=new T.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#3b82f6",lineWidth:2},z:100}),this.startCircle=new T.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.endCircle=new T.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1},z:101}),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[e,t]=this.startPoint,[i,s]=this.endPoint;this.line.setShape({x1:e,y1:t,x2:i,y2:s}),this.startCircle.setShape({cx:e,cy:t}),this.endCircle.setShape({cx:i,cy:s})}}var Ht=Object.defineProperty,Ot=(a,e,t)=>e in a?Ht(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,Y=(a,e,t)=>(Ot(a,typeof e!="symbol"?e+"":e,t),t);class Rt extends it{constructor(e={}){super({id:"fibonacci-tool",name:e.name||"Fibonacci Retracement",icon:e.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Z"/></svg>'}),Y(this,"startPoint",null),Y(this,"endPoint",null),Y(this,"state","idle"),Y(this,"graphicGroup",null),Y(this,"levels",[0,.236,.382,.5,.618,.786,1]),Y(this,"colors",["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"]),Y(this,"onClick",t=>{this.state==="idle"?(this.state="drawing",this.startPoint=[t.offsetX,t.offsetY],this.endPoint=[t.offsetX,t.offsetY],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),Y(this,"onMouseMove",t=>{this.state==="drawing"&&(this.endPoint=[t.offsetX,t.offsetY],this.updateGraphic())})}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const e=this.context.getChart().getZr();e.on("click",this.onClick),e.on("mousemove",this.onMouseMove)}unbindEvents(){const e=this.context.getChart().getZr();e.off("click",this.onClick),e.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new T.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const e=this.startPoint[0],t=this.startPoint[1],i=this.endPoint[0],s=this.endPoint[1],n=new T.graphic.Line({shape:{x1:e,y1:t,x2:i,y2:s},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]},silent:!0});this.graphicGroup.add(n);const o=Math.min(e,i),r=Math.max(e,i),p=r-o,u=s-t;this.levels.forEach((v,f)=>{const m=s-u*v,d=this.colors[f%this.colors.length],x=new T.graphic.Line({shape:{x1:o,y1:m,x2:r,y2:m},style:{stroke:d,lineWidth:1},silent:!0});if(this.graphicGroup.add(x),f<this.levels.length-1){const S=this.levels[f+1],k=s-u*S,L=Math.abs(k-m),D=Math.min(m,k),y=new T.graphic.Rect({shape:{x:o,y:D,width:p,height:L},style:{fill:this.colors[(f+1)%this.colors.length],opacity:.1},silent:!0});this.graphicGroup.add(y)}})}saveDrawing(){if(!this.startPoint||!this.endPoint)return;const e=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),t=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(e&&t){const i=e.paneIndex||0;this.context.addDrawing({id:`fib-${Date.now()}`,type:"fibonacci",points:[e,t],paneIndex:i,style:{color:"#3b82f6",lineWidth:1}})}}}export{it as AbstractPlugin,Rt as FibonacciTool,Wt as LineTool,$t as MeasureTool,At as QFChart};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qfo/qfchart",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "Professional financial charting library built on Apache ECharts with candlestick charts, technical indicators, and interactive drawing tools",
5
5
  "keywords": [
6
6
  "chart",
package/src/QFChart.ts CHANGED
@@ -636,12 +636,26 @@ export class QFChart implements ChartContext {
636
636
  // Build indicator series data
637
637
  const currentOption = this.chart.getOption() as any;
638
638
  const layout = LayoutManager.calculate(this.chart.getHeight(), this.indicators, this.options, this.isMainCollapsed, this.maximizedPaneId);
639
+
640
+ // Pass full padded candlestick data for shape positioning
641
+ // But SeriesBuilder expects 'OHLCV[]', while paddedCandlestickData is array of arrays [open,close,low,high]
642
+ // We need to pass the raw marketData but ALIGNED with padding?
643
+ // Or better, pass the processed OHLCV array?
644
+ // Let's pass the raw marketData, but SeriesBuilder needs to handle the padding internally or we pass padded data?
645
+ // SeriesBuilder.buildIndicatorSeries iterates over 'totalDataLength' (which includes padding) and uses 'dataIndexOffset'.
646
+ // So passing 'this.marketData' is not enough because index 0 in marketData corresponds to 'paddingPoints' index in chart.
647
+ // We should pass an array that aligns with chart indices.
648
+ // Let's reconstruct an array of objects {high, low} that includes padding.
649
+
650
+ const paddedOHLCVForShapes = [...Array(paddingPoints).fill(null), ...this.marketData, ...Array(paddingPoints).fill(null)];
651
+
639
652
  const indicatorSeries = SeriesBuilder.buildIndicatorSeries(
640
653
  this.indicators,
641
654
  this.timeToIndex,
642
655
  layout.paneLayout,
643
656
  categoryData.length,
644
- paddingPoints
657
+ paddingPoints,
658
+ paddedOHLCVForShapes // Pass padded OHLCV data
645
659
  );
646
660
 
647
661
  // Update only the data arrays in the option, not the full config
@@ -843,12 +857,16 @@ export class QFChart implements ChartContext {
843
857
  const emptyCandle = { value: [NaN, NaN, NaN, NaN], itemStyle: { opacity: 0 } };
844
858
  candlestickSeries.data = [...Array(paddingPoints).fill(emptyCandle), ...candlestickSeries.data, ...Array(paddingPoints).fill(emptyCandle)];
845
859
 
860
+ // Build array of OHLCV aligned with indices for shape positioning
861
+ const paddedOHLCVForShapes = [...Array(paddingPoints).fill(null), ...this.marketData, ...Array(paddingPoints).fill(null)];
862
+
846
863
  const indicatorSeries = SeriesBuilder.buildIndicatorSeries(
847
864
  this.indicators,
848
865
  this.timeToIndex,
849
866
  layout.paneLayout,
850
867
  categoryData.length,
851
- paddingPoints
868
+ paddingPoints,
869
+ paddedOHLCVForShapes // Pass padded OHLCV
852
870
  );
853
871
 
854
872
  // 3. Build Graphics
@@ -33,12 +33,152 @@ export class SeriesBuilder {
33
33
  };
34
34
  }
35
35
 
36
+ private static getShapeSymbol(shape: string): string {
37
+ // SVG Paths need to be:
38
+ // 1. Valid SVG path data strings
39
+ // 2. Ideally centered around the origin or a standard box (e.g., 0 0 24 24)
40
+ // 3. ECharts path:// format expects just the path data usually, but complex shapes might need 'image://' or better paths.
41
+ // For simple shapes, standard ECharts symbols or simple paths work.
42
+
43
+ switch (shape) {
44
+ case 'arrowdown':
45
+ // Blocky arrow down
46
+ return 'path://M12 24l-12-12h8v-12h8v12h8z';
47
+
48
+ case 'arrowup':
49
+ // Blocky arrow up
50
+ return 'path://M12 0l12 12h-8v12h-8v-12h-8z';
51
+
52
+ case 'circle':
53
+ return 'circle';
54
+
55
+ case 'cross':
56
+ // Plus sign (+)
57
+ return 'path://M11 2h2v9h9v2h-9v9h-2v-9h-9v-2h9z';
58
+
59
+ case 'diamond':
60
+ return 'diamond'; // Built-in
61
+
62
+ case 'flag':
63
+ // Flag on a pole
64
+ return 'path://M6 2v20h2v-8h12l-2-6 2-6h-12z';
65
+
66
+ case 'labeldown':
67
+ // Bubble pointing down: Rounded rect with a triangle at bottom
68
+ return 'path://M4 2h16a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-6l-2 4l-2 -4h-6a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2z';
69
+
70
+ case 'labelup':
71
+ // Bubble pointing up: Rounded rect with triangle at top
72
+ return 'path://M12 2l2 4h6a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-16a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h6z';
73
+
74
+ case 'square':
75
+ return 'rect';
76
+
77
+ case 'triangledown':
78
+ // Pointing down
79
+ return 'path://M12 21l-10-18h20z';
80
+
81
+ case 'triangleup':
82
+ // Pointing up
83
+ return 'triangle'; // Built-in is pointing up
84
+
85
+ case 'xcross':
86
+ // 'X' shape
87
+ return 'path://M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z';
88
+
89
+ default:
90
+ return 'circle';
91
+ }
92
+ }
93
+
94
+ private static getShapeRotation(shape: string): number {
95
+ // With custom paths defined above, we might not need rotation unless we reuse shapes.
96
+ // Built-in triangle is UP.
97
+ return 0;
98
+ }
99
+
100
+ private static getShapeSize(size: string, width?: number, height?: number): number | number[] {
101
+ // If both width and height are specified, use them directly
102
+ if (width !== undefined && height !== undefined) {
103
+ return [width, height];
104
+ }
105
+
106
+ // Base size from the size parameter
107
+ let baseSize: number;
108
+ switch (size) {
109
+ case 'tiny':
110
+ baseSize = 8;
111
+ break;
112
+ case 'small':
113
+ baseSize = 12;
114
+ break;
115
+ case 'normal':
116
+ case 'auto':
117
+ baseSize = 16;
118
+ break;
119
+ case 'large':
120
+ baseSize = 24;
121
+ break;
122
+ case 'huge':
123
+ baseSize = 32;
124
+ break;
125
+ default:
126
+ baseSize = 16;
127
+ }
128
+
129
+ // If only width is specified, preserve aspect ratio (assume square default)
130
+ if (width !== undefined) {
131
+ return [width, width];
132
+ }
133
+
134
+ // If only height is specified, preserve aspect ratio (assume square default)
135
+ if (height !== undefined) {
136
+ return [height, height];
137
+ }
138
+
139
+ // Default uniform size
140
+ return baseSize;
141
+ }
142
+
143
+ // Helper to determine label position and distance relative to shape BASED ON LOCATION
144
+ private static getLabelConfig(shape: string, location: string): { position: string; distance: number } {
145
+ // Text position should be determined by location, not shape direction
146
+
147
+ switch (location) {
148
+ case 'abovebar':
149
+ // Shape is above the candle, text should be above the shape
150
+ return { position: 'top', distance: 5 };
151
+
152
+ case 'belowbar':
153
+ // Shape is below the candle, text should be below the shape
154
+ return { position: 'bottom', distance: 5 };
155
+
156
+ case 'top':
157
+ // Shape at top of chart, text below it
158
+ return { position: 'bottom', distance: 5 };
159
+
160
+ case 'bottom':
161
+ // Shape at bottom of chart, text above it
162
+ return { position: 'top', distance: 5 };
163
+
164
+ case 'absolute':
165
+ default:
166
+ // For labelup/down, text is INSIDE the shape
167
+ if (shape === 'labelup' || shape === 'labeldown') {
168
+ return { position: 'inside', distance: 0 };
169
+ }
170
+ // For other shapes, text above by default
171
+ return { position: 'top', distance: 5 };
172
+ }
173
+ }
174
+
36
175
  public static buildIndicatorSeries(
37
176
  indicators: Map<string, IndicatorType>,
38
177
  timeToIndex: Map<number, number>,
39
178
  paneLayout: PaneConfiguration[],
40
179
  totalDataLength: number,
41
- dataIndexOffset: number = 0
180
+ dataIndexOffset: number = 0,
181
+ candlestickData?: OHLCV[] // Add candlestick data to access High/Low for positioning
42
182
  ): any[] {
43
183
  const series: any[] = [];
44
184
 
@@ -65,6 +205,7 @@ export class SeriesBuilder {
65
205
 
66
206
  const dataArray = new Array(totalDataLength).fill(null);
67
207
  const colorArray = new Array(totalDataLength).fill(null);
208
+ const optionsArray = new Array(totalDataLength).fill(null); // Store per-point options
68
209
 
69
210
  plot.data.forEach((point) => {
70
211
  const index = timeToIndex.get(point.time);
@@ -89,9 +230,11 @@ export class SeriesBuilder {
89
230
 
90
231
  dataArray[offsetIndex] = value;
91
232
  colorArray[offsetIndex] = pointColor || plot.options.color;
233
+ optionsArray[offsetIndex] = point.options || {};
92
234
  }
93
235
  }
94
236
  });
237
+
95
238
  switch (plot.options.style) {
96
239
  case 'histogram':
97
240
  case 'columns':
@@ -140,6 +283,130 @@ export class SeriesBuilder {
140
283
  });
141
284
  break;
142
285
 
286
+ case 'shape':
287
+ const shapeData = dataArray
288
+ .map((val, i) => {
289
+ // Merge global options with per-point options to get location first
290
+ const pointOpts = optionsArray[i] || {};
291
+ const globalOpts = plot.options;
292
+ const location = pointOpts.location || globalOpts.location || 'absolute';
293
+
294
+ // For location="absolute", always draw the shape (ignore value)
295
+ // For other locations, only draw if value is truthy (TradingView behavior)
296
+ if (location !== 'absolute' && !val) {
297
+ return null;
298
+ }
299
+
300
+ // If we get here and val is null/undefined, it means location is absolute
301
+ // In that case, we still need a valid value for positioning
302
+ // Use the value if it exists, otherwise we'd need a fallback
303
+ // But in TradingView, absolute location still expects a value for Y position
304
+ if (val === null || val === undefined) {
305
+ return null; // Can't plot without a Y coordinate
306
+ }
307
+
308
+ const color = pointOpts.color || globalOpts.color || 'blue';
309
+ const shape = pointOpts.shape || globalOpts.shape || 'circle';
310
+ const size = pointOpts.size || globalOpts.size || 'normal';
311
+ const text = pointOpts.text || globalOpts.text;
312
+ const textColor = pointOpts.textcolor || globalOpts.textcolor || 'white';
313
+
314
+ // NEW: Get width and height
315
+ const width = pointOpts.width || globalOpts.width;
316
+ const height = pointOpts.height || globalOpts.height;
317
+
318
+ // Debug logging (remove after testing)
319
+ // if (width !== undefined || height !== undefined) {
320
+ // console.log('[Shape Debug]', { shape, width, height, pointOpts, globalOpts });
321
+ // }
322
+
323
+ // Positioning based on location
324
+ let yValue = val; // Default to absolute value
325
+ let symbolOffset: (string | number)[] = [0, 0];
326
+
327
+ if (location === 'abovebar') {
328
+ // Shape above the candle
329
+ if (candlestickData && candlestickData[i]) {
330
+ yValue = candlestickData[i].high;
331
+ }
332
+ symbolOffset = [0, '-150%']; // Shift up
333
+ } else if (location === 'belowbar') {
334
+ // Shape below the candle
335
+ if (candlestickData && candlestickData[i]) {
336
+ yValue = candlestickData[i].low;
337
+ }
338
+ symbolOffset = [0, '150%']; // Shift down
339
+ } else if (location === 'top') {
340
+ // Shape at top of chart - we need to use a very high value
341
+ // This would require knowing the y-axis max, which we don't have here easily
342
+ // For now, use a placeholder approach - might need to calculate from data
343
+ // Or we can use a percentage of the viewport? ECharts doesn't support that directly in scatter.
344
+ // Best approach: use a large multiplier of current value or track max
345
+ // Simplified: use coordinate system max (will need enhancement)
346
+ yValue = val; // For now, keep absolute - would need axis max
347
+ symbolOffset = [0, 0];
348
+ } else if (location === 'bottom') {
349
+ // Shape at bottom of chart
350
+ yValue = val; // For now, keep absolute - would need axis min
351
+ symbolOffset = [0, 0];
352
+ }
353
+
354
+ const symbol = SeriesBuilder.getShapeSymbol(shape);
355
+ const symbolSize = SeriesBuilder.getShapeSize(size, width, height);
356
+ const rotate = SeriesBuilder.getShapeRotation(shape);
357
+
358
+ // Debug logging (remove after testing)
359
+ // if (width !== undefined || height !== undefined) {
360
+ // console.log('[Shape Size Debug]', { symbolSize, width, height, size });
361
+ // }
362
+
363
+ // Special handling for labelup/down sizing - they contain text so they should be larger
364
+ let finalSize: number | number[] = symbolSize;
365
+ if (shape.includes('label')) {
366
+ // If custom size, scale it up for labels
367
+ if (Array.isArray(symbolSize)) {
368
+ finalSize = [symbolSize[0] * 2.5, symbolSize[1] * 2.5];
369
+ } else {
370
+ finalSize = symbolSize * 2.5;
371
+ }
372
+ }
373
+
374
+ // Get label configuration based on location
375
+ const labelConfig = SeriesBuilder.getLabelConfig(shape, location);
376
+
377
+ const item: any = {
378
+ value: [i, yValue],
379
+ symbol: symbol,
380
+ symbolSize: finalSize,
381
+ symbolRotate: rotate,
382
+ symbolOffset: symbolOffset,
383
+ itemStyle: {
384
+ color: color,
385
+ },
386
+ label: {
387
+ show: !!text,
388
+ position: labelConfig.position,
389
+ distance: labelConfig.distance,
390
+ formatter: text,
391
+ color: textColor,
392
+ fontSize: 10,
393
+ fontWeight: 'bold',
394
+ },
395
+ };
396
+
397
+ return item;
398
+ })
399
+ .filter((item) => item !== null);
400
+
401
+ series.push({
402
+ name: seriesName,
403
+ type: 'scatter',
404
+ xAxisIndex: xAxisIndex,
405
+ yAxisIndex: yAxisIndex,
406
+ data: shapeData,
407
+ });
408
+ break;
409
+
143
410
  case 'background':
144
411
  series.push({
145
412
  name: seriesName,
package/src/types.ts CHANGED
@@ -18,7 +18,7 @@ export interface IndicatorPoint {
18
18
  };
19
19
  }
20
20
 
21
- export type IndicatorStyle = 'line' | 'step' | 'columns' | 'histogram' | 'circles' | 'cross' | 'background';
21
+ export type IndicatorStyle = 'line' | 'step' | 'columns' | 'histogram' | 'circles' | 'cross' | 'background' | 'shape';
22
22
 
23
23
  export interface IndicatorOptions {
24
24
  style: IndicatorStyle;
@@ -26,6 +26,13 @@ export interface IndicatorOptions {
26
26
  offset?: number;
27
27
  linewidth?: number;
28
28
  smooth?: boolean;
29
+ shape?: string;
30
+ size?: string;
31
+ text?: string;
32
+ textcolor?: string;
33
+ location?: string;
34
+ width?: number;
35
+ height?: number;
29
36
  }
30
37
 
31
38
  export interface IndicatorPlot {