emberwick 0.2.0 → 0.3.0
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/README.md +38 -3
- package/index.d.ts +30 -2
- package/index.js +50 -0
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/umd/emberwick.umd.js +1 -1
- package/umd/emberwick.umd.js.map +1 -1
package/umd/emberwick.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(w,L){typeof exports=="object"&&typeof module!="undefined"?L(exports):typeof define=="function"&&define.amd?define(["exports"],L):(w=typeof globalThis!="undefined"?globalThis:w||self,L(w.Emberwick={}))})(this,function(w){"use strict";class L{constructor(t,e){this.container=t,this.names=e,this.canvas={},this.ctx={},this.width=0,this.height=0,this.dpr=0,this.onResize=null,getComputedStyle(t).position==="static"&&(t.style.position="relative"),e.forEach((s,n)=>{const o=document.createElement("canvas");Object.assign(o.style,{position:"absolute",left:"0",top:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:String(n+1)}),t.appendChild(o),this.canvas[s]=o,this.ctx[s]=o.getContext("2d")}),this._ro=new ResizeObserver(()=>this.measure()),this._ro.observe(t),this.measure()}measure(){const t=this.container.getBoundingClientRect(),e=Math.max(1,Math.floor(t.width)),s=Math.max(1,Math.floor(t.height)),n=Math.min(window.devicePixelRatio||1,2);if(!(e===this.width&&s===this.height&&n===this.dpr)){this.width=e,this.height=s,this.dpr=n;for(const o of this.names){const a=this.canvas[o];a.width=Math.floor(e*n),a.height=Math.floor(s*n),this.ctx[o].setTransform(n,0,0,n,0,0)}this.onResize&&this.onResize(e,s)}}composite(){const t=document.createElement("canvas");t.width=Math.floor(this.width*this.dpr),t.height=Math.floor(this.height*this.dpr);const e=t.getContext("2d");for(const s of this.names)e.drawImage(this.canvas[s],0,0);return t}destroy(){this._ro.disconnect();for(const t of this.names)this.canvas[t].remove();this.canvas={},this.ctx={}}}class J{constructor(t){this.onFrame=t,this.fps=0,this._raf=0,this._dirty=new Set,this._last=0,this._running=!1,this._frames=0,this._fpsAt=0,this._tick=this._tick.bind(this)}invalidate(...t){if(!t.length)this._dirty.add("all");else for(const e of t)this._dirty.add(e);this._schedule()}start(){this._running||(this._running=!0,this._last=performance.now(),this._fpsAt=this._last,this.invalidate("all"))}stop(){this._running=!1,this._raf&&cancelAnimationFrame(this._raf),this._raf=0}_schedule(){this._raf||!this._running||(this._raf=requestAnimationFrame(this._tick))}_tick(t){if(this._raf=0,!this._running)return;const e=Math.min(Math.max(t-this._last,1),64);this._last=t,this._frames++,t-this._fpsAt>=500&&(this.fps=Math.round(this._frames*1e3/(t-this._fpsAt)),this._frames=0,this._fpsAt=t);const s=this._dirty;this._dirty=new Set;let n=!1;try{n=this.onFrame(s,e,t)===!0}catch(o){console.error("[Emberwick] frame error",o)}(n||this._dirty.size)&&this._schedule()}}const F=i=>1-Math.pow(1-i,3),Q=i=>i<.5?4*i*i*i:1-Math.pow(-2*i+2,3)/2;class S{constructor(t=0,e=90){this.value=t,this.target=t,this.tau=e}set(t){this.target=t}jump(t){this.value=t,this.target=t}get settled(){const t=1e-9+Math.abs(this.target)*1e-6;return Math.abs(this.target-this.value)<=t}tick(t){return this.settled?(this.value=this.target,!1):(this.value+=(this.target-this.value)*(1-Math.exp(-t/this.tau)),!0)}}class I{constructor(t=200,e=F){this.duration=t,this.ease=e,this.t=t}restart(){this.t=0}get done(){return this.t>=this.duration}get progress(){return this.ease(Math.min(1,this.t/this.duration))}tick(t){return this.done?!1:(this.t+=t,!0)}}const C=(i,t,e)=>i<t?t:i>e?e:i;class H{constructor({spacing:t=9,minSpacing:e=.8,maxSpacing:s=160,rightOffset:n=12}={}){this.minSpacing=e,this.maxSpacing=s,this.rightOffset=n,this.width=0,this.barCount=0,this.follow=!0,this.timeframeMs=6e4,this._spacing=new S(t,65),this._right=new S(n,65),this._initial=t}get spacing(){return this._spacing.value}get right(){return this._right.value}resize(t){this.width=Math.max(1,t)}setBarCount(t){const e=t>this.barCount;if(this.barCount=t,this.follow){const s=t-1+this.rightOffset;e?this._right.set(s):this._right.jump(s)}}x(t){return this.width-(this._right.value-t)*this._spacing.value}index(t){return this._right.value-(this.width-t)/this._spacing.value}barWidth(){const t=this._spacing.value;return Math.max(1,Math.floor(t*.72))}visibleRange(){const t=Math.floor(this.index(0))-1,e=Math.ceil(this.index(this.width))+1;return{from:C(t,0,Math.max(0,this.barCount-1)),to:C(e,0,Math.max(0,this.barCount-1))}}_clampRight(t){const e=this.barCount-1+this.rightOffset+this.width/this._spacing.target,s=Math.min(4,this.barCount-1+this.rightOffset);return C(t,s,e)}panBy(t){if(!t)return!1;const e=this._clampRight(this._right.value-t/this._spacing.value);return this._right.jump(e),this.follow=!1,!0}zoomAt(t,e){const s=this._spacing.target,n=C(s*e,this.minSpacing,this.maxSpacing);if(Math.abs(n-s)<1e-9)return!1;const o=this.follow?this.width:t,h=this._right.target-(this.width-o)/s+(this.width-o)/n;return this._spacing.set(n),this._right.set(this._clampRight(h)),!0}snapToRealtime(){this.follow=!0,this._right.set(this.barCount-1+this.rightOffset)}reset(){this._spacing.set(this._initial),this.snapToRealtime()}tick(t){const e=this._spacing.tick(t),s=this._right.tick(t);return e||s}get settled(){return this._spacing.settled&&this._right.settled}}const x=(i,t,e)=>i<t?t:i>e?e:i;class O{constructor({mode:t="linear",tau:e=120,marginTop:s=.12,marginBottom:n=.12}={}){this.mode=t,this.marginTop=s,this.marginBottom=n,this.auto=!0,this.top=0,this.height=1,this._lo=new S(0,e),this._hi=new S(1,e),this._primed=!1}_fwd(t){return this.mode==="log"?Math.log(Math.max(t,1e-9)):t}_inv(t){return this.mode==="log"?Math.exp(t):t}setMode(t){if(t===this.mode)return;const e=this._inv(this._lo.value),s=this._inv(this._hi.value);this.mode=t,this._lo.jump(this._fwd(e)),this._hi.jump(this._fwd(s))}layout(t,e){this.top=t,this.height=Math.max(1,e)}get lo(){return this._inv(this._lo.value)}get hi(){return this._inv(this._hi.value)}y(t){const e=this._lo.value,s=this._hi.value,n=(this._fwd(t)-e)/(s-e||1);return this.top+this.height*(1-n)}price(t){const e=this._lo.value,s=this._hi.value,n=1-(t-this.top)/this.height;return this._inv(e+n*(s-e))}fit(t,e,s,n){if(!this.auto||!t.length)return;let o=1/0,a=-1/0;for(let m=e;m<=s;m++){const r=t[m];r&&(r.low<o&&(o=r.low),r.high>a&&(a=r.high))}if(n&&(n.low<o&&(o=n.low),n.high>a&&(a=n.high)),!isFinite(o)||!isFinite(a))return;let f=this._fwd(o),h=this._fwd(a),l=(h-f)*this.marginTop;l>0||(l=Math.abs(h)*.01||1),f-=l,h+=(h-f)*0+l,this._lo.set(f),this._hi.set(h),this._primed||(this._lo.jump(f),this._hi.jump(h),this._primed=!0)}scaleBy(t){this.auto=!1;const e=this._lo.target,s=this._hi.target,n=(e+s)/2,o=(s-e)/2*x(t,.2,5);this._lo.set(n-o),this._hi.set(n+o)}resetAuto(){this.auto=!0}tick(t){const e=this._lo.tick(t),s=this._hi.tick(t);return e||s}}const P={background:"#0b0e14",grid:"rgba(255,255,255,0.045)",axisLine:"rgba(255,255,255,0.10)",text:"#8b93a7",textStrong:"#e6e9ef",up:"#26a69a",down:"#ef5350",upFill:"#26a69a",downFill:"#ef5350",wickUp:"#26a69a",wickDown:"#ef5350",volumeUp:"rgba(38,166,154,0.30)",volumeDown:"rgba(239,83,80,0.30)",crosshair:"rgba(255,255,255,0.32)",labelBg:"#2a3040",labelText:"#e6e9ef",tagText:"#06080d",font:'11px ui-sans-serif, -apple-system, "Segoe UI", Roboto, sans-serif',priceAxisWidth:68,timeAxisHeight:26},tt={...P,background:"#ffffff",grid:"rgba(0,0,0,0.06)",axisLine:"rgba(0,0,0,0.14)",text:"#6b7280",textStrong:"#111827",labelBg:"#374151",volumeUp:"rgba(38,166,154,0.25)",volumeDown:"rgba(239,83,80,0.25)",crosshair:"rgba(0,0,0,0.35)",tagText:"#ffffff"};class U{constructor(t=55){this.enabled=!0,this.o=new S(0,t),this.h=new S(0,t),this.l=new S(0,t),this.c=new S(0,t),this.vol=new S(0,t*2),this.spawn=new I(240),this._has=!1,this._time=null}setTarget(t){if(!t){this._has=!1;return}(!this._has||t.time!==this._time)&&(this.o.jump(t.open),this.h.jump(t.open),this.l.jump(t.open),this.c.jump(t.open),this.vol.jump(0),this.spawn.restart(),this._time=t.time,this._has=!0),this.o.set(t.open),this.h.set(t.high),this.l.set(t.low),this.c.set(t.close),this.vol.set(t.volume||0)}reset(){this._has=!1,this._time=null}tick(t){if(!this._has)return!1;let e=!1;return this.o.tick(t)&&(e=!0),this.h.tick(t)&&(e=!0),this.l.tick(t)&&(e=!0),this.c.tick(t)&&(e=!0),this.vol.tick(t)&&(e=!0),this.spawn.tick(t)&&(e=!0),e}read(t){if(!this._has||!this.enabled||t.time!==this._time)return t;const e=this.o.value,s=this.c.value;return{time:t.time,open:e,close:s,high:Math.max(this.h.value,e,s),low:Math.min(this.l.value,e,s),volume:this.vol.value,_spawn:this.spawn.progress}}}class j{constructor({friction:t=.92,min:e=.015}={}){this.friction=t,this.min=e,this.v=0,this.active=!1}sample(t,e){if(e<=0)return;const s=t/e;this.v=this.v*.6+s*.4,this.active=!1}release(){Math.abs(this.v)>this.min&&(this.active=!0)}stop(){this.v=0,this.active=!1}tick(t){if(!this.active)return 0;const e=this.v*t;return this.v*=Math.pow(this.friction,t/16.6667),Math.abs(this.v)<this.min&&this.stop(),e}}function et(i,t){const e=i/Math.max(1,t);if(!(e>0)||!isFinite(e))return 1;const s=Math.pow(10,Math.floor(Math.log10(e))),n=e/s;return(n<1.5?1:n<3?2:n<7?5:10)*s}function R(i,t,e){const s=et(t-i,e),n=[],o=Math.ceil(i/s)*s;for(let a=o;a<=t+s*1e-9;a+=s)n.push(a);return{ticks:n,step:s}}function D(i){return!isFinite(i)||i<=0?2:i>=100?0:i>=1?2:Math.min(8,Math.ceil(-Math.log10(i))+1)}function it(i){const t=[1,2,5,10,15,20,30,60,120,240,480,960,1920,3840,7680];for(const e of t)if(e>=i)return e;return Math.ceil(i/1e3)*1e3}const A=i=>String(i).padStart(2,"0");function st(i,t){const e=new Date(i);return t>=864e5?`${e.getDate()} ${e.toLocaleString("en",{month:"short"})}`:e.getHours()===0&&e.getMinutes()===0?`${e.getDate()} ${e.toLocaleString("en",{month:"short"})}`:`${A(e.getHours())}:${A(e.getMinutes())}`}function nt(i){const t=new Date(i);return`${t.getFullYear()}-${A(t.getMonth()+1)}-${A(t.getDate())} ${A(t.getHours())}:${A(t.getMinutes())}`}function ot(i,t){const{theme:e,ts:s,ps:n,plot:o,bars:a,width:f,height:h}=t;i.clearRect(0,0,f,h),i.fillStyle=e.background,i.fillRect(0,0,f,h),i.font=e.font,i.textBaseline="middle";const l=Math.max(2,Math.floor(o.h/58)),{ticks:m,step:r}=R(n.lo,n.hi,l),c=D(r);i.strokeStyle=e.grid,i.lineWidth=1,i.beginPath();for(const p of m){const u=Math.round(n.y(p))+.5;u<o.y||u>o.y+o.h||(i.moveTo(0,u),i.lineTo(o.w,u))}i.stroke(),i.fillStyle=e.text,i.textAlign="left";for(const p of m){const u=Math.round(n.y(p));u<o.y+6||u>o.y+o.h-6||i.fillText(p.toFixed(c),o.w+8,u)}if(a.length){const p=Math.ceil(74/Math.max(1e-4,s.spacing)),u=it(p),{from:v,to:b}=s.visibleRange(),M=Math.ceil(v/u)*u;i.strokeStyle=e.grid,i.beginPath();for(let g=M;g<=b;g+=u){const d=Math.round(s.x(g))+.5;d<0||d>o.w||(i.moveTo(d,0),i.lineTo(d,o.h))}i.stroke(),i.fillStyle=e.text,i.textAlign="center";const y=o.h+e.timeAxisHeight/2;for(let g=M;g<=b;g+=u){const d=a[g];if(!d)continue;const _=Math.round(s.x(g));_<28||_>o.w-28||i.fillText(st(d.time,s.timeframeMs),_,y)}}i.strokeStyle=e.axisLine,i.beginPath(),i.moveTo(o.w+.5,0),i.lineTo(o.w+.5,o.h),i.moveTo(0,o.h+.5),i.lineTo(f,o.h+.5),i.stroke()}function ht(i,t){const{theme:e,ts:s,ps:n,plot:o,bars:a,width:f,height:h,live:l,volumeRatio:m}=t;if(i.clearRect(0,0,f,h),!a.length)return;const{from:r,to:c}=s.visibleRange(),p=s.barWidth(),u=p/2,v=p<=2,b=o.h*m,M=o.y+o.h-b;let y=0;for(let d=r;d<=c;d++){const _=a[d];_&&_.volume>y&&(y=_.volume)}if(y>0)for(let d=r;d<=c;d++){let _=a[d];if(!_)continue;l&&d===a.length-1&&(_=l);const k=s.x(d);if(k<-p||k>o.w+p)continue;const T=_.volume/y*b*.9;i.fillStyle=_.close>=_.open?e.volumeUp:e.volumeDown,i.fillRect(Math.round(k-u),M+(b-T),Math.max(1,p),T)}for(let d=r;d<=c;d++){let _=a[d];if(!_)continue;const k=d===a.length-1;l&&k&&(_=l);const T=s.x(d);if(T<-p||T>o.w+p)continue;const B=_.close>=_.open,Tt=B?e.up:e.down,Y=n.y(_.open),N=n.y(_.close),St=n.y(_.high),At=n.y(_.low);let Z=1;l&&k&&typeof _._spawn=="number"&&(Z=.35+.65*_._spawn);const G=Math.round(T)+(p%2?.5:0);if(i.strokeStyle=B?e.wickUp:e.wickDown,i.lineWidth=Math.max(1,Math.min(2,p*.16)),i.beginPath(),i.moveTo(G,St),i.lineTo(G,At),i.stroke(),v)continue;const Lt=Math.min(Y,N),Ct=Math.max(1,Math.abs(N-Y)),V=Math.max(1,p*Z);i.fillStyle=Tt,i.fillRect(Math.round(T-V/2),Math.round(Lt),Math.round(V),Math.round(Ct))}const g=l||a[a.length-1];if(g){const d=Math.round(n.y(g.close))+.5;if(d>o.y&&d<o.y+o.h){const _=g.close>=g.open;i.save(),i.setLineDash([3,3]),i.strokeStyle=_?e.up:e.down,i.lineWidth=1,i.globalAlpha=.7,i.beginPath(),i.moveTo(0,d),i.lineTo(o.w,d),i.stroke(),i.restore();const{step:k}=R(n.lo,n.hi,Math.max(2,Math.floor(o.h/58))),T=g.close.toFixed(D(k));i.font=e.font,i.textBaseline="middle",i.textAlign="left";const B=i.measureText(T).width;i.fillStyle=_?e.up:e.down,i.fillRect(o.w+1,d-9,B+14,18),i.fillStyle=e.tagText,i.fillText(T,o.w+8,d)}}}function at(i,t){const{theme:e,ts:s,ps:n,plot:o,bars:a,width:f,height:h,cursor:l,magnet:m}=t;if(i.clearRect(0,0,f,h),!l||!a.length||l.x<0||l.x>o.w||l.y<0||l.y>o.h)return;const r=Math.round(s.index(l.x)),c=a[r];let p=l.x,u=l.y;if(c&&(p=s.x(r),m)){const y=[c.open,c.high,c.low,c.close];let g=null,d=1/0;for(const _ of y){const k=n.y(_),T=Math.abs(k-l.y);T<d&&(d=T,g=k)}d<22&&(u=g)}i.save(),i.setLineDash([4,4]),i.strokeStyle=e.crosshair,i.lineWidth=1,i.beginPath(),i.moveTo(Math.round(p)+.5,0),i.lineTo(Math.round(p)+.5,o.h),i.moveTo(0,Math.round(u)+.5),i.lineTo(o.w,Math.round(u)+.5),i.stroke(),i.restore(),i.font=e.font,i.textBaseline="middle";const{step:v}=R(n.lo,n.hi,Math.max(2,Math.floor(o.h/58))),b=n.price(u).toFixed(D(v));i.textAlign="left";const M=i.measureText(b).width;if(i.fillStyle=e.labelBg,i.fillRect(o.w+1,u-9,M+14,18),i.fillStyle=e.labelText,i.fillText(b,o.w+8,u),c){const y=nt(c.time);i.textAlign="center";const g=i.measureText(y).width,d=Math.min(Math.max(p,g/2+6),o.w-g/2-6);i.fillStyle=e.labelBg,i.fillRect(d-g/2-7,o.h+3,g+14,18),i.fillStyle=e.labelText,i.fillText(y,d,o.h+12)}}const rt=["arrowUp","arrowDown","triangleUp","triangleDown","circle","square","diamond","flag","label"],lt=new Set(rt),ft={arrowUp:"belowBar",triangleUp:"belowBar",arrowDown:"aboveBar",triangleDown:"aboveBar"},ct=new Set(["aboveBar","belowBar","inBar","atPrice"]);function ut(i,t){if(!i||!isFinite(i.time))return null;const e=lt.has(i.shape)?i.shape:"circle",s=ct.has(i.position)?i.position:ft[e]||"aboveBar";return{id:i.id!=null?String(i.id):`mk${t}`,time:+i.time,price:isFinite(i.price)?+i.price:null,shape:e,position:s,color:i.color||null,textColor:i.textColor||null,text:i.text!=null?String(i.text):"",size:isFinite(i.size)&&i.size>0?+i.size:1,data:i.data,index:-1}}function W(i){if(!Array.isArray(i))return[];const t=[];for(let e=0;e<i.length;e++){const s=ut(i[e],e);s&&t.push(s)}return t.sort((e,s)=>e.time-s.time),t}function z(i,t){const e=i.length;if(!e)return-1;if(t<=i[0].time)return 0;if(t>=i[e-1].time)return e-1;let s=0,n=e-1;for(;s<=n;){const f=s+n>>1,h=i[f].time;if(h===t)return f;h<t?s=f+1:n=f-1}const o=Math.max(0,n),a=Math.min(e-1,s);return Math.abs(i[o].time-t)<=Math.abs(i[a].time-t)?o:a}function dt(i,t){for(let e=0;e<i.length;e++)i[e].index=z(t,i[e].time);return i}function mt(i,t){const{ts:e,ps:s,plot:n,bars:o,live:a}=t;if(!i.length||!o.length)return[];const{from:f,to:h}=e.visibleRange(),l=o.length-1,m=e.barWidth()<=3,r=new Map,c=[];let p=-1/0;for(const u of i){const v=u.index;if(v<0||v<f-2||v>h+2)continue;const b=a&&v===l?a:o[v];if(!b)continue;const M=e.x(v);if(M<-48||M>n.w+48)continue;if(m){if(M-p<4)continue;p=M}const y=5*u.size;let g,d=0;if(u.position==="atPrice"&&u.price!=null?g=s.y(u.price):u.position==="inBar"?g=s.y((b.high+b.low)/2):u.position==="belowBar"?(g=s.y(b.low)+y+7,d=1):(g=s.y(b.high)-y-7,d=-1),d!==0){const _=v+u.position,k=r.get(_)||0;r.set(_,k+1),g+=d*k*(y*2+5)}c.push({m:u,x:M,y:g,r:y,dir:d})}return c}const $={solid:[],dashed:[6,4],dotted:[1,3]},pt=new Set(["arrowDown","triangleDown"]);function q(i,t,e,s,n,o){const a=Math.max(0,Math.min(o,n/2,s/2));i.beginPath(),i.moveTo(t+a,e),i.lineTo(t+s-a,e),i.quadraticCurveTo(t+s,e,t+s,e+a),i.lineTo(t+s,e+n-a),i.quadraticCurveTo(t+s,e+n,t+s-a,e+n),i.lineTo(t+a,e+n),i.quadraticCurveTo(t,e+n,t,e+n-a),i.lineTo(t,e+a),i.quadraticCurveTo(t,e,t+a,e),i.closePath()}function gt(i,t){const{zones:e,theme:s,ts:n,ps:o,plot:a,bars:f}=t;if(!(!e||!e.length)){i.save(),i.font=s.font,i.textBaseline="top",i.textAlign="left";for(const h of e){let l,m,r,c;if(isFinite(h.from)&&isFinite(h.to))m=o.y(Math.max(h.from,h.to)),c=Math.max(1,o.y(Math.min(h.from,h.to))-m),l=0,r=a.w;else if(isFinite(h.fromTime)&&isFinite(h.toTime)&&f.length){const p=n.x(z(f,Math.min(h.fromTime,h.toTime))),u=n.x(z(f,Math.max(h.fromTime,h.toTime)));l=p,r=Math.max(1,u-p),m=0,c=a.h}else continue;l>a.w||l+r<0||m>a.h||m+c<0||(i.fillStyle=h.color||"rgba(38,166,154,0.10)",i.fillRect(l,m,r,c),h.border&&(i.strokeStyle=h.border,i.lineWidth=1,i.strokeRect(Math.round(l)+.5,Math.round(m)+.5,Math.round(r),Math.round(c))),h.label&&(i.fillStyle=h.labelColor||s.text,i.fillText(h.label,Math.max(6,l+6),Math.max(4,m+4))))}i.restore()}}function _t(i,t){const{priceLines:e,theme:s,ps:n,plot:o}=t;if(!e||!e.length)return;const{step:a}=R(n.lo,n.hi,Math.max(2,Math.floor(o.h/58))),f=D(a);i.save(),i.font=s.font,i.textBaseline="middle";for(const h of e){if(!h||!isFinite(h.price))continue;const l=Math.round(n.y(h.price))+.5;if(l<0||l>o.h)continue;const m=h.color||s.textStrong;if(i.setLineDash($[h.lineStyle]||$.dashed),i.strokeStyle=m,i.lineWidth=h.lineWidth||1,i.beginPath(),i.moveTo(0,l),i.lineTo(o.w,l),i.stroke(),i.setLineDash([]),h.title){i.textAlign="left";const r=i.measureText(h.title).width;i.fillStyle=m,q(i,6,l-9,r+12,18,4),i.fill(),i.fillStyle=h.titleColor||s.tagText,i.fillText(h.title,12,l)}if(h.axisLabel!==!1){const r=h.price.toFixed(f);i.textAlign="left";const c=i.measureText(r).width;i.fillStyle=m,i.fillRect(o.w+1,l-9,c+14,18),i.fillStyle=h.tagTextColor||s.tagText,i.fillText(r,o.w+8,l)}}i.restore()}function vt(i,t,e,s,n){switch(i.beginPath(),t){case"arrowUp":i.moveTo(e,s-n),i.lineTo(e+n,s),i.lineTo(e+n*.45,s),i.lineTo(e+n*.45,s+n),i.lineTo(e-n*.45,s+n),i.lineTo(e-n*.45,s),i.lineTo(e-n,s),i.closePath();break;case"arrowDown":i.moveTo(e,s+n),i.lineTo(e+n,s),i.lineTo(e+n*.45,s),i.lineTo(e+n*.45,s-n),i.lineTo(e-n*.45,s-n),i.lineTo(e-n*.45,s),i.lineTo(e-n,s),i.closePath();break;case"triangleUp":i.moveTo(e,s-n),i.lineTo(e+n,s+n),i.lineTo(e-n,s+n),i.closePath();break;case"triangleDown":i.moveTo(e,s+n),i.lineTo(e+n,s-n),i.lineTo(e-n,s-n),i.closePath();break;case"square":i.rect(e-n,s-n,n*2,n*2);break;case"diamond":i.moveTo(e,s-n),i.lineTo(e+n,s),i.lineTo(e,s+n),i.lineTo(e-n,s),i.closePath();break;default:i.arc(e,s,n,0,Math.PI*2)}}function bt(i,t,e,s,n){i.fillStyle=n,i.fillRect(t-s*.8,e-s,Math.max(1,s*.3),s*2),i.beginPath(),i.moveTo(t-s*.5,e-s),i.lineTo(t+s,e-s*.55),i.lineTo(t-s*.5,e-s*.1),i.closePath(),i.fill()}function wt(i,t,e,s){const n=[];if(!e||!e.length)return n;const{theme:o}=t;i.save(),i.font=o.font,i.textAlign="center",i.textBaseline="middle";for(const a of e){const{m:f,x:h,y:l,r:m,dir:r}=a,c=f.color||(pt.has(f.shape)?o.down:o.up),p=s!=null&&f.id===s;if(f.shape==="label"){const u=f.text||"•",v=i.measureText(u).width+14,b=18*f.size;q(i,h-v/2,l-b/2,v,b,4),i.fillStyle=c,i.fill(),p&&(i.strokeStyle=o.textStrong,i.lineWidth=1.5,i.stroke()),i.fillStyle=f.textColor||o.tagText,i.fillText(u,h,l+.5),n.push({id:f.id,marker:f,x:h,y:l,r:Math.max(v,b)/2});continue}p&&(i.beginPath(),i.arc(h,l,m+4,0,Math.PI*2),i.fillStyle="rgba(255,255,255,0.14)",i.fill()),f.shape==="flag"?bt(i,h,l,m,c):(vt(i,f.shape,h,l,m),i.fillStyle=c,i.fill()),f.text&&(i.fillStyle=f.textColor||o.text,i.fillText(f.text,h,r>=0?l+m+9:l-m-9)),n.push({id:f.id,marker:f,x:h,y:l,r:m+3})}return i.restore(),n}class K{constructor(t,e={}){if(!t)throw new Error("Chart: container element is required");this.container=t,this.theme={...P,...e.theme||{}},this.options={volumeRatio:.18,magnet:!0,animate:!0,...e},this.bars=[],this.feed=null,this._unsub=null,this._loadingHistory=!1,this._exhausted=!1,this._listeners={crosshair:new Set,visibleRange:new Set,markerClick:new Set,markerHover:new Set},this._markers=W(e.markers),this.priceLines=Array.isArray(e.priceLines)?e.priceLines.slice():[],this.zones=Array.isArray(e.zones)?e.zones.slice():[],this._markerHits=[],this._hoverMarkerId=null,this._resolveKey="",this.layers=new L(t,["base","main","overlay"]),this.ts=new H(e.timeScale),this.ps=new O(e.priceScale),this.live=new U,this.live.enabled=this.options.animate!==!1,this.inertia=new j,this.cursor=null,this.plot={x:0,y:0,w:1,h:1},this.loop=new J((s,n)=>this._frame(s,n)),this.layers.onResize=()=>{this._layout(),this.loop.invalidate("all")},this._layout(),this._bindEvents(),this.loop.start()}_layout(){const{width:t,height:e}=this.layers,s=Math.max(1,t-this.theme.priceAxisWidth),n=Math.max(1,e-this.theme.timeAxisHeight);this.plot={x:0,y:0,w:s,h:n},this.ts.resize(s),this.ps.layout(0,n)}setData(t){this.bars=Array.isArray(t)?t.slice():[],this._exhausted=!1,this.bars.length>1&&(this.ts.timeframeMs=this.bars[1].time-this.bars[0].time),this.ts.setBarCount(this.bars.length),this.ts.snapToRealtime(),this.live.reset(),this.ps._primed=!1,this.loop.invalidate("all")}update(t){if(!t)return;const e=this.bars.length;if(e&&this.bars[e-1].time===t.time)this.bars[e-1]=t;else{this.append(t);return}this.live.setTarget(t),this.loop.invalidate("main")}append(t){if(!t)return;const e=this.bars.length;e&&t.time<=this.bars[e-1].time?this.bars[e-1]=t:(this.bars.push(t),this.ts.setBarCount(this.bars.length)),this.live.setTarget(t),this.loop.invalidate("main")}async setFeed(t){if(this.detachFeed(),this.feed=t,!t)return;this.ts.timeframeMs=t.timeframe||this.ts.timeframeMs;const e=await t.getBars({symbol:t.symbol,timeframe:t.timeframe,to:null,limit:this.options.initialBars||1500});this.setData(e),typeof t.prime=="function"&&t.prime(e[e.length-1]),this._unsub=t.subscribe(s=>{!s||!s.bar||(s.type==="append"?this.append(s.bar):this.update(s.bar))})}detachFeed(){this._unsub&&this._unsub(),this._unsub=null,this.feed=null}async _maybeLoadHistory(){if(this._loadingHistory||this._exhausted||!this.feed)return;const{from:t}=this.ts.visibleRange();if(!(t>80||!this.bars.length)){this._loadingHistory=!0;try{const e=this.bars[0].time,s=await this.feed.getBars({symbol:this.feed.symbol,timeframe:this.feed.timeframe,to:e,limit:1e3});if(!s||!s.length)this._exhausted=!0;else{const n=s.filter(o=>o.time<e);if(!n.length)this._exhausted=!0;else{this.bars=n.concat(this.bars);const o=this.ts.follow;this.ts.barCount=this.bars.length,this.ts._right.jump(this.ts._right.value+n.length),this.ts._right.set(this.ts._right.target+n.length),this.ts.follow=o,this.loop.invalidate("all")}}}catch(e){console.error("[Emberwick] history load failed",e),this._exhausted=!0}finally{this._loadingHistory=!1}}}_bindEvents(){const t=this.container;t.style.touchAction="none",t.style.cursor="crosshair";let e=!1,s=null,n=0,o=0,a=0,f=!1;const h=new Map;let l=0;const m=r=>{const c=t.getBoundingClientRect();return{x:r.clientX-c.left,y:r.clientY-c.top}};this._onDown=r=>{if(h.set(r.pointerId,m(r)),h.size===2){const[p,u]=[...h.values()];l=Math.hypot(p.x-u.x,p.y-u.y),e=!1;return}const c=m(r);e=!0,f=!1,s=c.x>this.plot.w?"price":c.y>this.plot.h?"time":"pan",n=c.x,o=c.y,a=performance.now(),this.inertia.stop(),t.setPointerCapture(r.pointerId)},this._onMove=r=>{const c=m(r);if(h.has(r.pointerId)&&h.set(r.pointerId,c),h.size===2){const[M,y]=[...h.values()],g=Math.hypot(M.x-y.x,M.y-y.y);if(l>0&&g>0){const d=(M.x+y.x)/2;this.ts.zoomAt(d,g/l),this.loop.invalidate("all")}l=g;return}if(this.cursor=c,this._emitCrosshair(c),this.loop.invalidate("overlay"),!e)return;const p=performance.now(),u=p-a,v=c.x-n,b=c.y-o;(Math.abs(v)>1||Math.abs(b)>1)&&(f=!0),s==="pan"?(this.ts.panBy(v),this.inertia.sample(v,u),this.loop.invalidate("all"),this._maybeLoadHistory()):s==="price"?(this.ps.scaleBy(1+b/220),this.loop.invalidate("all")):s==="time"&&(this.ts.zoomAt(this.plot.w,1-v/260),this.loop.invalidate("all")),n=c.x,o=c.y,a=p},this._onUp=r=>{h.delete(r.pointerId),h.size<2&&(l=0),e&&s==="pan"&&f&&(this.inertia.release(),this.loop.invalidate("all")),e=!1,s=null;try{t.releasePointerCapture(r.pointerId)}catch{}},this._onLeave=()=>{this.cursor=null,this._emitCrosshair(null),this.loop.invalidate("overlay")},this._onWheel=r=>{r.preventDefault();const c=t.getBoundingClientRect(),p=r.clientX-c.left,u=Math.pow(.999,r.deltaY);this.ts.zoomAt(p,u),this.loop.invalidate("all"),this._maybeLoadHistory()},this._onDbl=()=>{this.ts.reset(),this.ps.resetAuto(),this.loop.invalidate("all")},this._onKey=r=>{const c=r.shiftKey?120:40;if(r.key==="ArrowLeft")this.ts.panBy(c),this.loop.invalidate("all"),this._maybeLoadHistory();else if(r.key==="ArrowRight")this.ts.panBy(-c),this.loop.invalidate("all");else if(r.key==="+"||r.key==="=")this.ts.zoomAt(this.plot.w/2,1.2),this.loop.invalidate("all");else if(r.key==="-"||r.key==="_")this.ts.zoomAt(this.plot.w/2,.8),this.loop.invalidate("all");else return;r.preventDefault()},this._onClick=r=>{if(f||!this._listeners.markerClick.size)return;const c=m(r),p=this.markerAt(c.x,c.y);if(p)for(const u of this._listeners.markerClick)u(p)},t.addEventListener("click",this._onClick),t.addEventListener("pointerdown",this._onDown),t.addEventListener("pointermove",this._onMove),t.addEventListener("pointerup",this._onUp),t.addEventListener("pointercancel",this._onUp),t.addEventListener("pointerleave",this._onLeave),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("dblclick",this._onDbl),t.addEventListener("keydown",this._onKey),t.hasAttribute("tabindex")||t.setAttribute("tabindex","0")}_emitCrosshair(t){if(this._listeners.crosshair.size){let e=null;if(t&&this.bars.length&&t.x<=this.plot.w&&t.y<=this.plot.h){const s=Math.round(this.ts.index(t.x)),n=this.bars[s];n&&(e={index:s,bar:n,price:this.ps.price(t.y)})}for(const s of this._listeners.crosshair)s(e)}this._updateHover(t)}markerAt(t,e){const s=this._markerHits;for(let n=s.length-1;n>=0;n--){const o=s[n],a=t-o.x,f=e-o.y;if(a*a+f*f<=o.r*o.r)return o.marker}return null}_updateHover(t){const e=t?this.markerAt(t.x,t.y):null,s=e?e.id:null;if(s!==this._hoverMarkerId){this._hoverMarkerId=s,this.container.style.cursor=e?"pointer":"crosshair",this.loop.invalidate("main");for(const n of this._listeners.markerHover)n(e)}}subscribe(t,e){const s=this._listeners[t];if(!s)throw new Error(`Chart: unknown event "${t}"`);return s.add(e),()=>s.delete(e)}setMarkers(t){this._markers=W(t),this._resolveKey="",this.loop.invalidate("main")}getMarkers(){return this._markers.slice()}addMarker(t){this.setMarkers(this._markers.concat([t]))}removeMarker(t){const e=String(t);this.setMarkers(this._markers.filter(s=>s.id!==e))}clearMarkers(){this.setMarkers([])}setPriceLines(t){this.priceLines=Array.isArray(t)?t.slice():[],this.loop.invalidate("main")}setZones(t){this.zones=Array.isArray(t)?t.slice():[],this.loop.invalidate("all")}_frame(t,e){let s=!1;this.ts.tick(e)&&(s=!0);const n=this.inertia.tick(e);n&&(this.ts.panBy(n),s=!0,this._maybeLoadHistory()),this.live.tick(e)&&(s=!0);const{from:o,to:a}=this.ts.visibleRange(),f=this.bars.length-1,h=this.bars.length?this.live.read(this.bars[f]):null,l=h&&a>=f?h:null;this.ps.fit(this.bars,o,a,l),this.ps.tick(e)&&(s=!0);const m=s||t.has("all")||t.has("base")||t.has("main"),r={theme:this.theme,ts:this.ts,ps:this.ps,plot:this.plot,bars:this.bars,width:this.layers.width,height:this.layers.height,live:l,volumeRatio:this.options.volumeRatio,cursor:this.cursor,magnet:this.options.magnet,priceLines:this.priceLines,zones:this.zones};if(this._markers.length){const c=this.bars.length+":"+(this.bars.length?this.bars[0].time:0);c!==this._resolveKey&&(dt(this._markers,this.bars),this._resolveKey=c)}return m&&(ot(this.layers.ctx.base,r),gt(this.layers.ctx.base,r),ht(this.layers.ctx.main,r),_t(this.layers.ctx.main,r),this._markerHits=wt(this.layers.ctx.main,r,mt(this._markers,r),this._hoverMarkerId)),(m||t.has("overlay"))&&at(this.layers.ctx.overlay,r),s}get fps(){return this.loop.fps}setTheme(t){this.theme={...this.theme,...t},this._layout(),this.loop.invalidate("all")}setPriceMode(t){this.ps.setMode(t),this.loop.invalidate("all")}setAnimate(t){this.live.enabled=!!t,this.loop.invalidate("all")}setMagnet(t){this.options.magnet=!!t,this.loop.invalidate("overlay")}snapToRealtime(){this.ts.snapToRealtime(),this.ps.resetAuto(),this.loop.invalidate("all")}toImage(){return this.layers.composite().toDataURL("image/png")}destroy(){const t=this.container;t.removeEventListener("pointerdown",this._onDown),t.removeEventListener("pointermove",this._onMove),t.removeEventListener("pointerup",this._onUp),t.removeEventListener("pointercancel",this._onUp),t.removeEventListener("pointerleave",this._onLeave),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("dblclick",this._onDbl),t.removeEventListener("keydown",this._onKey),t.removeEventListener("click",this._onClick),this.detachFeed(),this.loop.stop(),this.layers.destroy();for(const e of Object.values(this._listeners))e.clear();this._markers=[],this._markerHits=[],this.priceLines=[],this.zones=[],this.bars=[]}}class X{constructor({symbol:t="DEMO",timeframe:e=6e4}={}){this.symbol=t,this.timeframe=e}async getBars({symbol:t,timeframe:e,to:s,limit:n}){throw new Error("DataFeed.getBars() not implemented")}subscribe(t){return()=>{}}destroy(){}}function E(i){let t=i>>>0;return function(){t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}class yt extends X{constructor({symbol:t="EMBR",timeframe:e=6e4,seed:s=7,start:n=100,volatility:o=.0022,drift:a=2e-5,ticksPerSecond:f=8,speed:h=1}={}){super({symbol:t,timeframe:e}),this.seed=s,this.start=n,this.volatility=o,this.drift=a,this.ticksPerSecond=f,this.speed=h,this._rnd=E(s),this._handlers=new Set,this._timer=null,this._forming=null,this._last=n,this._vol=o,this._anchorTime=Math.floor(Date.now()/e)*e}_gauss(){let t=0,e=0;for(;t===0;)t=this._rnd();for(;e===0;)e=this._rnd();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e)}_step(t){const e=this._gauss();return this._vol+=(this.volatility-this._vol)*.02+Math.abs(e)*this.volatility*.015,this._vol=Math.min(this._vol,this.volatility*6),Math.max(.01,t*(1+this.drift+e*this._vol))}_makeBar(t,e){let s=e;const n=14;let o=e,a=e;for(let l=0;l<n;l++)s=this._step(s),s>o&&(o=s),s<a&&(a=s);const f=Math.max(1e-9,o-a),h=Math.round((300+this._rnd()*900)*(1+f/e*260));return{time:t,open:e,high:o,low:a,close:s,volume:h}}async getBars({to:t,limit:e=1500,timeframe:s=this.timeframe}={}){const n=t==null?this._anchorTime:t,o=[],a=n-e*s,f=E(this.seed^Math.floor(a/s)),h=this._rnd;this._rnd=f;let l=this.start*(1+(f()-.5)*.04);for(let m=0;m<e;m++){const r=a+m*s,c=this._makeBar(r,l);l=c.close,o.push(c)}return this._rnd=h,t==null&&(this._last=o.length?o[o.length-1].close:this.start),o}subscribe(t){return this._handlers.add(t),this._timer||this._start(),()=>{this._handlers.delete(t),this._handlers.size||this.stop()}}_emit(t){for(const e of this._handlers)e(t)}_start(){const t=Math.max(16,1e3/this.ticksPerSecond);this._timer=setInterval(()=>this._tick(),t)}prime(t){t&&(this._last=t.close,this._forming={...t})}_tick(){const t=this.timeframe/this.speed,e=Date.now(),s=Math.floor(e/t)*t;if(!this._forming||this._forming.time!==s){const a=this._last;this._forming={time:s,open:a,high:a,low:a,close:a,volume:0},this._emit({type:"append",bar:{...this._forming}});return}const n=this._step(this._last);this._last=n;const o=this._forming;o.close=n,n>o.high&&(o.high=n),n<o.low&&(o.low=n),o.volume+=Math.round(20+this._rnd()*120),this._emit({type:"update",bar:{...o}})}setSpeed(t){this.speed=t}setTicksPerSecond(t){this.ticksPerSecond=t,this._timer&&(this.stop(),this._start())}setPaused(t){t?this.stop():!this._timer&&this._handlers.size&&this._start()}get paused(){return!this._timer}stop(){this._timer&&clearInterval(this._timer),this._timer=null}destroy(){this.stop(),this._handlers.clear()}}function Mt(i,t){return new K(i,t)}const kt="0.2.0";w.Chart=K,w.DataFeed=X,w.Inertia=j,w.LiveCandle=U,w.PriceScale=O,w.RandomFeed=yt,w.Smoothed=S,w.TimeScale=H,w.Tween=I,w.createChart=Mt,w.defaultTheme=P,w.easeInOutCubic=Q,w.easeOutCubic=F,w.lightTheme=tt,w.mulberry32=E,w.version=kt,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(w,C){typeof exports=="object"&&typeof module!="undefined"?C(exports):typeof define=="function"&&define.amd?define(["exports"],C):(w=typeof globalThis!="undefined"?globalThis:w||self,C(w.Emberwick={}))})(this,function(w){"use strict";class C{constructor(t,e){this.container=t,this.names=e,this.canvas={},this.ctx={},this.width=0,this.height=0,this.dpr=0,this.onResize=null,getComputedStyle(t).position==="static"&&(t.style.position="relative"),e.forEach((s,n)=>{const o=document.createElement("canvas");Object.assign(o.style,{position:"absolute",left:"0",top:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:String(n+1)}),t.appendChild(o),this.canvas[s]=o,this.ctx[s]=o.getContext("2d")}),this._ro=new ResizeObserver(()=>this.measure()),this._ro.observe(t),this.measure()}measure(){const t=this.container.getBoundingClientRect(),e=Math.max(1,Math.floor(t.width)),s=Math.max(1,Math.floor(t.height)),n=Math.min(window.devicePixelRatio||1,2);if(!(e===this.width&&s===this.height&&n===this.dpr)){this.width=e,this.height=s,this.dpr=n;for(const o of this.names){const h=this.canvas[o];h.width=Math.floor(e*n),h.height=Math.floor(s*n),this.ctx[o].setTransform(n,0,0,n,0,0)}this.onResize&&this.onResize(e,s)}}composite(){const t=document.createElement("canvas");t.width=Math.floor(this.width*this.dpr),t.height=Math.floor(this.height*this.dpr);const e=t.getContext("2d");for(const s of this.names)e.drawImage(this.canvas[s],0,0);return t}destroy(){this._ro.disconnect();for(const t of this.names)this.canvas[t].remove();this.canvas={},this.ctx={}}}class J{constructor(t){this.onFrame=t,this.fps=0,this._raf=0,this._dirty=new Set,this._last=0,this._running=!1,this._frames=0,this._fpsAt=0,this._tick=this._tick.bind(this)}invalidate(...t){if(!t.length)this._dirty.add("all");else for(const e of t)this._dirty.add(e);this._schedule()}start(){this._running||(this._running=!0,this._last=performance.now(),this._fpsAt=this._last,this.invalidate("all"))}stop(){this._running=!1,this._raf&&cancelAnimationFrame(this._raf),this._raf=0}_schedule(){this._raf||!this._running||(this._raf=requestAnimationFrame(this._tick))}_tick(t){if(this._raf=0,!this._running)return;const e=Math.min(Math.max(t-this._last,1),64);this._last=t,this._frames++,t-this._fpsAt>=500&&(this.fps=Math.round(this._frames*1e3/(t-this._fpsAt)),this._frames=0,this._fpsAt=t);const s=this._dirty;this._dirty=new Set;let n=!1;try{n=this.onFrame(s,e,t)===!0}catch(o){console.error("[Emberwick] frame error",o)}(n||this._dirty.size)&&this._schedule()}}const F=i=>1-Math.pow(1-i,3),Q=i=>i<.5?4*i*i*i:1-Math.pow(-2*i+2,3)/2;class S{constructor(t=0,e=90){this.value=t,this.target=t,this.tau=e}set(t){this.target=t}jump(t){this.value=t,this.target=t}get settled(){const t=1e-9+Math.abs(this.target)*1e-6;return Math.abs(this.target-this.value)<=t}tick(t){return this.settled?(this.value=this.target,!1):(this.value+=(this.target-this.value)*(1-Math.exp(-t/this.tau)),!0)}}class I{constructor(t=200,e=F){this.duration=t,this.ease=e,this.t=t}restart(){this.t=0}get done(){return this.t>=this.duration}get progress(){return this.ease(Math.min(1,this.t/this.duration))}tick(t){return this.done?!1:(this.t+=t,!0)}}const L=(i,t,e)=>i<t?t:i>e?e:i;class H{constructor({spacing:t=9,minSpacing:e=.8,maxSpacing:s=160,rightOffset:n=12}={}){this.minSpacing=e,this.maxSpacing=s,this.rightOffset=n,this.width=0,this.barCount=0,this.follow=!0,this.timeframeMs=6e4,this._spacing=new S(t,65),this._right=new S(n,65),this._initial=t}get spacing(){return this._spacing.value}get right(){return this._right.value}resize(t){this.width=Math.max(1,t)}setBarCount(t){const e=t>this.barCount;if(this.barCount=t,this.follow){const s=t-1+this.rightOffset;e?this._right.set(s):this._right.jump(s)}}x(t){return this.width-(this._right.value-t)*this._spacing.value}index(t){return this._right.value-(this.width-t)/this._spacing.value}barWidth(){const t=this._spacing.value;return Math.max(1,Math.floor(t*.72))}visibleRange(){const t=Math.floor(this.index(0))-1,e=Math.ceil(this.index(this.width))+1;return{from:L(t,0,Math.max(0,this.barCount-1)),to:L(e,0,Math.max(0,this.barCount-1))}}_clampRight(t){const e=this.barCount-1+this.rightOffset+this.width/this._spacing.target,s=Math.min(4,this.barCount-1+this.rightOffset);return L(t,s,e)}panBy(t){if(!t)return!1;const e=this._clampRight(this._right.value-t/this._spacing.value);return this._right.jump(e),this.follow=!1,!0}zoomAt(t,e){const s=this._spacing.target,n=L(s*e,this.minSpacing,this.maxSpacing);if(Math.abs(n-s)<1e-9)return!1;const o=this.follow?this.width:t,a=this._right.target-(this.width-o)/s+(this.width-o)/n;return this._spacing.set(n),this._right.set(this._clampRight(a)),!0}snapToRealtime(){this.follow=!0,this._right.set(this.barCount-1+this.rightOffset)}reset(){this._spacing.set(this._initial),this.snapToRealtime()}tick(t){const e=this._spacing.tick(t),s=this._right.tick(t);return e||s}get settled(){return this._spacing.settled&&this._right.settled}}const x=(i,t,e)=>i<t?t:i>e?e:i;class O{constructor({mode:t="linear",tau:e=120,marginTop:s=.12,marginBottom:n=.12}={}){this.mode=t,this.marginTop=s,this.marginBottom=n,this.auto=!0,this.top=0,this.height=1,this._lo=new S(0,e),this._hi=new S(1,e),this._primed=!1}_fwd(t){return this.mode==="log"?Math.log(Math.max(t,1e-9)):t}_inv(t){return this.mode==="log"?Math.exp(t):t}setMode(t){if(t===this.mode)return;const e=this._inv(this._lo.value),s=this._inv(this._hi.value);this.mode=t,this._lo.jump(this._fwd(e)),this._hi.jump(this._fwd(s))}layout(t,e){this.top=t,this.height=Math.max(1,e)}get lo(){return this._inv(this._lo.value)}get hi(){return this._inv(this._hi.value)}y(t){const e=this._lo.value,s=this._hi.value,n=(this._fwd(t)-e)/(s-e||1);return this.top+this.height*(1-n)}price(t){const e=this._lo.value,s=this._hi.value,n=1-(t-this.top)/this.height;return this._inv(e+n*(s-e))}fit(t,e,s,n){if(!this.auto||!t.length)return;let o=1/0,h=-1/0;for(let m=e;m<=s;m++){const r=t[m];r&&(r.low<o&&(o=r.low),r.high>h&&(h=r.high))}if(n&&(n.low<o&&(o=n.low),n.high>h&&(h=n.high)),!isFinite(o)||!isFinite(h))return;let f=this._fwd(o),a=this._fwd(h),l=(a-f)*this.marginTop;l>0||(l=Math.abs(a)*.01||1),f-=l,a+=(a-f)*0+l,this._lo.set(f),this._hi.set(a),this._primed||(this._lo.jump(f),this._hi.jump(a),this._primed=!0)}scaleBy(t){this.auto=!1;const e=this._lo.target,s=this._hi.target,n=(e+s)/2,o=(s-e)/2*x(t,.2,5);this._lo.set(n-o),this._hi.set(n+o)}resetAuto(){this.auto=!0}tick(t){const e=this._lo.tick(t),s=this._hi.tick(t);return e||s}}const B={background:"#0b0e14",grid:"rgba(255,255,255,0.045)",axisLine:"rgba(255,255,255,0.10)",text:"#8b93a7",textStrong:"#e6e9ef",up:"#26a69a",down:"#ef5350",upFill:"#26a69a",downFill:"#ef5350",wickUp:"#26a69a",wickDown:"#ef5350",volumeUp:"rgba(38,166,154,0.30)",volumeDown:"rgba(239,83,80,0.30)",crosshair:"rgba(255,255,255,0.32)",labelBg:"#2a3040",labelText:"#e6e9ef",tagText:"#06080d",font:'11px ui-sans-serif, -apple-system, "Segoe UI", Roboto, sans-serif',priceAxisWidth:68,timeAxisHeight:26},tt={...B,background:"#ffffff",grid:"rgba(0,0,0,0.06)",axisLine:"rgba(0,0,0,0.14)",text:"#6b7280",textStrong:"#111827",labelBg:"#374151",volumeUp:"rgba(38,166,154,0.25)",volumeDown:"rgba(239,83,80,0.25)",crosshair:"rgba(0,0,0,0.35)",tagText:"#ffffff"};class U{constructor(t=55){this.enabled=!0,this.o=new S(0,t),this.h=new S(0,t),this.l=new S(0,t),this.c=new S(0,t),this.vol=new S(0,t*2),this.spawn=new I(240),this._has=!1,this._time=null}setTarget(t){if(!t){this._has=!1;return}(!this._has||t.time!==this._time)&&(this.o.jump(t.open),this.h.jump(t.open),this.l.jump(t.open),this.c.jump(t.open),this.vol.jump(0),this.spawn.restart(),this._time=t.time,this._has=!0),this.o.set(t.open),this.h.set(t.high),this.l.set(t.low),this.c.set(t.close),this.vol.set(t.volume||0)}reset(){this._has=!1,this._time=null}tick(t){if(!this._has)return!1;let e=!1;return this.o.tick(t)&&(e=!0),this.h.tick(t)&&(e=!0),this.l.tick(t)&&(e=!0),this.c.tick(t)&&(e=!0),this.vol.tick(t)&&(e=!0),this.spawn.tick(t)&&(e=!0),e}read(t){if(!this._has||!this.enabled||t.time!==this._time)return t;const e=this.o.value,s=this.c.value;return{time:t.time,open:e,close:s,high:Math.max(this.h.value,e,s),low:Math.min(this.l.value,e,s),volume:this.vol.value,_spawn:this.spawn.progress}}}class ${constructor({friction:t=.92,min:e=.015}={}){this.friction=t,this.min=e,this.v=0,this.active=!1}sample(t,e){if(e<=0)return;const s=t/e;this.v=this.v*.6+s*.4,this.active=!1}release(){Math.abs(this.v)>this.min&&(this.active=!0)}stop(){this.v=0,this.active=!1}tick(t){if(!this.active)return 0;const e=this.v*t;return this.v*=Math.pow(this.friction,t/16.6667),Math.abs(this.v)<this.min&&this.stop(),e}}function et(i,t){const e=i/Math.max(1,t);if(!(e>0)||!isFinite(e))return 1;const s=Math.pow(10,Math.floor(Math.log10(e))),n=e/s;return(n<1.5?1:n<3?2:n<7?5:10)*s}function R(i,t,e){const s=et(t-i,e),n=[],o=Math.ceil(i/s)*s;for(let h=o;h<=t+s*1e-9;h+=s)n.push(h);return{ticks:n,step:s}}function D(i){return!isFinite(i)||i<=0?2:i>=100?0:i>=1?2:Math.min(8,Math.ceil(-Math.log10(i))+1)}function it(i){const t=[1,2,5,10,15,20,30,60,120,240,480,960,1920,3840,7680];for(const e of t)if(e>=i)return e;return Math.ceil(i/1e3)*1e3}const A=i=>String(i).padStart(2,"0");function st(i,t){const e=new Date(i);return t>=864e5?`${e.getDate()} ${e.toLocaleString("en",{month:"short"})}`:e.getHours()===0&&e.getMinutes()===0?`${e.getDate()} ${e.toLocaleString("en",{month:"short"})}`:`${A(e.getHours())}:${A(e.getMinutes())}`}function nt(i){const t=new Date(i);return`${t.getFullYear()}-${A(t.getMonth()+1)}-${A(t.getDate())} ${A(t.getHours())}:${A(t.getMinutes())}`}function ot(i,t){const{theme:e,ts:s,ps:n,plot:o,bars:h,width:f,height:a}=t;i.clearRect(0,0,f,a),i.fillStyle=e.background,i.fillRect(0,0,f,a),i.font=e.font,i.textBaseline="middle";const l=Math.max(2,Math.floor(o.h/58)),{ticks:m,step:r}=R(n.lo,n.hi,l),c=D(r);i.strokeStyle=e.grid,i.lineWidth=1,i.beginPath();for(const p of m){const u=Math.round(n.y(p))+.5;u<o.y||u>o.y+o.h||(i.moveTo(0,u),i.lineTo(o.w,u))}i.stroke(),i.fillStyle=e.text,i.textAlign="left";for(const p of m){const u=Math.round(n.y(p));u<o.y+6||u>o.y+o.h-6||i.fillText(p.toFixed(c),o.w+8,u)}if(h.length){const p=Math.ceil(74/Math.max(1e-4,s.spacing)),u=it(p),{from:v,to:b}=s.visibleRange(),M=Math.ceil(v/u)*u;i.strokeStyle=e.grid,i.beginPath();for(let g=M;g<=b;g+=u){const d=Math.round(s.x(g))+.5;d<0||d>o.w||(i.moveTo(d,0),i.lineTo(d,o.h))}i.stroke(),i.fillStyle=e.text,i.textAlign="center";const y=o.h+e.timeAxisHeight/2;for(let g=M;g<=b;g+=u){const d=h[g];if(!d)continue;const _=Math.round(s.x(g));_<28||_>o.w-28||i.fillText(st(d.time,s.timeframeMs),_,y)}}i.strokeStyle=e.axisLine,i.beginPath(),i.moveTo(o.w+.5,0),i.lineTo(o.w+.5,o.h),i.moveTo(0,o.h+.5),i.lineTo(f,o.h+.5),i.stroke()}function ht(i,t){const{theme:e,ts:s,ps:n,plot:o,bars:h,width:f,height:a,live:l,volumeRatio:m}=t;if(i.clearRect(0,0,f,a),!h.length)return;const{from:r,to:c}=s.visibleRange(),p=s.barWidth(),u=p/2,v=p<=2,b=o.h*m,M=o.y+o.h-b;let y=0;for(let d=r;d<=c;d++){const _=h[d];_&&_.volume>y&&(y=_.volume)}if(y>0)for(let d=r;d<=c;d++){let _=h[d];if(!_)continue;l&&d===h.length-1&&(_=l);const k=s.x(d);if(k<-p||k>o.w+p)continue;const T=_.volume/y*b*.9;i.fillStyle=_.close>=_.open?e.volumeUp:e.volumeDown,i.fillRect(Math.round(k-u),M+(b-T),Math.max(1,p),T)}for(let d=r;d<=c;d++){let _=h[d];if(!_)continue;const k=d===h.length-1;l&&k&&(_=l);const T=s.x(d);if(T<-p||T>o.w+p)continue;const P=_.close>=_.open,Tt=P?e.up:e.down,Y=n.y(_.open),N=n.y(_.close),St=n.y(_.high),At=n.y(_.low);let V=1;l&&k&&typeof _._spawn=="number"&&(V=.35+.65*_._spawn);const Z=Math.round(T)+(p%2?.5:0);if(i.strokeStyle=P?e.wickUp:e.wickDown,i.lineWidth=Math.max(1,Math.min(2,p*.16)),i.beginPath(),i.moveTo(Z,St),i.lineTo(Z,At),i.stroke(),v)continue;const Ct=Math.min(Y,N),Lt=Math.max(1,Math.abs(N-Y)),G=Math.max(1,p*V);i.fillStyle=Tt,i.fillRect(Math.round(T-G/2),Math.round(Ct),Math.round(G),Math.round(Lt))}const g=l||h[h.length-1];if(g){const d=Math.round(n.y(g.close))+.5;if(d>o.y&&d<o.y+o.h){const _=g.close>=g.open;i.save(),i.setLineDash([3,3]),i.strokeStyle=_?e.up:e.down,i.lineWidth=1,i.globalAlpha=.7,i.beginPath(),i.moveTo(0,d),i.lineTo(o.w,d),i.stroke(),i.restore();const{step:k}=R(n.lo,n.hi,Math.max(2,Math.floor(o.h/58))),T=g.close.toFixed(D(k));i.font=e.font,i.textBaseline="middle",i.textAlign="left";const P=i.measureText(T).width;i.fillStyle=_?e.up:e.down,i.fillRect(o.w+1,d-9,P+14,18),i.fillStyle=e.tagText,i.fillText(T,o.w+8,d)}}}function at(i,t){const{theme:e,ts:s,ps:n,plot:o,bars:h,width:f,height:a,cursor:l,magnet:m}=t;if(i.clearRect(0,0,f,a),!l||!h.length||l.x<0||l.x>o.w||l.y<0||l.y>o.h)return;const r=Math.round(s.index(l.x)),c=h[r];let p=l.x,u=l.y;if(c&&(p=s.x(r),m)){const y=[c.open,c.high,c.low,c.close];let g=null,d=1/0;for(const _ of y){const k=n.y(_),T=Math.abs(k-l.y);T<d&&(d=T,g=k)}d<22&&(u=g)}i.save(),i.setLineDash([4,4]),i.strokeStyle=e.crosshair,i.lineWidth=1,i.beginPath(),i.moveTo(Math.round(p)+.5,0),i.lineTo(Math.round(p)+.5,o.h),i.moveTo(0,Math.round(u)+.5),i.lineTo(o.w,Math.round(u)+.5),i.stroke(),i.restore(),i.font=e.font,i.textBaseline="middle";const{step:v}=R(n.lo,n.hi,Math.max(2,Math.floor(o.h/58))),b=n.price(u).toFixed(D(v));i.textAlign="left";const M=i.measureText(b).width;if(i.fillStyle=e.labelBg,i.fillRect(o.w+1,u-9,M+14,18),i.fillStyle=e.labelText,i.fillText(b,o.w+8,u),c){const y=nt(c.time);i.textAlign="center";const g=i.measureText(y).width,d=Math.min(Math.max(p,g/2+6),o.w-g/2-6);i.fillStyle=e.labelBg,i.fillRect(d-g/2-7,o.h+3,g+14,18),i.fillStyle=e.labelText,i.fillText(y,d,o.h+12)}}const rt=["arrowUp","arrowDown","triangleUp","triangleDown","circle","square","diamond","flag","label"],lt=new Set(rt),ft={arrowUp:"belowBar",triangleUp:"belowBar",arrowDown:"aboveBar",triangleDown:"aboveBar"},ct=new Set(["aboveBar","belowBar","inBar","atPrice"]);function ut(i,t){if(!i||!isFinite(i.time))return null;const e=lt.has(i.shape)?i.shape:"circle",s=ct.has(i.position)?i.position:ft[e]||"aboveBar";return{id:i.id!=null?String(i.id):`mk${t}`,time:+i.time,price:isFinite(i.price)?+i.price:null,shape:e,position:s,color:i.color||null,textColor:i.textColor||null,text:i.text!=null?String(i.text):"",size:isFinite(i.size)&&i.size>0?+i.size:1,data:i.data,index:-1}}function j(i){if(!Array.isArray(i))return[];const t=[];for(let e=0;e<i.length;e++){const s=ut(i[e],e);s&&t.push(s)}return t.sort((e,s)=>e.time-s.time),t}function z(i,t){const e=i.length;if(!e)return-1;if(t<=i[0].time)return 0;if(t>=i[e-1].time)return e-1;let s=0,n=e-1;for(;s<=n;){const f=s+n>>1,a=i[f].time;if(a===t)return f;a<t?s=f+1:n=f-1}const o=Math.max(0,n),h=Math.min(e-1,s);return Math.abs(i[o].time-t)<=Math.abs(i[h].time-t)?o:h}function dt(i,t){for(let e=0;e<i.length;e++)i[e].index=z(t,i[e].time);return i}function mt(i,t){const{ts:e,ps:s,plot:n,bars:o,live:h}=t;if(!i.length||!o.length)return[];const{from:f,to:a}=e.visibleRange(),l=o.length-1,m=e.barWidth()<=3,r=new Map,c=[];let p=-1/0;for(const u of i){const v=u.index;if(v<0||v<f-2||v>a+2)continue;const b=h&&v===l?h:o[v];if(!b)continue;const M=e.x(v);if(M<-48||M>n.w+48)continue;if(m){if(M-p<4)continue;p=M}const y=5*u.size;let g,d=0;if(u.position==="atPrice"&&u.price!=null?g=s.y(u.price):u.position==="inBar"?g=s.y((b.high+b.low)/2):u.position==="belowBar"?(g=s.y(b.low)+y+7,d=1):(g=s.y(b.high)-y-7,d=-1),d!==0){const _=v+u.position,k=r.get(_)||0;r.set(_,k+1),g+=d*k*(y*2+5)}c.push({m:u,x:M,y:g,r:y,dir:d})}return c}const W={solid:[],dashed:[6,4],dotted:[1,3]},pt=new Set(["arrowDown","triangleDown"]);function K(i,t,e,s,n,o){const h=Math.max(0,Math.min(o,n/2,s/2));i.beginPath(),i.moveTo(t+h,e),i.lineTo(t+s-h,e),i.quadraticCurveTo(t+s,e,t+s,e+h),i.lineTo(t+s,e+n-h),i.quadraticCurveTo(t+s,e+n,t+s-h,e+n),i.lineTo(t+h,e+n),i.quadraticCurveTo(t,e+n,t,e+n-h),i.lineTo(t,e+h),i.quadraticCurveTo(t,e,t+h,e),i.closePath()}function gt(i,t){const{zones:e,theme:s,ts:n,ps:o,plot:h,bars:f}=t;if(!(!e||!e.length)){i.save(),i.font=s.font,i.textBaseline="top",i.textAlign="left";for(const a of e){let l,m,r,c;if(isFinite(a.from)&&isFinite(a.to))m=o.y(Math.max(a.from,a.to)),c=Math.max(1,o.y(Math.min(a.from,a.to))-m),l=0,r=h.w;else if(isFinite(a.fromTime)&&isFinite(a.toTime)&&f.length){const p=n.x(z(f,Math.min(a.fromTime,a.toTime))),u=n.x(z(f,Math.max(a.fromTime,a.toTime)));l=p,r=Math.max(1,u-p),m=0,c=h.h}else continue;l>h.w||l+r<0||m>h.h||m+c<0||(i.fillStyle=a.color||"rgba(38,166,154,0.10)",i.fillRect(l,m,r,c),a.border&&(i.strokeStyle=a.border,i.lineWidth=1,i.strokeRect(Math.round(l)+.5,Math.round(m)+.5,Math.round(r),Math.round(c))),a.label&&(i.fillStyle=a.labelColor||s.text,i.fillText(a.label,Math.max(6,l+6),Math.max(4,m+4))))}i.restore()}}function _t(i,t){const{priceLines:e,theme:s,ps:n,plot:o}=t;if(!e||!e.length)return;const{step:h}=R(n.lo,n.hi,Math.max(2,Math.floor(o.h/58))),f=D(h);i.save(),i.font=s.font,i.textBaseline="middle";for(const a of e){if(!a||!isFinite(a.price))continue;const l=Math.round(n.y(a.price))+.5;if(l<0||l>o.h)continue;const m=a.color||s.textStrong;if(i.setLineDash(W[a.lineStyle]||W.dashed),i.strokeStyle=m,i.lineWidth=a.lineWidth||1,i.beginPath(),i.moveTo(0,l),i.lineTo(o.w,l),i.stroke(),i.setLineDash([]),a.title){i.textAlign="left";const r=i.measureText(a.title).width;i.fillStyle=m,K(i,6,l-9,r+12,18,4),i.fill(),i.fillStyle=a.titleColor||s.tagText,i.fillText(a.title,12,l)}if(a.axisLabel!==!1){const r=a.price.toFixed(f);i.textAlign="left";const c=i.measureText(r).width;i.fillStyle=m,i.fillRect(o.w+1,l-9,c+14,18),i.fillStyle=a.tagTextColor||s.tagText,i.fillText(r,o.w+8,l)}}i.restore()}function vt(i,t,e,s,n){switch(i.beginPath(),t){case"arrowUp":i.moveTo(e,s-n),i.lineTo(e+n,s),i.lineTo(e+n*.45,s),i.lineTo(e+n*.45,s+n),i.lineTo(e-n*.45,s+n),i.lineTo(e-n*.45,s),i.lineTo(e-n,s),i.closePath();break;case"arrowDown":i.moveTo(e,s+n),i.lineTo(e+n,s),i.lineTo(e+n*.45,s),i.lineTo(e+n*.45,s-n),i.lineTo(e-n*.45,s-n),i.lineTo(e-n*.45,s),i.lineTo(e-n,s),i.closePath();break;case"triangleUp":i.moveTo(e,s-n),i.lineTo(e+n,s+n),i.lineTo(e-n,s+n),i.closePath();break;case"triangleDown":i.moveTo(e,s+n),i.lineTo(e+n,s-n),i.lineTo(e-n,s-n),i.closePath();break;case"square":i.rect(e-n,s-n,n*2,n*2);break;case"diamond":i.moveTo(e,s-n),i.lineTo(e+n,s),i.lineTo(e,s+n),i.lineTo(e-n,s),i.closePath();break;default:i.arc(e,s,n,0,Math.PI*2)}}function bt(i,t,e,s,n){i.fillStyle=n,i.fillRect(t-s*.8,e-s,Math.max(1,s*.3),s*2),i.beginPath(),i.moveTo(t-s*.5,e-s),i.lineTo(t+s,e-s*.55),i.lineTo(t-s*.5,e-s*.1),i.closePath(),i.fill()}function wt(i,t,e,s){const n=[];if(!e||!e.length)return n;const{theme:o}=t;i.save(),i.font=o.font,i.textAlign="center",i.textBaseline="middle";for(const h of e){const{m:f,x:a,y:l,r:m,dir:r}=h,c=f.color||(pt.has(f.shape)?o.down:o.up),p=s!=null&&f.id===s;if(f.shape==="label"){const u=f.text||"•",v=i.measureText(u).width+14,b=18*f.size;K(i,a-v/2,l-b/2,v,b,4),i.fillStyle=c,i.fill(),p&&(i.strokeStyle=o.textStrong,i.lineWidth=1.5,i.stroke()),i.fillStyle=f.textColor||o.tagText,i.fillText(u,a,l+.5),n.push({id:f.id,marker:f,x:a,y:l,r:Math.max(v,b)/2});continue}p&&(i.beginPath(),i.arc(a,l,m+4,0,Math.PI*2),i.fillStyle="rgba(255,255,255,0.14)",i.fill()),f.shape==="flag"?bt(i,a,l,m,c):(vt(i,f.shape,a,l,m),i.fillStyle=c,i.fill()),f.text&&(i.fillStyle=f.textColor||o.text,i.fillText(f.text,a,r>=0?l+m+9:l-m-9)),n.push({id:f.id,marker:f,x:a,y:l,r:m+3})}return i.restore(),n}class q{constructor(t,e={}){if(!t)throw new Error("Chart: container element is required");this.container=t,this.theme={...B,...e.theme||{}},this.options={volumeRatio:.18,magnet:!0,animate:!0,...e},this.bars=[],this.feed=null,this._unsub=null,this._loadingHistory=!1,this._exhausted=!1,this._listeners={crosshair:new Set,visibleRange:new Set,markerClick:new Set,markerHover:new Set},this._markers=j(e.markers),this.priceLines=Array.isArray(e.priceLines)?e.priceLines.slice():[],this.zones=Array.isArray(e.zones)?e.zones.slice():[],this._markerHits=[],this._hoverMarkerId=null,this._resolveKey="",this.layers=new C(t,["base","main","overlay"]),this.ts=new H(e.timeScale),this.ps=new O(e.priceScale),this.live=new U,this.live.enabled=this.options.animate!==!1,this.inertia=new $,this.cursor=null,this.plot={x:0,y:0,w:1,h:1},this.loop=new J((s,n)=>this._frame(s,n)),this.layers.onResize=()=>{this._layout(),this.loop.invalidate("all")},this._layout(),this._bindEvents(),this.loop.start()}_layout(){const{width:t,height:e}=this.layers,s=Math.max(1,t-this.theme.priceAxisWidth),n=Math.max(1,e-this.theme.timeAxisHeight);this.plot={x:0,y:0,w:s,h:n},this.ts.resize(s),this.ps.layout(0,n)}setData(t){this.bars=Array.isArray(t)?t.slice():[],this._exhausted=!1,this.bars.length>1&&(this.ts.timeframeMs=this.bars[1].time-this.bars[0].time),this.ts.setBarCount(this.bars.length),this.ts.snapToRealtime(),this.live.reset(),this.ps._primed=!1,this.loop.invalidate("all")}update(t){if(!t)return;const e=this.bars.length;if(e&&this.bars[e-1].time===t.time)this.bars[e-1]=t;else{this.append(t);return}this.live.setTarget(t),this.loop.invalidate("main")}append(t){if(!t)return;const e=this.bars.length;e&&t.time<=this.bars[e-1].time?this.bars[e-1]=t:(this.bars.push(t),this.ts.setBarCount(this.bars.length)),this.live.setTarget(t),this.loop.invalidate("main")}async setFeed(t){if(this.detachFeed(),this.feed=t,!t)return;this.ts.timeframeMs=t.timeframe||this.ts.timeframeMs;const e=await t.getBars({symbol:t.symbol,timeframe:t.timeframe,to:null,limit:this.options.initialBars||1500});this.setData(e),typeof t.prime=="function"&&t.prime(e[e.length-1]),this._unsub=t.subscribe(s=>{!s||!s.bar||(s.type==="append"?this.append(s.bar):this.update(s.bar))})}detachFeed(){this._unsub&&this._unsub(),this._unsub=null,this.feed=null}async _maybeLoadHistory(){if(this._loadingHistory||this._exhausted||!this.feed)return;const{from:t}=this.ts.visibleRange();if(!(t>80||!this.bars.length)){this._loadingHistory=!0;try{const e=this.bars[0].time,s=await this.feed.getBars({symbol:this.feed.symbol,timeframe:this.feed.timeframe,to:e,limit:1e3});if(!s||!s.length)this._exhausted=!0;else{const n=s.filter(o=>o.time<e);if(!n.length)this._exhausted=!0;else{this.bars=n.concat(this.bars);const o=this.ts.follow;this.ts.barCount=this.bars.length,this.ts._right.jump(this.ts._right.value+n.length),this.ts._right.set(this.ts._right.target+n.length),this.ts.follow=o,this.loop.invalidate("all")}}}catch(e){console.error("[Emberwick] history load failed",e),this._exhausted=!0}finally{this._loadingHistory=!1}}}_bindEvents(){const t=this.container;t.style.touchAction="none",t.style.cursor="crosshair";let e=!1,s=null,n=0,o=0,h=0,f=!1;const a=new Map;let l=0;const m=r=>{const c=t.getBoundingClientRect();return{x:r.clientX-c.left,y:r.clientY-c.top}};this._onDown=r=>{if(a.set(r.pointerId,m(r)),a.size===2){const[p,u]=[...a.values()];l=Math.hypot(p.x-u.x,p.y-u.y),e=!1;return}const c=m(r);e=!0,f=!1,s=c.x>this.plot.w?"price":c.y>this.plot.h?"time":"pan",n=c.x,o=c.y,h=performance.now(),this.inertia.stop(),t.setPointerCapture(r.pointerId)},this._onMove=r=>{const c=m(r);if(a.has(r.pointerId)&&a.set(r.pointerId,c),a.size===2){const[M,y]=[...a.values()],g=Math.hypot(M.x-y.x,M.y-y.y);if(l>0&&g>0){const d=(M.x+y.x)/2;this.ts.zoomAt(d,g/l),this.loop.invalidate("all")}l=g;return}if(this.cursor=c,this._emitCrosshair(c),this.loop.invalidate("overlay"),!e)return;const p=performance.now(),u=p-h,v=c.x-n,b=c.y-o;(Math.abs(v)>1||Math.abs(b)>1)&&(f=!0),s==="pan"?(this.ts.panBy(v),this.inertia.sample(v,u),this.loop.invalidate("all"),this._maybeLoadHistory()):s==="price"?(this.ps.scaleBy(1+b/220),this.loop.invalidate("all")):s==="time"&&(this.ts.zoomAt(this.plot.w,1-v/260),this.loop.invalidate("all")),n=c.x,o=c.y,h=p},this._onUp=r=>{a.delete(r.pointerId),a.size<2&&(l=0),e&&s==="pan"&&f&&(this.inertia.release(),this.loop.invalidate("all")),e=!1,s=null;try{t.releasePointerCapture(r.pointerId)}catch{}},this._onLeave=()=>{this.cursor=null,this._emitCrosshair(null),this.loop.invalidate("overlay")},this._onWheel=r=>{r.preventDefault();const c=t.getBoundingClientRect(),p=r.clientX-c.left,u=Math.pow(.999,r.deltaY);this.ts.zoomAt(p,u),this.loop.invalidate("all"),this._maybeLoadHistory()},this._onDbl=()=>{this.ts.reset(),this.ps.resetAuto(),this.loop.invalidate("all")},this._onKey=r=>{const c=r.shiftKey?120:40;if(r.key==="ArrowLeft")this.ts.panBy(c),this.loop.invalidate("all"),this._maybeLoadHistory();else if(r.key==="ArrowRight")this.ts.panBy(-c),this.loop.invalidate("all");else if(r.key==="+"||r.key==="=")this.ts.zoomAt(this.plot.w/2,1.2),this.loop.invalidate("all");else if(r.key==="-"||r.key==="_")this.ts.zoomAt(this.plot.w/2,.8),this.loop.invalidate("all");else return;r.preventDefault()},this._onClick=r=>{if(f||!this._listeners.markerClick.size)return;const c=m(r),p=this.markerAt(c.x,c.y);if(p)for(const u of this._listeners.markerClick)u(p)},t.addEventListener("click",this._onClick),t.addEventListener("pointerdown",this._onDown),t.addEventListener("pointermove",this._onMove),t.addEventListener("pointerup",this._onUp),t.addEventListener("pointercancel",this._onUp),t.addEventListener("pointerleave",this._onLeave),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("dblclick",this._onDbl),t.addEventListener("keydown",this._onKey),t.hasAttribute("tabindex")||t.setAttribute("tabindex","0")}_emitCrosshair(t){if(this._listeners.crosshair.size){let e=null;if(t&&this.bars.length&&t.x<=this.plot.w&&t.y<=this.plot.h){const s=Math.round(this.ts.index(t.x)),n=this.bars[s];n&&(e={index:s,bar:n,price:this.ps.price(t.y)})}for(const s of this._listeners.crosshair)s(e)}this._updateHover(t)}markerAt(t,e){const s=this._markerHits;for(let n=s.length-1;n>=0;n--){const o=s[n],h=t-o.x,f=e-o.y;if(h*h+f*f<=o.r*o.r)return o.marker}return null}_updateHover(t){const e=t?this.markerAt(t.x,t.y):null,s=e?e.id:null;if(s!==this._hoverMarkerId){this._hoverMarkerId=s,this.container.style.cursor=e?"pointer":"crosshair",this.loop.invalidate("main");for(const n of this._listeners.markerHover)n(e)}}subscribe(t,e){const s=this._listeners[t];if(!s)throw new Error(`Chart: unknown event "${t}"`);if(s.add(e),t==="visibleRange"){const n=this.visibleRange();this._rangeKey=this._rangeIdentity(n),e(n)}return()=>s.delete(e)}visibleRange(){const{from:t,to:e}=this.ts.visibleRange();return this._rangePayload(t,e)}_rangePayload(t,e){const s=this.bars.length;return{from:t,to:e,fromTime:s?this.bars[t].time:null,toTime:s?this.bars[e].time:null,barCount:s,spacing:this.ts.spacing,settled:this.ts.settled}}_rangeIdentity(t){return`${t.from}:${t.to}:${t.fromTime}:${t.toTime}:${t.settled?1:0}`}_emitVisibleRange(t,e){const s=this._listeners.visibleRange;if(!s.size)return;const n=this._rangePayload(t,e),o=this._rangeIdentity(n);if(o!==this._rangeKey){this._rangeKey=o;for(const h of s)h(n)}}setMarkers(t){this._markers=j(t),this._resolveKey="",this.loop.invalidate("main")}getMarkers(){return this._markers.slice()}addMarker(t){this.setMarkers(this._markers.concat([t]))}removeMarker(t){const e=String(t);this.setMarkers(this._markers.filter(s=>s.id!==e))}clearMarkers(){this.setMarkers([])}setPriceLines(t){this.priceLines=Array.isArray(t)?t.slice():[],this.loop.invalidate("main")}setZones(t){this.zones=Array.isArray(t)?t.slice():[],this.loop.invalidate("all")}_frame(t,e){let s=!1;this.ts.tick(e)&&(s=!0);const n=this.inertia.tick(e);n&&(this.ts.panBy(n),s=!0,this._maybeLoadHistory()),this.live.tick(e)&&(s=!0);const{from:o,to:h}=this.ts.visibleRange(),f=this.bars.length-1,a=this.bars.length?this.live.read(this.bars[f]):null,l=a&&h>=f?a:null;this.ps.fit(this.bars,o,h,l),this.ps.tick(e)&&(s=!0);const m=s||t.has("all")||t.has("base")||t.has("main"),r={theme:this.theme,ts:this.ts,ps:this.ps,plot:this.plot,bars:this.bars,width:this.layers.width,height:this.layers.height,live:l,volumeRatio:this.options.volumeRatio,cursor:this.cursor,magnet:this.options.magnet,priceLines:this.priceLines,zones:this.zones};if(this._markers.length){const c=this.bars.length+":"+(this.bars.length?this.bars[0].time:0);c!==this._resolveKey&&(dt(this._markers,this.bars),this._resolveKey=c)}return m&&(ot(this.layers.ctx.base,r),gt(this.layers.ctx.base,r),ht(this.layers.ctx.main,r),_t(this.layers.ctx.main,r),this._markerHits=wt(this.layers.ctx.main,r,mt(this._markers,r),this._hoverMarkerId)),(m||t.has("overlay"))&&at(this.layers.ctx.overlay,r),this._emitVisibleRange(o,h),s}get fps(){return this.loop.fps}setTheme(t){this.theme={...this.theme,...t},this._layout(),this.loop.invalidate("all")}setPriceMode(t){this.ps.setMode(t),this.loop.invalidate("all")}setAnimate(t){this.live.enabled=!!t,this.loop.invalidate("all")}setMagnet(t){this.options.magnet=!!t,this.loop.invalidate("overlay")}snapToRealtime(){this.ts.snapToRealtime(),this.ps.resetAuto(),this.loop.invalidate("all")}toImage(){return this.layers.composite().toDataURL("image/png")}destroy(){const t=this.container;t.removeEventListener("pointerdown",this._onDown),t.removeEventListener("pointermove",this._onMove),t.removeEventListener("pointerup",this._onUp),t.removeEventListener("pointercancel",this._onUp),t.removeEventListener("pointerleave",this._onLeave),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("dblclick",this._onDbl),t.removeEventListener("keydown",this._onKey),t.removeEventListener("click",this._onClick),this.detachFeed(),this.loop.stop(),this.layers.destroy();for(const e of Object.values(this._listeners))e.clear();this._markers=[],this._markerHits=[],this.priceLines=[],this.zones=[],this.bars=[]}}class X{constructor({symbol:t="DEMO",timeframe:e=6e4}={}){this.symbol=t,this.timeframe=e}async getBars({symbol:t,timeframe:e,to:s,limit:n}){throw new Error("DataFeed.getBars() not implemented")}subscribe(t){return()=>{}}destroy(){}}function E(i){let t=i>>>0;return function(){t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}class yt extends X{constructor({symbol:t="EMBR",timeframe:e=6e4,seed:s=7,start:n=100,volatility:o=.0022,drift:h=2e-5,ticksPerSecond:f=8,speed:a=1}={}){super({symbol:t,timeframe:e}),this.seed=s,this.start=n,this.volatility=o,this.drift=h,this.ticksPerSecond=f,this.speed=a,this._rnd=E(s),this._handlers=new Set,this._timer=null,this._forming=null,this._last=n,this._vol=o,this._anchorTime=Math.floor(Date.now()/e)*e}_gauss(){let t=0,e=0;for(;t===0;)t=this._rnd();for(;e===0;)e=this._rnd();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e)}_step(t){const e=this._gauss();return this._vol+=(this.volatility-this._vol)*.02+Math.abs(e)*this.volatility*.015,this._vol=Math.min(this._vol,this.volatility*6),Math.max(.01,t*(1+this.drift+e*this._vol))}_makeBar(t,e){let s=e;const n=14;let o=e,h=e;for(let l=0;l<n;l++)s=this._step(s),s>o&&(o=s),s<h&&(h=s);const f=Math.max(1e-9,o-h),a=Math.round((300+this._rnd()*900)*(1+f/e*260));return{time:t,open:e,high:o,low:h,close:s,volume:a}}async getBars({to:t,limit:e=1500,timeframe:s=this.timeframe}={}){const n=t==null?this._anchorTime:t,o=[],h=n-e*s,f=E(this.seed^Math.floor(h/s)),a=this._rnd;this._rnd=f;let l=this.start*(1+(f()-.5)*.04);for(let m=0;m<e;m++){const r=h+m*s,c=this._makeBar(r,l);l=c.close,o.push(c)}return this._rnd=a,t==null&&(this._last=o.length?o[o.length-1].close:this.start),o}subscribe(t){return this._handlers.add(t),this._timer||this._start(),()=>{this._handlers.delete(t),this._handlers.size||this.stop()}}_emit(t){for(const e of this._handlers)e(t)}_start(){const t=Math.max(16,1e3/this.ticksPerSecond);this._timer=setInterval(()=>this._tick(),t)}prime(t){t&&(this._last=t.close,this._forming={...t})}_tick(){const t=this.timeframe/this.speed,e=Date.now(),s=Math.floor(e/t)*t;if(!this._forming||this._forming.time!==s){const h=this._last;this._forming={time:s,open:h,high:h,low:h,close:h,volume:0},this._emit({type:"append",bar:{...this._forming}});return}const n=this._step(this._last);this._last=n;const o=this._forming;o.close=n,n>o.high&&(o.high=n),n<o.low&&(o.low=n),o.volume+=Math.round(20+this._rnd()*120),this._emit({type:"update",bar:{...o}})}setSpeed(t){this.speed=t}setTicksPerSecond(t){this.ticksPerSecond=t,this._timer&&(this.stop(),this._start())}setPaused(t){t?this.stop():!this._timer&&this._handlers.size&&this._start()}get paused(){return!this._timer}stop(){this._timer&&clearInterval(this._timer),this._timer=null}destroy(){this.stop(),this._handlers.clear()}}function Mt(i,t){return new q(i,t)}const kt="0.2.0";w.Chart=q,w.DataFeed=X,w.Inertia=$,w.LiveCandle=U,w.PriceScale=O,w.RandomFeed=yt,w.Smoothed=S,w.TimeScale=H,w.Tween=I,w.createChart=Mt,w.defaultTheme=B,w.easeInOutCubic=Q,w.easeOutCubic=F,w.lightTheme=tt,w.mulberry32=E,w.version=kt,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})});
|
|
2
2
|
//# sourceMappingURL=emberwick.umd.js.map
|