diff --git a/.gitignore b/.gitignore
index e1d488d12..927b85f33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
.DS_Store
/app-next
-/app-html
/datasets
/datasets2
/datasets_*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 074558e52..7e443a7b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@

+## v. 0.4.0 | WIP
+
+
+
### Parser
- Changed the block iterator from a custom version of [bitcoin-explorer](https://crates.io/crates/bitcoin-explorer) to the homemade [biter](https://crates.io/crates/biter) which allows the parser to run alongside `bitcoind`
diff --git a/app-html/_oklch.js b/app-html/_oklch.js
new file mode 100644
index 000000000..8bafe9f25
--- /dev/null
+++ b/app-html/_oklch.js
@@ -0,0 +1,48 @@
+merge = async (c1, c2) => {
+ function sleep(ms) {
+ return new Promise((resolve) => {
+ setTimeout(resolve, ms);
+ });
+ }
+
+ async function hexToOklch(c) {
+ hex.value = c;
+
+ hex.dispatchEvent(new Event("change"));
+
+ await sleep(1);
+
+ console.log(oklch.value);
+
+ const s = oklch.value.slice(6, -1).split(" ");
+
+ let [lightness, chroma, hue] = s;
+
+ lightness = Number(lightness.slice(0, -1));
+ chroma = Number(chroma);
+ hue = Number(hue);
+
+ return [lightness, chroma, hue];
+ }
+
+ function average(a, b) {
+ return (a + b) / 2;
+ }
+
+ const [lightness1, chroma1, hue1] = await hexToOklch(c1);
+ console.log(lightness1, chroma1, hue1);
+ const [lightness2, chroma2, hue2] = await hexToOklch(c2);
+ console.log(lightness2, chroma2, hue2);
+
+ const lightness = average(lightness1, lightness2);
+ const chroma = average(chroma1, chroma2);
+ const hue = average(hue1, hue2);
+
+ oklch.value = `oklch(${lightness}% ${chroma} ${hue})`;
+ console.log(oklch.value);
+ oklch.dispatchEvent(new Event("change"));
+
+ await sleep(10);
+
+ console.log(hex.value);
+};
diff --git a/app-html/fonts/Satoshi.var.woff2 b/app-html/fonts/Satoshi.var.woff2
new file mode 100644
index 000000000..b00e833ed
Binary files /dev/null and b/app-html/fonts/Satoshi.var.woff2 differ
diff --git a/app-html/index.html b/app-html/index.html
new file mode 100644
index 000000000..9519547e6
--- /dev/null
+++ b/app-html/index.html
@@ -0,0 +1,937 @@
+
+
+
+
+ kibō
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ General
+
+
+ Options for the application's color scheme
+
+
+
+
+ Donations
+
+
+ A massive thank you to everybody who sent their hard earned sats. This
+ project, by being completely free, is very dependent and only founded
+ by the goodwill of fellow ₿itcoiners.
+
+
+
+ And everybody else !
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Charts are displayed via
+
+ Trading View
+
+ 's
+
+ Lightweight Charts™
+
+ library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ formerly satonomics
+
+
+ Version:
+
+ 0.4.0
+
+
+
+
+
+
+
+
+
+
diff --git a/app-html/jsconfig.json b/app-html/jsconfig.json
new file mode 100644
index 000000000..03f537feb
--- /dev/null
+++ b/app-html/jsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "checkJs": true,
+ "strict": true,
+ "target": "ESNext",
+ "module": "ESNext"
+ },
+ "exclude": ["assets", "libraries"]
+}
diff --git a/app-html/libraries/lightweight-charts/standalone.mjs b/app-html/libraries/lightweight-charts/standalone.mjs
new file mode 100644
index 000000000..b814bc280
--- /dev/null
+++ b/app-html/libraries/lightweight-charts/standalone.mjs
@@ -0,0 +1,7 @@
+/*!
+ * @license
+ * TradingView Lightweight Charts™ v4.2.0
+ * Copyright (c) 2024 TradingView, Inc.
+ * Licensed under Apache License 2.0 https://www.apache.org/licenses/LICENSE-2.0
+ */
+const t={upColor:"#26a69a",downColor:"#ef5350",wickVisible:!0,borderVisible:!0,borderColor:"#378658",borderUpColor:"#26a69a",borderDownColor:"#ef5350",wickColor:"#737375",wickUpColor:"#26a69a",wickDownColor:"#ef5350"},i={upColor:"#26a69a",downColor:"#ef5350",openVisible:!0,thinBars:!0},n={color:"#2196f3",lineStyle:0,lineWidth:3,lineType:0,lineVisible:!0,crosshairMarkerVisible:!0,crosshairMarkerRadius:4,crosshairMarkerBorderColor:"",crosshairMarkerBorderWidth:2,crosshairMarkerBackgroundColor:"",lastPriceAnimation:0,pointMarkersVisible:!1},s={topColor:"rgba( 46, 220, 135, 0.4)",bottomColor:"rgba( 40, 221, 100, 0)",invertFilledArea:!1,lineColor:"#33D778",lineStyle:0,lineWidth:3,lineType:0,lineVisible:!0,crosshairMarkerVisible:!0,crosshairMarkerRadius:4,crosshairMarkerBorderColor:"",crosshairMarkerBorderWidth:2,crosshairMarkerBackgroundColor:"",lastPriceAnimation:0,pointMarkersVisible:!1},e={baseValue:{type:"price",price:0},topFillColor1:"rgba(38, 166, 154, 0.28)",topFillColor2:"rgba(38, 166, 154, 0.05)",topLineColor:"rgba(38, 166, 154, 1)",bottomFillColor1:"rgba(239, 83, 80, 0.05)",bottomFillColor2:"rgba(239, 83, 80, 0.28)",bottomLineColor:"rgba(239, 83, 80, 1)",lineWidth:3,lineStyle:0,lineType:0,lineVisible:!0,crosshairMarkerVisible:!0,crosshairMarkerRadius:4,crosshairMarkerBorderColor:"",crosshairMarkerBorderWidth:2,crosshairMarkerBackgroundColor:"",lastPriceAnimation:0,pointMarkersVisible:!1},r={color:"#26a69a",base:0},h={color:"#2196f3"},l={title:"",visible:!0,lastValueVisible:!0,priceLineVisible:!0,priceLineSource:0,priceLineWidth:1,priceLineColor:"",priceLineStyle:2,baseLineVisible:!0,baseLineWidth:1,baseLineColor:"#B2B5BE",baseLineStyle:0,priceFormat:{type:"price",precision:2,minMove:.01}};var a,o;function _(t,i){const n={0:[],1:[t.lineWidth,t.lineWidth],2:[2*t.lineWidth,2*t.lineWidth],3:[6*t.lineWidth,6*t.lineWidth],4:[t.lineWidth,4*t.lineWidth]}[i];t.setLineDash(n)}function u(t,i,n,s){t.beginPath();const e=t.lineWidth%2?.5:0;t.moveTo(n,i+e),t.lineTo(s,i+e),t.stroke()}function c(t,i){if(!t)throw new Error("Assertion failed"+(i?": "+i:""))}function d(t){if(void 0===t)throw new Error("Value is undefined");return t}function f(t){if(null===t)throw new Error("Value is null");return t}function v(t){return f(d(t))}!function(t){t[t.Simple=0]="Simple",t[t.WithSteps=1]="WithSteps",t[t.Curved=2]="Curved"}(a||(a={})),function(t){t[t.Solid=0]="Solid",t[t.Dotted=1]="Dotted",t[t.Dashed=2]="Dashed",t[t.LargeDashed=3]="LargeDashed",t[t.SparseDotted=4]="SparseDotted"}(o||(o={}));const p={khaki:"#f0e68c",azure:"#f0ffff",aliceblue:"#f0f8ff",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gainsboro:"#dcdcdc",gray:"#808080",green:"#008000",honeydew:"#f0fff0",floralwhite:"#fffaf0",lightblue:"#add8e6",lightcoral:"#f08080",lemonchiffon:"#fffacd",hotpink:"#ff69b4",lightyellow:"#ffffe0",greenyellow:"#adff2f",lightgoldenrodyellow:"#fafad2",limegreen:"#32cd32",linen:"#faf0e6",lightcyan:"#e0ffff",magenta:"#f0f",maroon:"#800000",olive:"#808000",orange:"#ffa500",oldlace:"#fdf5e6",mediumblue:"#0000cd",transparent:"#0000",lime:"#0f0",lightpink:"#ffb6c1",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",midnightblue:"#191970",orchid:"#da70d6",mediumorchid:"#ba55d3",mediumturquoise:"#48d1cc",orangered:"#ff4500",royalblue:"#4169e1",powderblue:"#b0e0e6",red:"#f00",coral:"#ff7f50",turquoise:"#40e0d0",white:"#fff",whitesmoke:"#f5f5f5",wheat:"#f5deb3",teal:"#008080",steelblue:"#4682b4",bisque:"#ffe4c4",aquamarine:"#7fffd4",aqua:"#0ff",sienna:"#a0522d",silver:"#c0c0c0",springgreen:"#00ff7f",antiquewhite:"#faebd7",burlywood:"#deb887",brown:"#a52a2a",beige:"#f5f5dc",chocolate:"#d2691e",chartreuse:"#7fff00",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cadetblue:"#5f9ea0",tomato:"#ff6347",fuchsia:"#f0f",blue:"#00f",salmon:"#fa8072",blanchedalmond:"#ffebcd",slateblue:"#6a5acd",slategray:"#708090",thistle:"#d8bfd8",tan:"#d2b48c",cyan:"#0ff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",blueviolet:"#8a2be2",black:"#000",darkmagenta:"#8b008b",darkslateblue:"#483d8b",darkkhaki:"#bdb76b",darkorchid:"#9932cc",darkorange:"#ff8c00",darkgreen:"#006400",darkred:"#8b0000",dodgerblue:"#1e90ff",darkslategray:"#2f4f4f",dimgray:"#696969",deepskyblue:"#00bfff",firebrick:"#b22222",forestgreen:"#228b22",indigo:"#4b0082",ivory:"#fffff0",lavenderblush:"#fff0f5",feldspar:"#d19275",indianred:"#cd5c5c",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightskyblue:"#87cefa",lightslategray:"#789",lightslateblue:"#8470ff",snow:"#fffafa",lightseagreen:"#20b2aa",lightsalmon:"#ffa07a",darksalmon:"#e9967a",darkviolet:"#9400d3",mediumpurple:"#9370d8",mediumaquamarine:"#66cdaa",skyblue:"#87ceeb",lavender:"#e6e6fa",lightsteelblue:"#b0c4de",mediumvioletred:"#c71585",mintcream:"#f5fffa",navajowhite:"#ffdead",navy:"#000080",olivedrab:"#6b8e23",palevioletred:"#d87093",violetred:"#d02090",yellow:"#ff0",yellowgreen:"#9acd32",lawngreen:"#7cfc00",pink:"#ffc0cb",paleturquoise:"#afeeee",palegoldenrod:"#eee8aa",darkolivegreen:"#556b2f",darkseagreen:"#8fbc8f",darkturquoise:"#00ced1",peachpuff:"#ffdab9",deeppink:"#ff1493",violet:"#ee82ee",palegreen:"#98fb98",mediumseagreen:"#3cb371",peru:"#cd853f",saddlebrown:"#8b4513",sandybrown:"#f4a460",rosybrown:"#bc8f8f",purple:"#800080",seagreen:"#2e8b57",seashell:"#fff5ee",papayawhip:"#ffefd5",mediumslateblue:"#7b68ee",plum:"#dda0dd",mediumspringgreen:"#00fa9a"};function m(t){return t<0?0:t>255?255:Math.round(t)||0}function b(t){return t<=0||t>1?Math.min(Math.max(t,0),1):Math.round(1e4*t)/1e4}const w=/^#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?$/i,g=/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/i,M=/^rgb\(\s*(-?\d{1,10})\s*,\s*(-?\d{1,10})\s*,\s*(-?\d{1,10})\s*\)$/,x=/^rgba\(\s*(-?\d{1,10})\s*,\s*(-?\d{1,10})\s*,\s*(-?\d{1,10})\s*,\s*(-?\d*\.?\d+)\s*\)$/;function S(t){(t=t.toLowerCase())in p&&(t=p[t]);{const i=x.exec(t)||M.exec(t);if(i)return[m(parseInt(i[1],10)),m(parseInt(i[2],10)),m(parseInt(i[3],10)),b(i.length<5?1:parseFloat(i[4]))]}{const i=g.exec(t);if(i)return[m(parseInt(i[1],16)),m(parseInt(i[2],16)),m(parseInt(i[3],16)),1]}{const i=w.exec(t);if(i)return[m(17*parseInt(i[1],16)),m(17*parseInt(i[2],16)),m(17*parseInt(i[3],16)),1]}throw new Error(`Cannot parse color: ${t}`)}function k(t){return.199*t[0]+.687*t[1]+.114*t[2]}function y(t){const i=S(t);return{t:`rgb(${i[0]}, ${i[1]}, ${i[2]})`,i:k(i)>160?"black":"white"}}class C{constructor(){this.h=[]}l(t,i,n){const s={o:t,_:i,u:!0===n};this.h.push(s)}v(t){const i=this.h.findIndex((i=>t===i.o));i>-1&&this.h.splice(i,1)}p(t){this.h=this.h.filter((i=>i._!==t))}m(t,i,n){const s=[...this.h];this.h=this.h.filter((t=>!t.u)),s.forEach((s=>s.o(t,i,n)))}M(){return this.h.length>0}S(){this.h=[]}}function T(t,...i){for(const n of i)for(const i in n)void 0!==n[i]&&("object"!=typeof n[i]||void 0===t[i]||Array.isArray(n[i])?t[i]=n[i]:T(t[i],n[i]));return t}function P(t){return"number"==typeof t&&isFinite(t)}function R(t){return"number"==typeof t&&t%1==0}function D(t){return"string"==typeof t}function O(t){return"boolean"==typeof t}function V(t){const i=t;if(!i||"object"!=typeof i)return i;let n,s,e;for(s in n=Array.isArray(i)?[]:{},i)i.hasOwnProperty(s)&&(e=i[s],n[s]=e&&"object"==typeof e?V(e):e);return n}function B(t){return null!==t}function A(t){return null===t?void 0:t}const z="-apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif";function E(t,i,n){return void 0===i&&(i=z),`${n=void 0!==n?`${n} `:""}${t}px ${i}`}class I{constructor(t){this.k={C:1,T:5,P:NaN,R:"",D:"",O:"",V:"",B:0,A:0,I:0,L:0,N:0},this.F=t}W(){const t=this.k,i=this.j(),n=this.H();return t.P===i&&t.D===n||(t.P=i,t.D=n,t.R=E(i,n),t.L=2.5/12*i,t.B=t.L,t.A=i/12*t.T,t.I=i/12*t.T,t.N=0),t.O=this.$(),t.V=this.U(),this.k}$(){return this.F.W().layout.textColor}U(){return this.F.q()}j(){return this.F.W().layout.fontSize}H(){return this.F.W().layout.fontFamily}}class L{constructor(){this.Y=[]}Z(t){this.Y=t}X(t,i,n){this.Y.forEach((s=>{s.X(t,i,n)}))}}class N{X(t,i,n){t.useBitmapCoordinateSpace((t=>this.K(t,i,n)))}}class F extends N{constructor(){super(...arguments),this.G=null}J(t){this.G=t}K({context:t,horizontalPixelRatio:i,verticalPixelRatio:n}){if(null===this.G||null===this.G.tt)return;const s=this.G.tt,e=this.G,r=Math.max(1,Math.floor(i))%2/2,h=h=>{t.beginPath();for(let l=s.to-1;l>=s.from;--l){const s=e.it[l],a=Math.round(s.nt*i)+r,o=s.st*n,_=h*n+r;t.moveTo(a,o),t.arc(a,o,_,0,2*Math.PI)}t.fill()};e.et>0&&(t.fillStyle=e.rt,h(e.ht+e.et)),t.fillStyle=e.lt,h(e.ht)}}function W(){return{it:[{nt:0,st:0,ot:0,_t:0}],lt:"",rt:"",ht:0,et:0,tt:null}}const j={from:0,to:1};class H{constructor(t,i){this.ut=new L,this.ct=[],this.dt=[],this.ft=!0,this.F=t,this.vt=i,this.ut.Z(this.ct)}bt(t){const i=this.F.wt();i.length!==this.ct.length&&(this.dt=i.map(W),this.ct=this.dt.map((t=>{const i=new F;return i.J(t),i})),this.ut.Z(this.ct)),this.ft=!0}gt(){return this.ft&&(this.Mt(),this.ft=!1),this.ut}Mt(){const t=2===this.vt.W().mode,i=this.F.wt(),n=this.vt.xt(),s=this.F.St();i.forEach(((i,e)=>{var r;const h=this.dt[e],l=i.kt(n);if(t||null===l||!i.yt())return void(h.tt=null);const a=f(i.Ct());h.lt=l.Tt,h.ht=l.ht,h.et=l.Pt,h.it[0]._t=l._t,h.it[0].st=i.Dt().Rt(l._t,a.Ot),h.rt=null!==(r=l.Vt)&&void 0!==r?r:this.F.Bt(h.it[0].st/i.Dt().At()),h.it[0].ot=n,h.it[0].nt=s.zt(n),h.tt=j}))}}class $ extends N{constructor(t){super(),this.Et=t}K({context:t,bitmapSize:i,horizontalPixelRatio:n,verticalPixelRatio:s}){if(null===this.Et)return;const e=this.Et.It.yt,r=this.Et.Lt.yt;if(!e&&!r)return;const h=Math.round(this.Et.nt*n),l=Math.round(this.Et.st*s);t.lineCap="butt",e&&h>=0&&(t.lineWidth=Math.floor(this.Et.It.et*n),t.strokeStyle=this.Et.It.O,t.fillStyle=this.Et.It.O,_(t,this.Et.It.Nt),function(t,i,n,s){t.beginPath();const e=t.lineWidth%2?.5:0;t.moveTo(i+e,n),t.lineTo(i+e,s),t.stroke()}(t,h,0,i.height)),r&&l>=0&&(t.lineWidth=Math.floor(this.Et.Lt.et*s),t.strokeStyle=this.Et.Lt.O,t.fillStyle=this.Et.Lt.O,_(t,this.Et.Lt.Nt),u(t,l,0,i.width))}}class U{constructor(t){this.ft=!0,this.Ft={It:{et:1,Nt:0,O:"",yt:!1},Lt:{et:1,Nt:0,O:"",yt:!1},nt:0,st:0},this.Wt=new $(this.Ft),this.jt=t}bt(){this.ft=!0}gt(){return this.ft&&(this.Mt(),this.ft=!1),this.Wt}Mt(){const t=this.jt.yt(),i=f(this.jt.Ht()),n=i.$t().W().crosshair,s=this.Ft;if(2===n.mode)return s.Lt.yt=!1,void(s.It.yt=!1);s.Lt.yt=t&&this.jt.Ut(i),s.It.yt=t&&this.jt.qt(),s.Lt.et=n.horzLine.width,s.Lt.Nt=n.horzLine.style,s.Lt.O=n.horzLine.color,s.It.et=n.vertLine.width,s.It.Nt=n.vertLine.style,s.It.O=n.vertLine.color,s.nt=this.jt.Yt(),s.st=this.jt.Zt()}}function q(t,i,n,s,e,r){t.fillRect(i+r,n,s-2*r,r),t.fillRect(i+r,n+e-r,s-2*r,r),t.fillRect(i,n,r,e),t.fillRect(i+s-r,n,r,e)}function Y(t,i,n,s,e,r){t.save(),t.globalCompositeOperation="copy",t.fillStyle=r,t.fillRect(i,n,s,e),t.restore()}function Z(t,i,n,s,e,r){t.beginPath(),t.roundRect?t.roundRect(i,n,s,e,r):(t.lineTo(i+s-r[1],n),0!==r[1]&&t.arcTo(i+s,n,i+s,n+r[1],r[1]),t.lineTo(i+s,n+e-r[2]),0!==r[2]&&t.arcTo(i+s,n+e,i+s-r[2],n+e,r[2]),t.lineTo(i+r[3],n+e),0!==r[3]&&t.arcTo(i,n+e,i,n+e-r[3],r[3]),t.lineTo(i,n+r[0]),0!==r[0]&&t.arcTo(i,n,i+r[0],n,r[0]))}function X(t,i,n,s,e,r,h=0,l=[0,0,0,0],a=""){if(t.save(),!h||!a||a===r)return Z(t,i,n,s,e,l),t.fillStyle=r,t.fill(),void t.restore();const o=h/2;var _;Z(t,i+o,n+o,s-h,e-h,(_=-o,l.map((t=>0===t?t:t+_)))),"transparent"!==r&&(t.fillStyle=r,t.fill()),"transparent"!==a&&(t.lineWidth=h,t.strokeStyle=a,t.closePath(),t.stroke()),t.restore()}function K(t,i,n,s,e,r,h){t.save(),t.globalCompositeOperation="copy";const l=t.createLinearGradient(0,0,0,e);l.addColorStop(0,r),l.addColorStop(1,h),t.fillStyle=l,t.fillRect(i,n,s,e),t.restore()}class G{constructor(t,i){this.J(t,i)}J(t,i){this.Et=t,this.Xt=i}At(t,i){return this.Et.yt?t.P+t.L+t.B:0}X(t,i,n,s){if(!this.Et.yt||0===this.Et.Kt.length)return;const e=this.Et.O,r=this.Xt.t,h=t.useBitmapCoordinateSpace((t=>{const h=t.context;h.font=i.R;const l=this.Gt(t,i,n,s),a=l.Jt,o=(t,i)=>{l.Qt?X(h,a.ti,a.ii,a.ni,a.si,t,a.ei,[a.ht,0,0,a.ht],i):X(h,a.ri,a.ii,a.ni,a.si,t,a.ei,[0,a.ht,a.ht,0],i)};return o(r,"transparent"),this.Et.hi&&(h.fillStyle=e,h.fillRect(a.ri,a.li,a.ai-a.ri,a.oi)),o("transparent",r),this.Et._i&&(h.fillStyle=i.V,h.fillRect(l.Qt?a.ui-a.ei:0,a.ii,a.ei,a.ci-a.ii)),l}));t.useMediaCoordinateSpace((({context:t})=>{const n=h.di;t.font=i.R,t.textAlign=h.Qt?"right":"left",t.textBaseline="middle",t.fillStyle=e,t.fillText(this.Et.Kt,n.fi,(n.ii+n.ci)/2+n.pi)}))}Gt(t,i,n,s){var e;const{context:r,bitmapSize:h,mediaSize:l,horizontalPixelRatio:a,verticalPixelRatio:o}=t,_=this.Et.hi||!this.Et.mi?i.T:0,u=this.Et.bi?i.C:0,c=i.L+this.Xt.wi,d=i.B+this.Xt.gi,f=i.A,v=i.I,p=this.Et.Kt,m=i.P,b=n.Mi(r,p),w=Math.ceil(n.xi(r,p)),g=m+c+d,M=i.C+f+v+w+_,x=Math.max(1,Math.floor(o));let S=Math.round(g*o);S%2!=x%2&&(S+=1);const k=u>0?Math.max(1,Math.floor(u*a)):0,y=Math.round(M*a),C=Math.round(_*a),T=null!==(e=this.Xt.Si)&&void 0!==e?e:this.Xt.ki,P=Math.round(T*o)-Math.floor(.5*o),R=Math.floor(P+x/2-S/2),D=R+S,O="right"===s,V=O?l.width-u:u,B=O?h.width-k:k;let A,z,E;return O?(A=B-y,z=B-C,E=V-_-f-u):(A=B+y,z=B+C,E=V+_+f),{Qt:O,Jt:{ii:R,li:P,ci:D,ni:y,si:S,ht:2*a,ei:k,ti:A,ri:B,ai:z,oi:x,ui:h.width},di:{ii:R/o,ci:D/o,fi:E,pi:b}}}}class J{constructor(t){this.yi={ki:0,t:"#000",gi:0,wi:0},this.Ci={Kt:"",yt:!1,hi:!0,mi:!1,Vt:"",O:"#FFF",_i:!1,bi:!1},this.Ti={Kt:"",yt:!1,hi:!1,mi:!0,Vt:"",O:"#FFF",_i:!0,bi:!0},this.ft=!0,this.Pi=new(t||G)(this.Ci,this.yi),this.Ri=new(t||G)(this.Ti,this.yi)}Kt(){return this.Di(),this.Ci.Kt}ki(){return this.Di(),this.yi.ki}bt(){this.ft=!0}At(t,i=!1){return Math.max(this.Pi.At(t,i),this.Ri.At(t,i))}Oi(){return this.yi.Si||0}Vi(t){this.yi.Si=t}Bi(){return this.Di(),this.Ci.yt||this.Ti.yt}Ai(){return this.Di(),this.Ci.yt}gt(t){return this.Di(),this.Ci.hi=this.Ci.hi&&t.W().ticksVisible,this.Ti.hi=this.Ti.hi&&t.W().ticksVisible,this.Pi.J(this.Ci,this.yi),this.Ri.J(this.Ti,this.yi),this.Pi}zi(){return this.Di(),this.Pi.J(this.Ci,this.yi),this.Ri.J(this.Ti,this.yi),this.Ri}Di(){this.ft&&(this.Ci.hi=!0,this.Ti.hi=!1,this.Ei(this.Ci,this.Ti,this.yi))}}class Q extends J{constructor(t,i,n){super(),this.jt=t,this.Ii=i,this.Li=n}Ei(t,i,n){if(t.yt=!1,2===this.jt.W().mode)return;const s=this.jt.W().horzLine;if(!s.labelVisible)return;const e=this.Ii.Ct();if(!this.jt.yt()||this.Ii.Ni()||null===e)return;const r=y(s.labelBackgroundColor);n.t=r.t,t.O=r.i;const h=2/12*this.Ii.P();n.wi=h,n.gi=h;const l=this.Li(this.Ii);n.ki=l.ki,t.Kt=this.Ii.Fi(l._t,e),t.yt=!0}}const tt=/[1-9]/g;class it{constructor(){this.Et=null}J(t){this.Et=t}X(t,i){if(null===this.Et||!1===this.Et.yt||0===this.Et.Kt.length)return;const n=t.useMediaCoordinateSpace((({context:t})=>(t.font=i.R,Math.round(i.Wi.xi(t,f(this.Et).Kt,tt)))));if(n<=0)return;const s=i.ji,e=n+2*s,r=e/2,h=this.Et.Hi;let l=this.Et.ki,a=Math.floor(l-r)+.5;a<0?(l+=Math.abs(0-a),a=Math.floor(l-r)+.5):a+e>h&&(l-=Math.abs(h-(a+e)),a=Math.floor(l-r)+.5);const o=a+e,_=Math.ceil(0+i.C+i.T+i.L+i.P+i.B);t.useBitmapCoordinateSpace((({context:t,horizontalPixelRatio:n,verticalPixelRatio:s})=>{const e=f(this.Et);t.fillStyle=e.t;const r=Math.round(a*n),h=Math.round(0*s),l=Math.round(o*n),u=Math.round(_*s),c=Math.round(2*n);if(t.beginPath(),t.moveTo(r,h),t.lineTo(r,u-c),t.arcTo(r,u,r+c,u,c),t.lineTo(l-c,u),t.arcTo(l,u,l,u-c,c),t.lineTo(l,h),t.fill(),e.hi){const r=Math.round(e.ki*n),l=h,a=Math.round((l+i.T)*s);t.fillStyle=e.O;const o=Math.max(1,Math.floor(n)),_=Math.floor(.5*n);t.fillRect(r-_,l,o,a-l)}})),t.useMediaCoordinateSpace((({context:t})=>{const n=f(this.Et),e=0+i.C+i.T+i.L+i.P/2;t.font=i.R,t.textAlign="left",t.textBaseline="middle",t.fillStyle=n.O;const r=i.Wi.Mi(t,"Apr0");t.translate(a+s,e+r),t.fillText(n.Kt,0,0)}))}}class nt{constructor(t,i,n){this.ft=!0,this.Wt=new it,this.Ft={yt:!1,t:"#4c525e",O:"white",Kt:"",Hi:0,ki:NaN,hi:!0},this.vt=t,this.$i=i,this.Li=n}bt(){this.ft=!0}gt(){return this.ft&&(this.Mt(),this.ft=!1),this.Wt.J(this.Ft),this.Wt}Mt(){const t=this.Ft;if(t.yt=!1,2===this.vt.W().mode)return;const i=this.vt.W().vertLine;if(!i.labelVisible)return;const n=this.$i.St();if(n.Ni())return;t.Hi=n.Hi();const s=this.Li();if(null===s)return;t.ki=s.ki;const e=n.Ui(this.vt.xt());t.Kt=n.qi(f(e)),t.yt=!0;const r=y(i.labelBackgroundColor);t.t=r.t,t.O=r.i,t.hi=n.W().ticksVisible}}class st{constructor(){this.Yi=null,this.Zi=0}Xi(){return this.Zi}Ki(t){this.Zi=t}Dt(){return this.Yi}Gi(t){this.Yi=t}Ji(t){return[]}Qi(){return[]}yt(){return!0}}var et;!function(t){t[t.Normal=0]="Normal",t[t.Magnet=1]="Magnet",t[t.Hidden=2]="Hidden"}(et||(et={}));class rt extends st{constructor(t,i){super(),this.tn=null,this.nn=NaN,this.sn=0,this.en=!0,this.rn=new Map,this.hn=!1,this.ln=NaN,this.an=NaN,this._n=NaN,this.un=NaN,this.$i=t,this.cn=i,this.dn=new H(t,this);this.fn=((t,i)=>n=>{const s=i(),e=t();if(n===f(this.tn).vn())return{_t:e,ki:s};{const t=f(n.Ct());return{_t:n.pn(s,t),ki:s}}})((()=>this.nn),(()=>this.an));const n=((t,i)=>()=>{const n=this.$i.St().mn(t()),s=i();return n&&Number.isFinite(s)?{ot:n,ki:s}:null})((()=>this.sn),(()=>this.Yt()));this.bn=new nt(this,t,n),this.wn=new U(this)}W(){return this.cn}gn(t,i){this._n=t,this.un=i}Mn(){this._n=NaN,this.un=NaN}xn(){return this._n}Sn(){return this.un}kn(t,i,n){this.hn||(this.hn=!0),this.en=!0,this.yn(t,i,n)}xt(){return this.sn}Yt(){return this.ln}Zt(){return this.an}yt(){return this.en}Cn(){this.en=!1,this.Tn(),this.nn=NaN,this.ln=NaN,this.an=NaN,this.tn=null,this.Mn()}Pn(t){return null!==this.tn?[this.wn,this.dn]:[]}Ut(t){return t===this.tn&&this.cn.horzLine.visible}qt(){return this.cn.vertLine.visible}Rn(t,i){this.en&&this.tn===t||this.rn.clear();const n=[];return this.tn===t&&n.push(this.Dn(this.rn,i,this.fn)),n}Qi(){return this.en?[this.bn]:[]}Ht(){return this.tn}On(){this.wn.bt(),this.rn.forEach((t=>t.bt())),this.bn.bt(),this.dn.bt()}Vn(t){return t&&!t.vn().Ni()?t.vn():null}yn(t,i,n){this.Bn(t,i,n)&&this.On()}Bn(t,i,n){const s=this.ln,e=this.an,r=this.nn,h=this.sn,l=this.tn,a=this.Vn(n);this.sn=t,this.ln=isNaN(t)?NaN:this.$i.St().zt(t),this.tn=n;const o=null!==a?a.Ct():null;return null!==a&&null!==o?(this.nn=i,this.an=a.Rt(i,o)):(this.nn=NaN,this.an=NaN),s!==this.ln||e!==this.an||h!==this.sn||r!==this.nn||l!==this.tn}Tn(){const t=this.$i.wt().map((t=>t.zn().An())).filter(B),i=0===t.length?null:Math.max(...t);this.sn=null!==i?i:NaN}Dn(t,i,n){let s=t.get(i);return void 0===s&&(s=new Q(this,i,n),t.set(i,s)),s}}function ht(t){return"left"===t||"right"===t}class lt{constructor(t){this.En=new Map,this.In=[],this.Ln=t}Nn(t,i){const n=function(t,i){return void 0===t?i:{Fn:Math.max(t.Fn,i.Fn),Wn:t.Wn||i.Wn}}(this.En.get(t),i);this.En.set(t,n)}jn(){return this.Ln}Hn(t){const i=this.En.get(t);return void 0===i?{Fn:this.Ln}:{Fn:Math.max(this.Ln,i.Fn),Wn:i.Wn}}$n(){this.Un(),this.In=[{qn:0}]}Yn(t){this.Un(),this.In=[{qn:1,Ot:t}]}Zn(t){this.Xn(),this.In.push({qn:5,Ot:t})}Un(){this.Xn(),this.In.push({qn:6})}Kn(){this.Un(),this.In=[{qn:4}]}Gn(t){this.Un(),this.In.push({qn:2,Ot:t})}Jn(t){this.Un(),this.In.push({qn:3,Ot:t})}Qn(){return this.In}ts(t){for(const i of t.In)this.ns(i);this.Ln=Math.max(this.Ln,t.Ln),t.En.forEach(((t,i)=>{this.Nn(i,t)}))}static ss(){return new lt(2)}static es(){return new lt(3)}ns(t){switch(t.qn){case 0:this.$n();break;case 1:this.Yn(t.Ot);break;case 2:this.Gn(t.Ot);break;case 3:this.Jn(t.Ot);break;case 4:this.Kn();break;case 5:this.Zn(t.Ot);break;case 6:this.Xn()}}Xn(){const t=this.In.findIndex((t=>5===t.qn));-1!==t&&this.In.splice(t,1)}}const at=".";function ot(t,i){if(!P(t))return"n/a";if(!R(i))throw new TypeError("invalid length");if(i<0||i>16)throw new TypeError("invalid length");if(0===i)return t.toString();return("0000000000000000"+t.toString()).slice(-i)}class _t{constructor(t,i){if(i||(i=1),P(t)&&R(t)||(t=100),t<0)throw new TypeError("invalid base");this.Ii=t,this.rs=i,this.hs()}format(t){const i=t<0?"−":"";return t=Math.abs(t),i+this.ls(t)}hs(){if(this.os=0,this.Ii>0&&this.rs>0){let t=this.Ii;for(;t>1;)t/=10,this.os++}}ls(t){const i=this.Ii/this.rs;let n=Math.floor(t),s="";const e=void 0!==this.os?this.os:NaN;if(i>1){let r=+(Math.round(t*i)-n*i).toFixed(this.os);r>=i&&(r-=i,n+=1),s=at+ot(+r.toFixed(this.os)*this.rs,e)}else n=Math.round(n*i)/i,e>0&&(s=at+ot(0,e));return n.toFixed(0)+s}}class ut extends _t{constructor(t=100){super(t)}format(t){return`${super.format(t)}%`}}class ct{constructor(t){this._s=t}format(t){let i="";return t<0&&(i="-",t=-t),t<995?i+this.us(t):t<999995?i+this.us(t/1e3)+"K":t<999999995?(t=1e3*Math.round(t/1e3),i+this.us(t/1e6)+"M"):(t=1e6*Math.round(t/1e6),i+this.us(t/1e9)+"B")}us(t){let i;const n=Math.pow(10,this._s);return i=(t=Math.round(t*n)/n)>=1e-15&&t<1?t.toFixed(this._s).replace(/\.?0+$/,""):String(t),i.replace(/(\.[1-9]*)0+$/,((t,i)=>i))}}function dt(t,i,n,s,e,r,h){if(0===i.length||s.from>=i.length||s.to<=0)return;const{context:l,horizontalPixelRatio:a,verticalPixelRatio:o}=t,_=i[s.from];let u=r(t,_),c=_;if(s.to-s.from<2){const i=e/2;l.beginPath();const n={nt:_.nt-i,st:_.st},s={nt:_.nt+i,st:_.st};l.moveTo(n.nt*a,n.st*o),l.lineTo(s.nt*a,s.st*o),h(t,u,n,s)}else{const e=(i,n)=>{h(t,u,c,n),l.beginPath(),u=i,c=n};let d=c;l.beginPath(),l.moveTo(_.nt*a,_.st*o);for(let h=s.from+1;h=s.from;--n){const s=i[n];if(s){const i=e(t,s);i!==a&&(l.beginPath(),null!==a&&l.fill(),l.fillStyle=i,a=i);const n=Math.round(s.nt*r)+o,u=s.st*h;l.moveTo(n,u),l.arc(n,u,_,0,2*Math.PI)}}l.fill()}(t,i,l,n,o)}}class Tt extends Ct{Ds(t,i){return i.lt}}function Pt(t,i,n,s,e=0,r=i.length){let h=r-e;for(;0>1,l=e+r;s(i[l],n)===t?(e=l+1,h-=r+1):h=r}return e}const Rt=Pt.bind(null,!0),Dt=Pt.bind(null,!1);function Ot(t,i){return t.ot0&&r=s&&(l=r-1),h>0&&hObject.assign(Object.assign({},t),this.Is.$s().Hs(t.ot))))}Us(){this.Es=null}Fs(){this.Bs&&(this.qs(),this.Bs=!1),this.As&&(this.js(),this.As=!1),this.Vs&&(this.Ys(),this.Vs=!1)}Ys(){const t=this.Is.Dt(),i=this.Ls.St();if(this.Us(),i.Ni()||t.Ni())return;const n=i.Zs();if(null===n)return;if(0===this.Is.zn().Xs())return;const s=this.Is.Ct();null!==s&&(this.Es=Bt(this.zs,n,this.Ns),this.Ks(t,i,s.Ot),this.Gs())}}class zt extends At{constructor(t,i){super(t,i,!0)}Ks(t,i,n){i.Js(this.zs,A(this.Es)),t.Qs(this.zs,n,A(this.Es))}te(t,i){return{ot:t,_t:i,nt:NaN,st:NaN}}qs(){const t=this.Is.$s();this.zs=this.Is.zn().ie().map((i=>{const n=i.Ot[3];return this.ne(i.se,n,t)}))}}class Et extends zt{constructor(t,i){super(t,i),this.Ws=new L,this.ee=new kt,this.re=new Tt,this.Ws.Z([this.ee,this.re])}ne(t,i,n){return Object.assign(Object.assign({},this.te(t,i)),n.Hs(t))}Gs(){const t=this.Is.W();this.ee.J({ds:t.lineType,it:this.zs,Nt:t.lineStyle,et:t.lineWidth,fs:null,vs:t.invertFilledArea,tt:this.Es,cs:this.Ls.St().he()}),this.re.J({ds:t.lineVisible?t.lineType:void 0,it:this.zs,Nt:t.lineStyle,et:t.lineWidth,tt:this.Es,cs:this.Ls.St().he(),Rs:t.pointMarkersVisible?t.pointMarkersRadius||t.lineWidth/2+2:void 0})}}class It extends N{constructor(){super(...arguments),this.Et=null,this.le=0,this.ae=0}J(t){this.Et=t}K({context:t,horizontalPixelRatio:i,verticalPixelRatio:n}){if(null===this.Et||0===this.Et.zn.length||null===this.Et.tt)return;if(this.le=this.oe(i),this.le>=2){Math.max(1,Math.floor(i))%2!=this.le%2&&this.le--}this.ae=this.Et._e?Math.min(this.le,Math.floor(i)):this.le;let s=null;const e=this.ae<=this.le&&this.Et.he>=Math.floor(1.5*i);for(let r=this.Et.tt.from;rf+p-1&&(e=f+p-1,s=e-_+1),t.fillRect(i,s,o-i,e-s+1)}const i=a+m;let s=Math.max(f,Math.round(h.pe*n)-l),e=s+_-1;e>f+p-1&&(e=f+p-1,s=e-_+1),t.fillRect(u+1,s,i-u,e-s+1)}}}oe(t){const i=Math.floor(t);return Math.max(i,Math.floor(function(t,i){return Math.floor(.3*t*i)}(f(this.Et).he,t)))}}class Lt extends At{constructor(t,i){super(t,i,!1)}Ks(t,i,n){i.Js(this.zs,A(this.Es)),t.me(this.zs,n,A(this.Es))}be(t,i,n){return{ot:t,we:i.Ot[0],ge:i.Ot[1],Me:i.Ot[2],xe:i.Ot[3],nt:NaN,ve:NaN,ce:NaN,de:NaN,pe:NaN}}qs(){const t=this.Is.$s();this.zs=this.Is.zn().ie().map((i=>this.ne(i.se,i,t)))}}class Nt extends Lt{constructor(){super(...arguments),this.Ws=new It}ne(t,i,n){return Object.assign(Object.assign({},this.be(t,i,n)),n.Hs(t))}Gs(){const t=this.Is.W();this.Ws.J({zn:this.zs,he:this.Ls.St().he(),fe:t.openVisible,_e:t.thinBars,tt:this.Es})}}class Ft extends wt{constructor(){super(...arguments),this.Cs=new St}ps(t,i){const n=this.G;return this.Cs.bs(t,{gs:i.Se,Ms:i.ke,xs:i.ye,Ss:i.Ce,ks:t.bitmapSize.height,fs:n.fs})}}class Wt extends Ct{constructor(){super(...arguments),this.Te=new St}Ds(t,i){const n=this.G;return this.Te.bs(t,{gs:i.Pe,Ms:i.Pe,xs:i.Re,Ss:i.Re,ks:t.bitmapSize.height,fs:n.fs})}}class jt extends zt{constructor(t,i){super(t,i),this.Ws=new L,this.De=new Ft,this.Oe=new Wt,this.Ws.Z([this.De,this.Oe])}ne(t,i,n){return Object.assign(Object.assign({},this.te(t,i)),n.Hs(t))}Gs(){const t=this.Is.Ct();if(null===t)return;const i=this.Is.W(),n=this.Is.Dt().Rt(i.baseValue.price,t.Ot),s=this.Ls.St().he();this.De.J({it:this.zs,et:i.lineWidth,Nt:i.lineStyle,ds:i.lineType,fs:n,vs:!1,tt:this.Es,cs:s}),this.Oe.J({it:this.zs,et:i.lineWidth,Nt:i.lineStyle,ds:i.lineVisible?i.lineType:void 0,Rs:i.pointMarkersVisible?i.pointMarkersRadius||i.lineWidth/2+2:void 0,fs:n,tt:this.Es,cs:s})}}class Ht extends N{constructor(){super(...arguments),this.Et=null,this.le=0}J(t){this.Et=t}K(t){if(null===this.Et||0===this.Et.zn.length||null===this.Et.tt)return;const{horizontalPixelRatio:i}=t;if(this.le=function(t,i){if(t>=2.5&&t<=4)return Math.floor(3*i);const n=1-.2*Math.atan(Math.max(4,t)-4)/(.5*Math.PI),s=Math.floor(t*n*i),e=Math.floor(t*i),r=Math.min(s,e);return Math.max(Math.floor(i),r)}(this.Et.he,i),this.le>=2){Math.floor(i)%2!=this.le%2&&this.le--}const n=this.Et.zn;this.Et.Ve&&this.Be(t,n,this.Et.tt),this.Et._i&&this.Ae(t,n,this.Et.tt);const s=this.ze(i);(!this.Et._i||this.le>2*s)&&this.Ee(t,n,this.Et.tt)}Be(t,i,n){if(null===this.Et)return;const{context:s,horizontalPixelRatio:e,verticalPixelRatio:r}=t;let h="",l=Math.min(Math.floor(e),Math.floor(this.Et.he*e));l=Math.max(Math.floor(e),Math.min(l,this.le));const a=Math.floor(.5*l);let o=null;for(let t=n.from;t2*l)q(s,o,u,_-o+1,c-u+1,l);else{const t=_-o+1;s.fillRect(o,u,t,c-u+1)}a=_}}Ee(t,i,n){if(null===this.Et)return;const{context:s,horizontalPixelRatio:e,verticalPixelRatio:r}=t;let h="";const l=this.ze(e);for(let t=n.from;to||s.fillRect(_,a,u-_+1,o-a+1)}}}class $t extends Lt{constructor(){super(...arguments),this.Ws=new Ht}ne(t,i,n){return Object.assign(Object.assign({},this.be(t,i,n)),n.Hs(t))}Gs(){const t=this.Is.W();this.Ws.J({zn:this.zs,he:this.Ls.St().he(),Ve:t.wickVisible,_i:t.borderVisible,tt:this.Es})}}class Ut{constructor(t,i){this.Ne=t,this.Ii=i}X(t,i,n){this.Ne.draw(t,this.Ii,i,n)}}class qt extends At{constructor(t,i,n){super(t,i,!1),this.wn=n,this.Ws=new Ut(this.wn.renderer(),(i=>{const n=t.Ct();return null===n?null:t.Dt().Rt(i,n.Ot)}))}Fe(t){return this.wn.priceValueBuilder(t)}We(t){return this.wn.isWhitespace(t)}qs(){const t=this.Is.$s();this.zs=this.Is.zn().ie().map((i=>Object.assign(Object.assign({ot:i.se,nt:NaN},t.Hs(i.se)),{je:i.He})))}Ks(t,i){i.Js(this.zs,A(this.Es))}Gs(){this.wn.update({bars:this.zs.map(Yt),barSpacing:this.Ls.St().he(),visibleRange:this.Es},this.Is.W())}}function Yt(t){return{x:t.nt,time:t.ot,originalData:t.je,barColor:t.ue}}class Zt extends N{constructor(){super(...arguments),this.Et=null,this.$e=[]}J(t){this.Et=t,this.$e=[]}K({context:t,horizontalPixelRatio:i,verticalPixelRatio:n}){if(null===this.Et||0===this.Et.it.length||null===this.Et.tt)return;this.$e.length||this.Ue(i);const s=Math.max(1,Math.floor(n)),e=Math.round(this.Et.qe*n)-Math.floor(s/2),r=e+s;for(let i=this.Et.tt.from;is.Ze?s.ui=n.Os-i-1:n.Os=s.ui+i+1))}let s=Math.ceil(this.Et.he*t);for(let t=this.Et.tt.from;t0&&s<4)for(let t=this.Et.tt.from;ts&&(i.Ye>i.Ze?i.ui-=1:i.Os+=1)}}}class Xt extends zt{constructor(){super(...arguments),this.Ws=new Zt}ne(t,i,n){return Object.assign(Object.assign({},this.te(t,i)),n.Hs(t))}Gs(){const t={it:this.zs,he:this.Ls.St().he(),tt:this.Es,qe:this.Is.Dt().Rt(this.Is.W().base,f(this.Is.Ct()).Ot)};this.Ws.J(t)}}class Kt extends zt{constructor(){super(...arguments),this.Ws=new Tt}ne(t,i,n){return Object.assign(Object.assign({},this.te(t,i)),n.Hs(t))}Gs(){const t=this.Is.W(),i={it:this.zs,Nt:t.lineStyle,ds:t.lineVisible?t.lineType:void 0,et:t.lineWidth,Rs:t.pointMarkersVisible?t.pointMarkersRadius||t.lineWidth/2+2:void 0,tt:this.Es,cs:this.Ls.St().he()};this.Ws.J(i)}}const Gt=/[2-9]/g;class Jt{constructor(t=50){this.Xe=0,this.Ke=1,this.Ge=1,this.Je={},this.Qe=new Map,this.tr=t}ir(){this.Xe=0,this.Qe.clear(),this.Ke=1,this.Ge=1,this.Je={}}xi(t,i,n){return this.nr(t,i,n).width}Mi(t,i,n){const s=this.nr(t,i,n);return((s.actualBoundingBoxAscent||0)-(s.actualBoundingBoxDescent||0))/2}nr(t,i,n){const s=n||Gt,e=String(i).replace(s,"0");if(this.Qe.has(e))return d(this.Qe.get(e)).sr;if(this.Xe===this.tr){const t=this.Je[this.Ge];delete this.Je[this.Ge],this.Qe.delete(t),this.Ge++,this.Xe--}t.save(),t.textBaseline="middle";const r=t.measureText(e);return t.restore(),0===r.width&&i.length||(this.Qe.set(e,{sr:r,er:this.Ke}),this.Je[this.Ke]=e,this.Xe++,this.Ke++),r}}class Qt{constructor(t){this.rr=null,this.k=null,this.hr="right",this.lr=t}ar(t,i,n){this.rr=t,this.k=i,this.hr=n}X(t){null!==this.k&&null!==this.rr&&this.rr.X(t,this.k,this.lr,this.hr)}}class ti{constructor(t,i,n){this._r=t,this.lr=new Jt(50),this.ur=i,this.F=n,this.j=-1,this.Wt=new Qt(this.lr)}gt(){const t=this.F.cr(this.ur);if(null===t)return null;const i=t.dr(this.ur)?t.vr():this.ur.Dt();if(null===i)return null;const n=t.pr(i);if("overlay"===n)return null;const s=this.F.mr();return s.P!==this.j&&(this.j=s.P,this.lr.ir()),this.Wt.ar(this._r.zi(),s,n),this.Wt}}class ii extends N{constructor(){super(...arguments),this.Et=null}J(t){this.Et=t}br(t,i){var n;if(!(null===(n=this.Et)||void 0===n?void 0:n.yt))return null;const{st:s,et:e,wr:r}=this.Et;return i>=s-e-7&&i<=s+e+7?{gr:this.Et,wr:r}:null}K({context:t,bitmapSize:i,horizontalPixelRatio:n,verticalPixelRatio:s}){if(null===this.Et)return;if(!1===this.Et.yt)return;const e=Math.round(this.Et.st*s);e<0||e>i.height||(t.lineCap="butt",t.strokeStyle=this.Et.O,t.lineWidth=Math.floor(this.Et.et*n),_(t,this.Et.Nt),u(t,e,0,i.width))}}class ni{constructor(t){this.Mr={st:0,O:"rgba(0, 0, 0, 0)",et:1,Nt:0,yt:!1},this.Sr=new ii,this.ft=!0,this.Is=t,this.Ls=t.$t(),this.Sr.J(this.Mr)}bt(){this.ft=!0}gt(){return this.Is.yt()?(this.ft&&(this.kr(),this.ft=!1),this.Sr):null}}class si extends ni{constructor(t){super(t)}kr(){this.Mr.yt=!1;const t=this.Is.Dt(),i=t.yr().yr;if(2!==i&&3!==i)return;const n=this.Is.W();if(!n.baseLineVisible||!this.Is.yt())return;const s=this.Is.Ct();null!==s&&(this.Mr.yt=!0,this.Mr.st=t.Rt(s.Ot,s.Ot),this.Mr.O=n.baseLineColor,this.Mr.et=n.baseLineWidth,this.Mr.Nt=n.baseLineStyle)}}class ei extends N{constructor(){super(...arguments),this.Et=null}J(t){this.Et=t}He(){return this.Et}K({context:t,horizontalPixelRatio:i,verticalPixelRatio:n}){const s=this.Et;if(null===s)return;const e=Math.max(1,Math.floor(i)),r=e%2/2,h=Math.round(s.Ze.x*i)+r,l=s.Ze.y*n;t.fillStyle=s.Cr,t.beginPath();const a=Math.max(2,1.5*s.Tr)*i;t.arc(h,l,a,0,2*Math.PI,!1),t.fill(),t.fillStyle=s.Pr,t.beginPath(),t.arc(h,l,s.ht*i,0,2*Math.PI,!1),t.fill(),t.lineWidth=e,t.strokeStyle=s.Rr,t.beginPath(),t.arc(h,l,s.ht*i+e/2,0,2*Math.PI,!1),t.stroke()}}const ri=[{Dr:0,Or:.25,Vr:4,Br:10,Ar:.25,zr:0,Er:.4,Ir:.8},{Dr:.25,Or:.525,Vr:10,Br:14,Ar:0,zr:0,Er:.8,Ir:0},{Dr:.525,Or:1,Vr:14,Br:14,Ar:0,zr:0,Er:0,Ir:0}];function hi(t,i,n,s){return function(t,i){if("transparent"===t)return t;const n=S(t),s=n[3];return`rgba(${n[0]}, ${n[1]}, ${n[2]}, ${i*s})`}(t,n+(s-n)*i)}function li(t,i){const n=t%2600/2600;let s;for(const t of ri)if(n>=t.Dr&&n<=t.Or){s=t;break}c(void 0!==s,"Last price animation internal logic error");const e=(n-s.Dr)/(s.Or-s.Dr);return{Pr:hi(i,e,s.Ar,s.zr),Rr:hi(i,e,s.Er,s.Ir),ht:(r=e,h=s.Vr,l=s.Br,h+(l-h)*r)};var r,h,l}class ai{constructor(t){this.Wt=new ei,this.ft=!0,this.Lr=!0,this.Nr=performance.now(),this.Fr=this.Nr-1,this.Wr=t}jr(){this.Fr=this.Nr-1,this.bt()}Hr(){if(this.bt(),2===this.Wr.W().lastPriceAnimation){const t=performance.now(),i=this.Fr-t;if(i>0)return void(i<650&&(this.Fr+=2600));this.Nr=t,this.Fr=t+2600}}bt(){this.ft=!0}$r(){this.Lr=!0}yt(){return 0!==this.Wr.W().lastPriceAnimation}Ur(){switch(this.Wr.W().lastPriceAnimation){case 0:return!1;case 1:return!0;case 2:return performance.now()<=this.Fr}}gt(){return this.ft?(this.Mt(),this.ft=!1,this.Lr=!1):this.Lr&&(this.qr(),this.Lr=!1),this.Wt}Mt(){this.Wt.J(null);const t=this.Wr.$t().St(),i=t.Zs(),n=this.Wr.Ct();if(null===i||null===n)return;const s=this.Wr.Yr(!0);if(s.Zr||!i.Xr(s.se))return;const e={x:t.zt(s.se),y:this.Wr.Dt().Rt(s._t,n.Ot)},r=s.O,h=this.Wr.W().lineWidth,l=li(this.Kr(),r);this.Wt.J({Cr:r,Tr:h,Pr:l.Pr,Rr:l.Rr,ht:l.ht,Ze:e})}qr(){const t=this.Wt.He();if(null!==t){const i=li(this.Kr(),t.Cr);t.Pr=i.Pr,t.Rr=i.Rr,t.ht=i.ht}}Kr(){return this.Ur()?performance.now()-this.Nr:2599}}function oi(t,i){return xt(Math.min(Math.max(t,12),30)*i)}function _i(t,i){switch(t){case"arrowDown":case"arrowUp":return oi(i,1);case"circle":return oi(i,.8);case"square":return oi(i,.7)}}function ui(t){return function(t){const i=Math.ceil(t);return i%2!=0?i-1:i}(oi(t,1))}function ci(t){return Math.max(oi(t,.1),3)}function di(t,i,n){return i?t:n?Math.ceil(t/2):0}function fi(t,i,n,s,e){const r=_i("square",n),h=(r-1)/2,l=t-h,a=i-h;return s>=l&&s<=l+r&&e>=a&&e<=a+r}function vi(t,i,n,s){const e=(_i("arrowUp",s)-1)/2*n.Gr,r=(xt(s/2)-1)/2*n.Gr;i.beginPath(),t?(i.moveTo(n.nt-e,n.st),i.lineTo(n.nt,n.st-e),i.lineTo(n.nt+e,n.st),i.lineTo(n.nt+r,n.st),i.lineTo(n.nt+r,n.st+e),i.lineTo(n.nt-r,n.st+e),i.lineTo(n.nt-r,n.st)):(i.moveTo(n.nt-e,n.st),i.lineTo(n.nt,n.st+e),i.lineTo(n.nt+e,n.st),i.lineTo(n.nt+r,n.st),i.lineTo(n.nt+r,n.st-e),i.lineTo(n.nt-r,n.st-e),i.lineTo(n.nt-r,n.st)),i.fill()}function pi(t,i,n,s,e,r){return fi(i,n,s,e,r)}class mi extends N{constructor(){super(...arguments),this.Et=null,this.lr=new Jt,this.j=-1,this.H="",this.Jr=""}J(t){this.Et=t}ar(t,i){this.j===t&&this.H===i||(this.j=t,this.H=i,this.Jr=E(t,i),this.lr.ir())}br(t,i){if(null===this.Et||null===this.Et.tt)return null;for(let n=this.Et.tt.from;n=t&&e<=t+n&&r>=i-h&&r<=i+h}(t.Kt.nt,t.Kt.st,t.Kt.Hi,t.Kt.At,i,n))||function(t,i,n){if(0===t.Xs)return!1;switch(t.ih){case"arrowDown":case"arrowUp":return pi(0,t.nt,t.st,t.Xs,i,n);case"circle":return function(t,i,n,s,e){const r=2+_i("circle",n)/2,h=t-s,l=i-e;return Math.sqrt(h*h+l*l)<=r}(t.nt,t.st,t.Xs,i,n);case"square":return fi(t.nt,t.st,t.Xs,i,n)}}(t,i,n)}function gi(t,i,n,s,e,r,h,l,a){const o=P(n)?n:n.xe,_=P(n)?n:n.ge,u=P(n)?n:n.Me,c=P(i.size)?Math.max(i.size,0):1,d=ui(l.he())*c,f=d/2;switch(t.Xs=d,i.position){case"inBar":return t.st=h.Rt(o,a),void(void 0!==t.Kt&&(t.Kt.st=t.st+f+r+.6*e));case"aboveBar":return t.st=h.Rt(_,a)-f-s.nh,void 0!==t.Kt&&(t.Kt.st=t.st-f-.6*e,s.nh+=1.2*e),void(s.nh+=d+r);case"belowBar":return t.st=h.Rt(u,a)+f+s.sh,void 0!==t.Kt&&(t.Kt.st=t.st+f+r+.6*e,s.sh+=1.2*e),void(s.sh+=d+r)}i.position}class Mi{constructor(t,i){this.ft=!0,this.eh=!0,this.rh=!0,this.hh=null,this.ah=null,this.Wt=new mi,this.Wr=t,this.$i=i,this.Et={it:[],tt:null}}bt(t){this.ft=!0,this.rh=!0,"data"===t&&(this.eh=!0,this.ah=null)}gt(t){if(!this.Wr.yt())return null;this.ft&&this.oh();const i=this.$i.W().layout;return this.Wt.ar(i.fontSize,i.fontFamily),this.Wt.J(this.Et),this.Wt}_h(){if(this.rh){if(this.Wr.uh().length>0){const t=this.$i.St().he(),i=ci(t),n=1.5*ui(t)+2*i,s=this.dh();this.hh={above:di(n,s.aboveBar,s.inBar),below:di(n,s.belowBar,s.inBar)}}else this.hh=null;this.rh=!1}return this.hh}dh(){return null===this.ah&&(this.ah=this.Wr.uh().reduce(((t,i)=>(t[i.position]||(t[i.position]=!0),t)),{inBar:!1,aboveBar:!1,belowBar:!1})),this.ah}oh(){const t=this.Wr.Dt(),i=this.$i.St(),n=this.Wr.uh();this.eh&&(this.Et.it=n.map((t=>({ot:t.time,nt:0,st:0,Xs:0,ih:t.shape,O:t.color,Qr:t.Qr,wr:t.id,Kt:void 0}))),this.eh=!1);const s=this.$i.W().layout;this.Et.tt=null;const e=i.Zs();if(null===e)return;const r=this.Wr.Ct();if(null===r)return;if(0===this.Et.it.length)return;let h=NaN;const l=ci(i.he()),a={nh:l,sh:l};this.Et.tt=Bt(this.Et.it,e,!0);for(let e=this.Et.tt.from;e0&&(_.Kt={th:o.text,nt:0,st:0,Hi:0,At:0});const u=this.Wr.fh(o.time);null!==u&&gi(_,o,u,a,s.fontSize,l,t,i,r.Ot)}this.ft=!1}}class xi extends ni{constructor(t){super(t)}kr(){const t=this.Mr;t.yt=!1;const i=this.Is.W();if(!i.priceLineVisible||!this.Is.yt())return;const n=this.Is.Yr(0===i.priceLineSource);n.Zr||(t.yt=!0,t.st=n.ki,t.O=this.Is.ph(n.O),t.et=i.priceLineWidth,t.Nt=i.priceLineStyle)}}class Si extends J{constructor(t){super(),this.jt=t}Ei(t,i,n){t.yt=!1,i.yt=!1;const s=this.jt;if(!s.yt())return;const e=s.W(),r=e.lastValueVisible,h=""!==s.mh(),l=0===e.seriesLastValueMode,a=s.Yr(!1);if(a.Zr)return;r&&(t.Kt=this.bh(a,r,l),t.yt=0!==t.Kt.length),(h||l)&&(i.Kt=this.wh(a,r,h,l),i.yt=i.Kt.length>0);const o=s.ph(a.O),_=y(o);n.t=_.t,n.ki=a.ki,i.Vt=s.$t().Bt(a.ki/s.Dt().At()),t.Vt=o,t.O=_.i,i.O=_.i}wh(t,i,n,s){let e="";const r=this.jt.mh();return n&&0!==r.length&&(e+=`${r} `),i&&s&&(e+=this.jt.Dt().gh()?t.Mh:t.xh),e.trim()}bh(t,i,n){return i?n?this.jt.Dt().gh()?t.xh:t.Mh:t.Kt:""}}function ki(t,i,n,s){const e=Number.isFinite(i),r=Number.isFinite(n);return e&&r?t(i,n):e||r?e?i:n:s}class yi{constructor(t,i){this.Sh=t,this.kh=i}yh(t){return null!==t&&(this.Sh===t.Sh&&this.kh===t.kh)}Ch(){return new yi(this.Sh,this.kh)}Th(){return this.Sh}Ph(){return this.kh}Rh(){return this.kh-this.Sh}Ni(){return this.kh===this.Sh||Number.isNaN(this.kh)||Number.isNaN(this.Sh)}ts(t){return null===t?this:new yi(ki(Math.min,this.Th(),t.Th(),-1/0),ki(Math.max,this.Ph(),t.Ph(),1/0))}Dh(t){if(!P(t))return;if(0===this.kh-this.Sh)return;const i=.5*(this.kh+this.Sh);let n=this.kh-i,s=this.Sh-i;n*=t,s*=t,this.kh=i+n,this.Sh=i+s}Oh(t){P(t)&&(this.kh+=t,this.Sh+=t)}Vh(){return{minValue:this.Sh,maxValue:this.kh}}static Bh(t){return null===t?null:new yi(t.minValue,t.maxValue)}}class Ci{constructor(t,i){this.Ah=t,this.zh=i||null}Eh(){return this.Ah}Ih(){return this.zh}Vh(){return null===this.Ah?null:{priceRange:this.Ah.Vh(),margins:this.zh||void 0}}static Bh(t){return null===t?null:new Ci(yi.Bh(t.priceRange),t.margins)}}class Ti extends ni{constructor(t,i){super(t),this.Lh=i}kr(){const t=this.Mr;t.yt=!1;const i=this.Lh.W();if(!this.Is.yt()||!i.lineVisible)return;const n=this.Lh.Nh();null!==n&&(t.yt=!0,t.st=n,t.O=i.color,t.et=i.lineWidth,t.Nt=i.lineStyle,t.wr=this.Lh.W().id)}}class Pi extends J{constructor(t,i){super(),this.Wr=t,this.Lh=i}Ei(t,i,n){t.yt=!1,i.yt=!1;const s=this.Lh.W(),e=s.axisLabelVisible,r=""!==s.title,h=this.Wr;if(!e||!h.yt())return;const l=this.Lh.Nh();if(null===l)return;r&&(i.Kt=s.title,i.yt=!0),i.Vt=h.$t().Bt(l/h.Dt().At()),t.Kt=this.Fh(s.price),t.yt=!0;const a=y(s.axisLabelColor||s.color);n.t=a.t;const o=s.axisLabelTextColor||a.i;t.O=o,i.O=o,n.ki=l}Fh(t){const i=this.Wr.Ct();return null===i?"":this.Wr.Dt().Fi(t,i.Ot)}}class Ri{constructor(t,i){this.Wr=t,this.cn=i,this.Wh=new Ti(t,this),this._r=new Pi(t,this),this.jh=new ti(this._r,t,t.$t())}Hh(t){T(this.cn,t),this.bt(),this.Wr.$t().$h()}W(){return this.cn}Uh(){return this.Wh}qh(){return this.jh}Yh(){return this._r}bt(){this.Wh.bt(),this._r.bt()}Nh(){const t=this.Wr,i=t.Dt();if(t.$t().St().Ni()||i.Ni())return null;const n=t.Ct();return null===n?null:i.Rt(this.cn.price,n.Ot)}}class Di extends st{constructor(t){super(),this.$i=t}$t(){return this.$i}}const Oi={Bar:(t,i,n,s)=>{var e;const r=i.upColor,h=i.downColor,l=f(t(n,s)),a=v(l.Ot[0])<=v(l.Ot[3]);return{ue:null!==(e=l.O)&&void 0!==e?e:a?r:h}},Candlestick:(t,i,n,s)=>{var e,r,h;const l=i.upColor,a=i.downColor,o=i.borderUpColor,_=i.borderDownColor,u=i.wickUpColor,c=i.wickDownColor,d=f(t(n,s)),p=v(d.Ot[0])<=v(d.Ot[3]);return{ue:null!==(e=d.O)&&void 0!==e?e:p?l:a,Le:null!==(r=d.Vt)&&void 0!==r?r:p?o:_,Ie:null!==(h=d.Zh)&&void 0!==h?h:p?u:c}},Custom:(t,i,n,s)=>{var e;return{ue:null!==(e=f(t(n,s)).O)&&void 0!==e?e:i.color}},Area:(t,i,n,s)=>{var e,r,h,l;const a=f(t(n,s));return{ue:null!==(e=a.lt)&&void 0!==e?e:i.lineColor,lt:null!==(r=a.lt)&&void 0!==r?r:i.lineColor,Ts:null!==(h=a.Ts)&&void 0!==h?h:i.topColor,Ps:null!==(l=a.Ps)&&void 0!==l?l:i.bottomColor}},Baseline:(t,i,n,s)=>{var e,r,h,l,a,o;const _=f(t(n,s));return{ue:_.Ot[3]>=i.baseValue.price?i.topLineColor:i.bottomLineColor,Pe:null!==(e=_.Pe)&&void 0!==e?e:i.topLineColor,Re:null!==(r=_.Re)&&void 0!==r?r:i.bottomLineColor,Se:null!==(h=_.Se)&&void 0!==h?h:i.topFillColor1,ke:null!==(l=_.ke)&&void 0!==l?l:i.topFillColor2,ye:null!==(a=_.ye)&&void 0!==a?a:i.bottomFillColor1,Ce:null!==(o=_.Ce)&&void 0!==o?o:i.bottomFillColor2}},Line:(t,i,n,s)=>{var e,r;const h=f(t(n,s));return{ue:null!==(e=h.O)&&void 0!==e?e:i.color,lt:null!==(r=h.O)&&void 0!==r?r:i.color}},Histogram:(t,i,n,s)=>{var e;return{ue:null!==(e=f(t(n,s)).O)&&void 0!==e?e:i.color}}};class Vi{constructor(t){this.Xh=(t,i)=>void 0!==i?i.Ot:this.Wr.zn().Kh(t),this.Wr=t,this.Gh=Oi[t.Jh()]}Hs(t,i){return this.Gh(this.Xh,this.Wr.W(),t,i)}}var Bi;!function(t){t[t.NearestLeft=-1]="NearestLeft",t[t.None=0]="None",t[t.NearestRight=1]="NearestRight"}(Bi||(Bi={}));const Ai=30;class zi{constructor(){this.Qh=[],this.tl=new Map,this.il=new Map}nl(){return this.Xs()>0?this.Qh[this.Qh.length-1]:null}sl(){return this.Xs()>0?this.el(0):null}An(){return this.Xs()>0?this.el(this.Qh.length-1):null}Xs(){return this.Qh.length}Ni(){return 0===this.Xs()}Xr(t){return null!==this.rl(t,0)}Kh(t){return this.hl(t)}hl(t,i=0){const n=this.rl(t,i);return null===n?null:Object.assign(Object.assign({},this.ll(n)),{se:this.el(n)})}ie(){return this.Qh}al(t,i,n){if(this.Ni())return null;let s=null;for(const e of n){s=Ei(s,this.ol(t,i,e))}return s}J(t){this.il.clear(),this.tl.clear(),this.Qh=t}el(t){return this.Qh[t].se}ll(t){return this.Qh[t]}rl(t,i){const n=this._l(t);if(null===n&&0!==i)switch(i){case-1:return this.ul(t);case 1:return this.cl(t);default:throw new TypeError("Unknown search mode")}return n}ul(t){let i=this.dl(t);return i>0&&(i-=1),i!==this.Qh.length&&this.el(i)t.set.se>i))}vl(t,i,n){let s=null;for(let e=t;es.ml&&(s.ml=t)))}return s}ol(t,i,n){if(this.Ni())return null;let s=null;const e=f(this.sl()),r=f(this.An()),h=Math.max(t,e),l=Math.min(i,r),a=Math.ceil(h/Ai)*Ai,o=Math.max(a,Math.floor(l/Ai)*Ai);{const t=this.dl(h),e=this.fl(Math.min(l,a,i));s=Ei(s,this.vl(t,e,n))}let _=this.tl.get(n);void 0===_&&(_=new Map,this.tl.set(n,_));for(let t=Math.max(a+1,h);tnew Li(t)));return this.yl={gl:e,Ml:r},r}Qi(){var t,i,n,s;const e=null!==(n=null===(i=(t=this.Dl).timeAxisViews)||void 0===i?void 0:i.call(t))&&void 0!==n?n:[];if((null===(s=this.Cl)||void 0===s?void 0:s.gl)===e)return this.Cl.Ml;const r=this.Wr.$t().St(),h=e.map((t=>new Fi(t,r)));return this.Cl={gl:e,Ml:h},h}Rn(){var t,i,n,s;const e=null!==(n=null===(i=(t=this.Dl).priceAxisViews)||void 0===i?void 0:i.call(t))&&void 0!==n?n:[];if((null===(s=this.Tl)||void 0===s?void 0:s.gl)===e)return this.Tl.Ml;const r=this.Wr.Dt(),h=e.map((t=>new Wi(t,r)));return this.Tl={gl:e,Ml:h},h}Vl(){var t,i,n,s;const e=null!==(n=null===(i=(t=this.Dl).priceAxisPaneViews)||void 0===i?void 0:i.call(t))&&void 0!==n?n:[];if((null===(s=this.Pl)||void 0===s?void 0:s.gl)===e)return this.Pl.Ml;const r=e.map((t=>new Li(t)));return this.Pl={gl:e,Ml:r},r}Bl(){var t,i,n,s;const e=null!==(n=null===(i=(t=this.Dl).timeAxisPaneViews)||void 0===i?void 0:i.call(t))&&void 0!==n?n:[];if((null===(s=this.Rl)||void 0===s?void 0:s.gl)===e)return this.Rl.Ml;const r=e.map((t=>new Li(t)));return this.Rl={gl:e,Ml:r},r}Al(t,i){var n,s,e;return null!==(e=null===(s=(n=this.Dl).autoscaleInfo)||void 0===s?void 0:s.call(n,t,i))&&void 0!==e?e:null}br(t,i){var n,s,e;return null!==(e=null===(s=(n=this.Dl).hitTest)||void 0===s?void 0:s.call(n,t,i))&&void 0!==e?e:null}}function Hi(t,i,n,s){t.forEach((t=>{i(t).forEach((t=>{t.xl()===n&&s.push(t)}))}))}function $i(t){return t.Pn()}function Ui(t){return t.Vl()}function qi(t){return t.Bl()}class Yi extends Di{constructor(t,i,n,s,e){super(t),this.Et=new zi,this.Wh=new xi(this),this.zl=[],this.El=new si(this),this.Il=null,this.Ll=null,this.Nl=[],this.Fl=[],this.Wl=null,this.jl=[],this.cn=i,this.Hl=n;const r=new Si(this);this.rn=[r],this.jh=new ti(r,this,t),"Area"!==n&&"Line"!==n&&"Baseline"!==n||(this.Il=new ai(this)),this.$l(),this.Ul(e)}S(){null!==this.Wl&&clearTimeout(this.Wl)}ph(t){return this.cn.priceLineColor||t}Yr(t){const i={Zr:!0},n=this.Dt();if(this.$t().St().Ni()||n.Ni()||this.Et.Ni())return i;const s=this.$t().St().Zs(),e=this.Ct();if(null===s||null===e)return i;let r,h;if(t){const t=this.Et.nl();if(null===t)return i;r=t,h=t.se}else{const t=this.Et.hl(s.ui(),-1);if(null===t)return i;if(r=this.Et.Kh(t.se),null===r)return i;h=t.se}const l=r.Ot[3],a=this.$s().Hs(h,{Ot:r}),o=n.Rt(l,e.Ot);return{Zr:!1,_t:l,Kt:n.Fi(l,e.Ot),Mh:n.ql(l),xh:n.Yl(l,e.Ot),O:a.ue,ki:o,se:h}}$s(){return null!==this.Ll||(this.Ll=new Vi(this)),this.Ll}W(){return this.cn}Hh(t){const i=t.priceScaleId;void 0!==i&&i!==this.cn.priceScaleId&&this.$t().Zl(this,i),T(this.cn,t),void 0!==t.priceFormat&&(this.$l(),this.$t().Xl()),this.$t().Kl(this),this.$t().Gl(),this.wn.bt("options")}J(t,i){this.Et.J(t),this.Jl(),this.wn.bt("data"),this.dn.bt("data"),null!==this.Il&&(i&&i.Ql?this.Il.Hr():0===t.length&&this.Il.jr());const n=this.$t().cr(this);this.$t().ta(n),this.$t().Kl(this),this.$t().Gl(),this.$t().$h()}ia(t){this.Nl=t,this.Jl();const i=this.$t().cr(this);this.dn.bt("data"),this.$t().ta(i),this.$t().Kl(this),this.$t().Gl(),this.$t().$h()}na(){return this.Nl}uh(){return this.Fl}sa(t){const i=new Ri(this,t);return this.zl.push(i),this.$t().Kl(this),i}ea(t){const i=this.zl.indexOf(t);-1!==i&&this.zl.splice(i,1),this.$t().Kl(this)}Jh(){return this.Hl}Ct(){const t=this.ra();return null===t?null:{Ot:t.Ot[3],ha:t.ot}}ra(){const t=this.$t().St().Zs();if(null===t)return null;const i=t.Os();return this.Et.hl(i,1)}zn(){return this.Et}fh(t){const i=this.Et.Kh(t);return null===i?null:"Bar"===this.Hl||"Candlestick"===this.Hl||"Custom"===this.Hl?{we:i.Ot[0],ge:i.Ot[1],Me:i.Ot[2],xe:i.Ot[3]}:i.Ot[3]}la(t){const i=[];Hi(this.jl,$i,"top",i);const n=this.Il;return null!==n&&n.yt()?(null===this.Wl&&n.Ur()&&(this.Wl=setTimeout((()=>{this.Wl=null,this.$t().aa()}),0)),n.$r(),i.unshift(n),i):i}Pn(){const t=[];this.oa()||t.push(this.El),t.push(this.wn,this.Wh,this.dn);const i=this.zl.map((t=>t.Uh()));return t.push(...i),Hi(this.jl,$i,"normal",t),t}_a(){return this.ua($i,"bottom")}ca(t){return this.ua(Ui,t)}da(t){return this.ua(qi,t)}fa(t,i){return this.jl.map((n=>n.br(t,i))).filter((t=>null!==t))}Ji(t){return[this.jh,...this.zl.map((t=>t.qh()))]}Rn(t,i){if(i!==this.Yi&&!this.oa())return[];const n=[...this.rn];for(const t of this.zl)n.push(t.Yh());return this.jl.forEach((t=>{n.push(...t.Rn())})),n}Qi(){const t=[];return this.jl.forEach((i=>{t.push(...i.Qi())})),t}Al(t,i){if(void 0!==this.cn.autoscaleInfoProvider){const n=this.cn.autoscaleInfoProvider((()=>{const n=this.va(t,i);return null===n?null:n.Vh()}));return Ci.Bh(n)}return this.va(t,i)}pa(){return this.cn.priceFormat.minMove}ma(){return this.ba}On(){var t;this.wn.bt(),this.dn.bt();for(const t of this.rn)t.bt();for(const t of this.zl)t.bt();this.Wh.bt(),this.El.bt(),null===(t=this.Il)||void 0===t||t.bt(),this.jl.forEach((t=>t.On()))}Dt(){return f(super.Dt())}kt(t){if(!(("Line"===this.Hl||"Area"===this.Hl||"Baseline"===this.Hl)&&this.cn.crosshairMarkerVisible))return null;const i=this.Et.Kh(t);if(null===i)return null;return{_t:i.Ot[3],ht:this.wa(),Vt:this.ga(),Pt:this.Ma(),Tt:this.xa(t)}}mh(){return this.cn.title}yt(){return this.cn.visible}Sa(t){this.jl.push(new ji(t,this))}ka(t){this.jl=this.jl.filter((i=>i.Ol()!==t))}ya(){if(this.wn instanceof qt!=!1)return t=>this.wn.Fe(t)}Ca(){if(this.wn instanceof qt!=!1)return t=>this.wn.We(t)}oa(){return!ht(this.Dt().Ta())}va(t,i){if(!R(t)||!R(i)||this.Et.Ni())return null;const n="Line"===this.Hl||"Area"===this.Hl||"Baseline"===this.Hl||"Histogram"===this.Hl?[3]:[2,1],s=this.Et.al(t,i,n);let e=null!==s?new yi(s.pl,s.ml):null;if("Histogram"===this.Jh()){const t=this.cn.base,i=new yi(t,t);e=null!==e?e.ts(i):i}let r=this.dn._h();return this.jl.forEach((n=>{const s=n.Al(t,i);if(null==s?void 0:s.priceRange){const t=new yi(s.priceRange.minValue,s.priceRange.maxValue);e=null!==e?e.ts(t):t}var h,l,a,o;(null==s?void 0:s.margins)&&(h=r,l=s.margins,r={above:Math.max(null!==(a=null==h?void 0:h.above)&&void 0!==a?a:0,l.above),below:Math.max(null!==(o=null==h?void 0:h.below)&&void 0!==o?o:0,l.below)})})),new Ci(e,r)}wa(){switch(this.Hl){case"Line":case"Area":case"Baseline":return this.cn.crosshairMarkerRadius}return 0}ga(){switch(this.Hl){case"Line":case"Area":case"Baseline":{const t=this.cn.crosshairMarkerBorderColor;if(0!==t.length)return t}}return null}Ma(){switch(this.Hl){case"Line":case"Area":case"Baseline":return this.cn.crosshairMarkerBorderWidth}return 0}xa(t){switch(this.Hl){case"Line":case"Area":case"Baseline":{const t=this.cn.crosshairMarkerBackgroundColor;if(0!==t.length)return t}}return this.$s().Hs(t).ue}$l(){switch(this.cn.priceFormat.type){case"custom":this.ba={format:this.cn.priceFormat.formatter};break;case"volume":this.ba=new ct(this.cn.priceFormat.precision);break;case"percent":this.ba=new ut(this.cn.priceFormat.precision);break;default:{const t=Math.pow(10,this.cn.priceFormat.precision);this.ba=new _t(t,this.cn.priceFormat.minMove*t)}}null!==this.Yi&&this.Yi.Pa()}Jl(){const t=this.$t().St();if(!t.Ra()||this.Et.Ni())return void(this.Fl=[]);const i=f(this.Et.sl());this.Fl=this.Nl.map(((n,s)=>{const e=f(t.Da(n.time,!0)),r=et instanceof Yi)).reduce(((t,s)=>{if(n.dr(s)||!s.yt())return t;const e=s.Dt(),r=s.zn();if(e.Ni()||!r.Xr(i))return t;const h=r.Kh(i);if(null===h)return t;const l=v(s.Ct());return t.concat([e.Rt(h.Ot[3],l.Ot)])}),[]);if(0===l.length)return s;l.sort(((t,i)=>Math.abs(t-h)-Math.abs(i-h)));const a=l[0];return s=e.pn(a,r),s}}class Xi extends N{constructor(){super(...arguments),this.Et=null}J(t){this.Et=t}K({context:t,bitmapSize:i,horizontalPixelRatio:n,verticalPixelRatio:s}){if(null===this.Et)return;const e=Math.max(1,Math.floor(n));t.lineWidth=e,function(t,i){t.save(),t.lineWidth%2&&t.translate(.5,.5),i(),t.restore()}(t,(()=>{const r=f(this.Et);if(r.Ba){t.strokeStyle=r.Aa,_(t,r.za),t.beginPath();for(const s of r.Ea){const r=Math.round(s.Ia*n);t.moveTo(r,-e),t.lineTo(r,i.height+e)}t.stroke()}if(r.La){t.strokeStyle=r.Na,_(t,r.Fa),t.beginPath();for(const n of r.Wa){const r=Math.round(n.Ia*s);t.moveTo(-e,r),t.lineTo(i.width+e,r)}t.stroke()}}))}}class Ki{constructor(t){this.Wt=new Xi,this.ft=!0,this.tn=t}bt(){this.ft=!0}gt(){if(this.ft){const t=this.tn.$t().W().grid,i={La:t.horzLines.visible,Ba:t.vertLines.visible,Na:t.horzLines.color,Aa:t.vertLines.color,Fa:t.horzLines.style,za:t.vertLines.style,Wa:this.tn.vn().ja(),Ea:(this.tn.$t().St().ja()||[]).map((t=>({Ia:t.coord})))};this.Wt.J(i),this.ft=!1}return this.Wt}}class Gi{constructor(t){this.wn=new Ki(t)}Uh(){return this.wn}}const Ji={Ha:4,$a:1e-4};function Qi(t,i){const n=100*(t-i)/i;return i<0?-n:n}function tn(t,i){const n=Qi(t.Th(),i),s=Qi(t.Ph(),i);return new yi(n,s)}function nn(t,i){const n=100*(t-i)/i+100;return i<0?-n:n}function sn(t,i){const n=nn(t.Th(),i),s=nn(t.Ph(),i);return new yi(n,s)}function en(t,i){const n=Math.abs(t);if(n<1e-15)return 0;const s=Math.log10(n+i.$a)+i.Ha;return t<0?-s:s}function rn(t,i){const n=Math.abs(t);if(n<1e-15)return 0;const s=Math.pow(10,n-i.Ha)-i.$a;return t<0?-s:s}function hn(t,i){if(null===t)return null;const n=en(t.Th(),i),s=en(t.Ph(),i);return new yi(n,s)}function ln(t,i){if(null===t)return null;const n=rn(t.Th(),i),s=rn(t.Ph(),i);return new yi(n,s)}function an(t){if(null===t)return Ji;const i=Math.abs(t.Ph()-t.Th());if(i>=1||i<1e-15)return Ji;const n=Math.ceil(Math.abs(Math.log10(i))),s=Ji.Ha+n;return{Ha:s,$a:1/Math.pow(10,s)}}class on{constructor(t,i){if(this.Ua=t,this.qa=i,function(t){if(t<0)return!1;for(let i=t;i>1;i/=10)if(i%10!=0)return!1;return!0}(this.Ua))this.Ya=[2,2.5,2];else{this.Ya=[];for(let t=this.Ua;1!==t;){if(t%2==0)this.Ya.push(2),t/=2;else{if(t%5!=0)throw new Error("unexpected base");this.Ya.push(2,2.5),t/=5}if(this.Ya.length>100)throw new Error("something wrong with base")}}}Za(t,i,n){const s=0===this.Ua?0:1/this.Ua;let e=Math.pow(10,Math.max(0,Math.ceil(Math.log10(t-i)))),r=0,h=this.qa[0];for(;;){const t=Mt(e,s,1e-14)&&e>s+1e-14,i=Mt(e,n*h,1e-14),l=Mt(e,1,1e-14);if(!(t&&i&&l))break;e/=h,h=this.qa[++r%this.qa.length]}if(e<=s+1e-14&&(e=s),e=Math.max(1,e),this.Ya.length>0&&(l=e,a=1,o=1e-14,Math.abs(l-a)s+1e-14;)e/=h,h=this.Ya[++r%this.Ya.length];var l,a,o;return e}}class _n{constructor(t,i,n,s){this.Xa=[],this.Ii=t,this.Ua=i,this.Ka=n,this.Ga=s}Za(t,i){if(t=o?1:-1;let d=null,f=0;for(let n=a-u;n>o;n-=_){const s=this.Ga(n,i,!0);null!==d&&Math.abs(s-d)l||(ff(t.Xi())-f(i.Xi())))}var cn;!function(t){t[t.Normal=0]="Normal",t[t.Logarithmic=1]="Logarithmic",t[t.Percentage=2]="Percentage",t[t.IndexedTo100=3]="IndexedTo100"}(cn||(cn={}));const dn=new ut,fn=new _t(100,1);class vn{constructor(t,i,n,s){this.ro=0,this.ho=null,this.Ah=null,this.lo=null,this.ao={oo:!1,_o:null},this.uo=0,this.co=0,this.do=new C,this.fo=new C,this.vo=[],this.po=null,this.mo=null,this.bo=null,this.wo=null,this.ba=fn,this.Mo=an(null),this.xo=t,this.cn=i,this.So=n,this.ko=s,this.yo=new _n(this,100,this.Co.bind(this),this.To.bind(this))}Ta(){return this.xo}W(){return this.cn}Hh(t){if(T(this.cn,t),this.Pa(),void 0!==t.mode&&this.Po({yr:t.mode}),void 0!==t.scaleMargins){const i=d(t.scaleMargins.top),n=d(t.scaleMargins.bottom);if(i<0||i>1)throw new Error(`Invalid top margin - expect value between 0 and 1, given=${i}`);if(n<0||n>1)throw new Error(`Invalid bottom margin - expect value between 0 and 1, given=${n}`);if(i+n>1)throw new Error(`Invalid margins - sum of margins must be less than 1, given=${i+n}`);this.Ro(),this.mo=null}}Do(){return this.cn.autoScale}eo(){return 1===this.cn.mode}gh(){return 2===this.cn.mode}Oo(){return 3===this.cn.mode}yr(){return{Wn:this.cn.autoScale,Vo:this.cn.invertScale,yr:this.cn.mode}}Po(t){const i=this.yr();let n=null;void 0!==t.Wn&&(this.cn.autoScale=t.Wn),void 0!==t.yr&&(this.cn.mode=t.yr,2!==t.yr&&3!==t.yr||(this.cn.autoScale=!0),this.ao.oo=!1),1===i.yr&&t.yr!==i.yr&&(!function(t,i){if(null===t)return!1;const n=rn(t.Th(),i),s=rn(t.Ph(),i);return isFinite(n)&&isFinite(s)}(this.Ah,this.Mo)?this.cn.autoScale=!0:(n=ln(this.Ah,this.Mo),null!==n&&this.Bo(n))),1===t.yr&&t.yr!==i.yr&&(n=hn(this.Ah,this.Mo),null!==n&&this.Bo(n));const s=i.yr!==this.cn.mode;s&&(2===i.yr||this.gh())&&this.Pa(),s&&(3===i.yr||this.Oo())&&this.Pa(),void 0!==t.Vo&&i.Vo!==t.Vo&&(this.cn.invertScale=t.Vo,this.Ao()),this.fo.m(i,this.yr())}zo(){return this.fo}P(){return this.So.fontSize}At(){return this.ro}Eo(t){this.ro!==t&&(this.ro=t,this.Ro(),this.mo=null)}Io(){if(this.ho)return this.ho;const t=this.At()-this.Lo()-this.No();return this.ho=t,t}Eh(){return this.Fo(),this.Ah}Bo(t,i){const n=this.Ah;(i||null===n&&null!==t||null!==n&&!n.yh(t))&&(this.mo=null,this.Ah=t)}Ni(){return this.Fo(),0===this.ro||!this.Ah||this.Ah.Ni()}Wo(t){return this.Vo()?t:this.At()-1-t}Rt(t,i){return this.gh()?t=Qi(t,i):this.Oo()&&(t=nn(t,i)),this.To(t,i)}Qs(t,i,n){this.Fo();const s=this.No(),e=f(this.Eh()),r=e.Th(),h=e.Ph(),l=this.Io()-1,a=this.Vo(),o=l/(h-r),_=void 0===n?0:n.from,u=void 0===n?t.length:n.to,c=this.jo();for(let n=_;nt.On()))}Pa(){this.mo=null;const t=this.s_();let i=100;null!==t&&(i=Math.round(1/t.pa())),this.ba=fn,this.gh()?(this.ba=dn,i=100):this.Oo()?(this.ba=new _t(100,1),i=100):null!==t&&(this.ba=t.ma()),this.yo=new _n(this,i,this.Co.bind(this),this.To.bind(this)),this.yo.Qa()}qo(){this.po=null}s_(){return this.vo[0]||null}Lo(){return this.Vo()?this.cn.scaleMargins.bottom*this.At()+this.co:this.cn.scaleMargins.top*this.At()+this.uo}No(){return this.Vo()?this.cn.scaleMargins.top*this.At()+this.uo:this.cn.scaleMargins.bottom*this.At()+this.co}Fo(){this.ao.oo||(this.ao.oo=!0,this.h_())}Ro(){this.ho=null}To(t,i){if(this.Fo(),this.Ni())return 0;t=this.eo()&&t?en(t,this.Mo):t;const n=f(this.Eh()),s=this.No()+(this.Io()-1)*(t-n.Th())/n.Rh();return this.Wo(s)}Co(t,i){if(this.Fo(),this.Ni())return 0;const n=this.Wo(t),s=f(this.Eh()),e=s.Th()+s.Rh()*((n-this.No())/(this.Io()-1));return this.eo()?rn(e,this.Mo):e}Ao(){this.mo=null,this.yo.Qa()}h_(){const t=this.ao._o;if(null===t)return;let i=null;const n=this.e_();let s=0,e=0;for(const r of n){if(!r.yt())continue;const n=r.Ct();if(null===n)continue;const h=r.Al(t.Os(),t.ui());let l=h&&h.Eh();if(null!==l){switch(this.cn.mode){case 1:l=hn(l,this.Mo);break;case 2:l=tn(l,n.Ot);break;case 3:l=sn(l,n.Ot)}if(i=null===i?l:i.ts(f(l)),null!==h){const t=h.Ih();null!==t&&(s=Math.max(s,t.above),e=Math.max(e,t.below))}}}if(s===this.uo&&e===this.co||(this.uo=s,this.co=e,this.mo=null,this.Ro()),null!==i){if(i.Th()===i.Ph()){const t=this.s_(),n=5*(null===t||this.gh()||this.Oo()?1:t.pa());this.eo()&&(i=ln(i,this.Mo)),i=new yi(i.Th()-n,i.Ph()+n),this.eo()&&(i=hn(i,this.Mo))}if(this.eo()){const t=ln(i,this.Mo),n=an(t);if(r=n,h=this.Mo,r.Ha!==h.Ha||r.$a!==h.$a){const s=null!==this.lo?ln(this.lo,this.Mo):null;this.Mo=n,i=hn(t,n),null!==s&&(this.lo=hn(s,n))}}this.Bo(i)}else null===this.Ah&&(this.Bo(new yi(-.5,.5)),this.Mo=an(null));var r,h;this.ao.oo=!0}jo(){return this.gh()?Qi:this.Oo()?nn:this.eo()?t=>en(t,this.Mo):null}l_(t,i,n){return void 0===i?(void 0===n&&(n=this.ma()),n.format(t)):i(t)}Fh(t,i){return this.l_(t,this.ko.priceFormatter,i)}n_(t,i){return this.l_(t,this.ko.percentageFormatter,i)}}class pn{constructor(t,i){this.vo=[],this.a_=new Map,this.ro=0,this.o_=0,this.__=1e3,this.po=null,this.u_=new C,this.kl=t,this.$i=i,this.c_=new Gi(this);const n=i.W();this.d_=this.f_("left",n.leftPriceScale),this.v_=this.f_("right",n.rightPriceScale),this.d_.zo().l(this.p_.bind(this,this.d_),this),this.v_.zo().l(this.p_.bind(this,this.v_),this),this.m_(n)}m_(t){if(t.leftPriceScale&&this.d_.Hh(t.leftPriceScale),t.rightPriceScale&&this.v_.Hh(t.rightPriceScale),t.localization&&(this.d_.Pa(),this.v_.Pa()),t.overlayPriceScales){const i=Array.from(this.a_.values());for(const n of i){const i=f(n[0].Dt());i.Hh(t.overlayPriceScales),t.localization&&i.Pa()}}}b_(t){switch(t){case"left":return this.d_;case"right":return this.v_}return this.a_.has(t)?d(this.a_.get(t))[0].Dt():null}S(){this.$t().w_().p(this),this.d_.zo().p(this),this.v_.zo().p(this),this.vo.forEach((t=>{t.S&&t.S()})),this.u_.m()}g_(){return this.__}M_(t){this.__=t}$t(){return this.$i}Hi(){return this.o_}At(){return this.ro}x_(t){this.o_=t,this.S_()}Eo(t){this.ro=t,this.d_.Eo(t),this.v_.Eo(t),this.vo.forEach((i=>{if(this.dr(i)){const n=i.Dt();null!==n&&n.Eo(t)}})),this.S_()}Va(){return this.vo}dr(t){const i=t.Dt();return null===i||this.d_!==i&&this.v_!==i}Uo(t,i,n){const s=void 0!==n?n:this.y_().k_+1;this.C_(t,i,s)}Yo(t){const i=this.vo.indexOf(t);c(-1!==i,"removeDataSource: invalid data source"),this.vo.splice(i,1);const n=f(t.Dt()).Ta();if(this.a_.has(n)){const i=d(this.a_.get(n)),s=i.indexOf(t);-1!==s&&(i.splice(s,1),0===i.length&&this.a_.delete(n))}const s=t.Dt();s&&s.Va().indexOf(t)>=0&&s.Yo(t),null!==s&&(s.qo(),this.T_(s)),this.po=null}pr(t){return t===this.d_?"left":t===this.v_?"right":"overlay"}P_(){return this.d_}R_(){return this.v_}D_(t,i){t.Ko(i)}O_(t,i){t.Go(i),this.S_()}V_(t){t.Jo()}B_(t,i){t.Qo(i)}A_(t,i){t.t_(i),this.S_()}z_(t){t.i_()}S_(){this.vo.forEach((t=>{t.On()}))}vn(){let t=null;return this.$i.W().rightPriceScale.visible&&0!==this.v_.Va().length?t=this.v_:this.$i.W().leftPriceScale.visible&&0!==this.d_.Va().length?t=this.d_:0!==this.vo.length&&(t=this.vo[0].Dt()),null===t&&(t=this.v_),t}vr(){let t=null;return this.$i.W().rightPriceScale.visible?t=this.v_:this.$i.W().leftPriceScale.visible&&(t=this.d_),t}T_(t){null!==t&&t.Do()&&this.E_(t)}I_(t){const i=this.kl.Zs();t.Po({Wn:!0}),null!==i&&t.r_(i),this.S_()}L_(){this.E_(this.d_),this.E_(this.v_)}N_(){this.T_(this.d_),this.T_(this.v_),this.vo.forEach((t=>{this.dr(t)&&this.T_(t.Dt())})),this.S_(),this.$i.$h()}$o(){return null===this.po&&(this.po=un(this.vo)),this.po}F_(){return this.u_}W_(){return this.c_}E_(t){const i=t.e_();if(i&&i.length>0&&!this.kl.Ni()){const i=this.kl.Zs();null!==i&&t.r_(i)}t.On()}y_(){const t=this.$o();if(0===t.length)return{j_:0,k_:0};let i=0,n=0;for(let s=0;sn&&(n=e))}return{j_:i,k_:n}}C_(t,i,n){let s=this.b_(i);if(null===s&&(s=this.f_(i,this.$i.W().overlayPriceScales)),this.vo.push(t),!ht(i)){const n=this.a_.get(i)||[];n.push(t),this.a_.set(i,n)}s.Uo(t),t.Gi(s),t.Ki(n),this.T_(s),this.po=null}p_(t,i,n){i.yr!==n.yr&&this.E_(t)}f_(t,i){const n=Object.assign({visible:!0,autoScale:!0},V(i)),s=new vn(t,n,this.$i.W().layout,this.$i.W().localization);return s.Eo(this.At()),s}}class mn{constructor(t,i,n=50){this.Xe=0,this.Ke=1,this.Ge=1,this.Qe=new Map,this.Je=new Map,this.H_=t,this.U_=i,this.tr=n}q_(t){const i=t.time,n=this.U_.cacheKey(i),s=this.Qe.get(n);if(void 0!==s)return s.Y_;if(this.Xe===this.tr){const t=this.Je.get(this.Ge);this.Je.delete(this.Ge),this.Qe.delete(d(t)),this.Ge++,this.Xe--}const e=this.H_(t);return this.Qe.set(n,{Y_:e,er:this.Ke}),this.Je.set(this.Ke,n),this.Xe++,this.Ke++,e}}class bn{constructor(t,i){c(t<=i,"right should be >= left"),this.Z_=t,this.X_=i}Os(){return this.Z_}ui(){return this.X_}K_(){return this.X_-this.Z_+1}Xr(t){return this.Z_<=t&&t<=this.X_}yh(t){return this.Z_===t.Os()&&this.X_===t.ui()}}function wn(t,i){return null===t||null===i?t===i:t.yh(i)}class gn{constructor(){this.G_=new Map,this.Qe=null,this.J_=!1}Q_(t){this.J_=t,this.Qe=null}tu(t,i){this.iu(i),this.Qe=null;for(let n=i;n{t<=n[0].index?i.push(s):n.splice(Rt(n,t,(i=>i.indexi-t))){if(!this.G_.get(n))continue;const s=i;i=[];const e=s.length;let r=0;const h=d(this.G_.get(n)),l=h.length;let a=1/0,o=-1/0;for(let n=0;n=t&&_-o>=t)i.push(l),o=_;else if(this.J_)return s}for(;ri.weight?t:i}class Sn{constructor(t,i,n,s){this.o_=0,this.ou=null,this._u=[],this.wo=null,this.bo=null,this.uu=new gn,this.cu=new Map,this.du=Mn.au(),this.fu=!0,this.vu=new C,this.pu=new C,this.mu=new C,this.bu=null,this.wu=null,this.gu=[],this.cn=i,this.ko=n,this.Mu=i.rightOffset,this.xu=i.barSpacing,this.$i=t,this.U_=s,this.Su(),this.uu.Q_(i.uniformDistribution)}W(){return this.cn}ku(t){T(this.ko,t),this.yu(),this.Su()}Hh(t,i){var n;T(this.cn,t),this.cn.fixLeftEdge&&this.Cu(),this.cn.fixRightEdge&&this.Tu(),void 0!==t.barSpacing&&this.$i.Gn(t.barSpacing),void 0!==t.rightOffset&&this.$i.Jn(t.rightOffset),void 0!==t.minBarSpacing&&this.$i.Gn(null!==(n=t.barSpacing)&&void 0!==n?n:this.xu),this.yu(),this.Su(),this.mu.m()}mn(t){var i,n;return null!==(n=null===(i=this._u[t])||void 0===i?void 0:i.time)&&void 0!==n?n:null}Ui(t){var i;return null!==(i=this._u[t])&&void 0!==i?i:null}Da(t,i){if(this._u.length<1)return null;if(this.U_.key(t)>this.U_.key(this._u[this._u.length-1].time))return i?this._u.length-1:null;const n=Rt(this._u,this.U_.key(t),((t,i)=>this.U_.key(t.time)0}Zs(){return this.Pu(),this.du.hu()}Ru(){return this.Pu(),this.du.lu()}Du(){const t=this.Zs();if(null===t)return null;const i={from:t.Os(),to:t.ui()};return this.Ou(i)}Ou(t){const i=Math.round(t.from),n=Math.round(t.to),s=f(this.Vu()),e=f(this.Bu());return{from:f(this.Ui(Math.max(s,i))),to:f(this.Ui(Math.min(e,n)))}}Au(t){return{from:f(this.Da(t.from,!0)),to:f(this.Da(t.to,!0))}}Hi(){return this.o_}x_(t){if(!isFinite(t)||t<=0)return;if(this.o_===t)return;const i=this.Ru(),n=this.o_;if(this.o_=t,this.fu=!0,this.cn.lockVisibleTimeRangeOnResize&&0!==n){const i=this.xu*t/n;this.xu=i}if(this.cn.fixLeftEdge&&null!==i&&i.Os()<=0){const i=n-t;this.Mu-=Math.round(i/this.xu)+1,this.fu=!0}this.zu(),this.Eu()}zt(t){if(this.Ni()||!R(t))return 0;const i=this.Iu()+this.Mu-t;return this.o_-(i+.5)*this.xu-1}Js(t,i){const n=this.Iu(),s=void 0===i?0:i.from,e=void 0===i?t.length:i.to;for(let i=s;ii/2&&!o?n.needAlignCoordinate=!1:n.needAlignCoordinate=_&&t.index<=l||u&&t.index>=a,c++}return this.gu.length=c,this.wu=this.gu,this.gu}Uu(){this.fu=!0,this.Gn(this.cn.barSpacing),this.Jn(this.cn.rightOffset)}qu(t){this.fu=!0,this.ou=t,this.Eu(),this.Cu()}Yu(t,i){const n=this.Nu(t),s=this.he(),e=s+i*(s/10);this.Gn(e),this.cn.rightBarStaysOnScroll||this.Jn(this.ju()+(n-this.Nu(t)))}Ko(t){this.wo&&this.i_(),null===this.bo&&null===this.bu&&(this.Ni()||(this.bo=t,this.Zu()))}Go(t){if(null===this.bu)return;const i=gt(this.o_-t,0,this.o_),n=gt(this.o_-f(this.bo),0,this.o_);0!==i&&0!==n&&this.Gn(this.bu.he*i/n)}Jo(){null!==this.bo&&(this.bo=null,this.Xu())}Qo(t){null===this.wo&&null===this.bu&&(this.Ni()||(this.wo=t,this.Zu()))}t_(t){if(null===this.wo)return;const i=(this.wo-t)/this.he();this.Mu=f(this.bu).ju+i,this.fu=!0,this.Eu()}i_(){null!==this.wo&&(this.wo=null,this.Xu())}Ku(){this.Gu(this.cn.rightOffset)}Gu(t,i=400){if(!isFinite(t))throw new RangeError("offset is required and must be finite number");if(!isFinite(i)||i<=0)throw new RangeError("animationDuration (optional) must be finite positive number");const n=this.Mu,s=performance.now();this.$i.Zn({Ju:t=>(t-s)/i>=1,Qu:e=>{const r=(e-s)/i;return r>=1?t:n+(t-n)*r}})}bt(t,i){this.fu=!0,this._u=t,this.uu.tu(t,i),this.Eu()}tc(){return this.vu}nc(){return this.pu}sc(){return this.mu}Iu(){return this.ou||0}ec(t){const i=t.K_();this.Wu(this.o_/i),this.Mu=t.ui()-this.Iu(),this.Eu(),this.fu=!0,this.$i.Fu(),this.$i.$h()}rc(){const t=this.Vu(),i=this.Bu();null!==t&&null!==i&&this.ec(new bn(t,i+this.cn.rightOffset))}hc(t){const i=new bn(t.from,t.to);this.ec(i)}qi(t){return void 0!==this.ko.timeFormatter?this.ko.timeFormatter(t.originalTime):this.U_.formatHorzItem(t.time)}Hu(){const{handleScroll:t,handleScale:i}=this.$i.W();return!(t.horzTouchDrag||t.mouseWheel||t.pressedMouseMove||t.vertTouchDrag||i.axisDoubleClickReset.time||i.axisPressedMouseMove.time||i.mouseWheel||i.pinch)}Vu(){return 0===this._u.length?null:0}Bu(){return 0===this._u.length?null:this._u.length-1}lc(t){return(this.o_-1-t)/this.xu}Nu(t){const i=this.lc(t),n=this.Iu()+this.Mu-i;return Math.round(1e6*n)/1e6}Wu(t){const i=this.xu;this.xu=t,this.zu(),i!==this.xu&&(this.fu=!0,this.ac())}Pu(){if(!this.fu)return;if(this.fu=!1,this.Ni())return void this.oc(Mn.au());const t=this.Iu(),i=this.o_/this.xu,n=this.Mu+t,s=new bn(n-i+1,n);this.oc(new Mn(s))}zu(){const t=this._c();if(this.xut&&(this.xu=t,this.fu=!0)}}_c(){return this.cn.fixLeftEdge&&this.cn.fixRightEdge&&0!==this._u.length?this.o_/this._u.length:this.cn.minBarSpacing}Eu(){const t=this.uc();this.Mu>t&&(this.Mu=t,this.fu=!0);const i=this.cc();null!==i&&this.Muthis.dc(t)),this.U_),this.cu.set(t.weight,i)),i.q_(t)}dc(t){return this.U_.formatTickmark(t,this.ko)}oc(t){const i=this.du;this.du=t,wn(i.hu(),this.du.hu())||this.vu.m(),wn(i.lu(),this.du.lu())||this.pu.m(),this.ac()}ac(){this.wu=null}yu(){this.ac(),this.cu.clear()}Su(){this.U_.updateFormatter(this.ko)}Cu(){if(!this.cn.fixLeftEdge)return;const t=this.Vu();if(null===t)return;const i=this.Zs();if(null===i)return;const n=i.Os()-t;if(n<0){const t=this.Mu-n-1;this.Jn(t)}this.zu()}Tu(){this.Eu(),this.zu()}}class kn{X(t,i,n){t.useMediaCoordinateSpace((t=>this.K(t,i,n)))}wl(t,i,n){t.useMediaCoordinateSpace((t=>this.fc(t,i,n)))}fc(t,i,n){}}class yn extends kn{constructor(t){super(),this.vc=new Map,this.Et=t}K(t){}fc(t){if(!this.Et.yt)return;const{context:i,mediaSize:n}=t;let s=0;for(const t of this.Et.mc){if(0===t.Kt.length)continue;i.font=t.R;const e=this.bc(i,t.Kt);e>n.width?t.Yu=n.width/e:t.Yu=1,s+=t.wc*t.Yu}let e=0;switch(this.Et.gc){case"top":e=0;break;case"center":e=Math.max((n.height-s)/2,0);break;case"bottom":e=Math.max(n.height-s,0)}i.fillStyle=this.Et.O;for(const t of this.Et.mc){i.save();let s=0;switch(this.Et.Mc){case"left":i.textAlign="left",s=t.wc/2;break;case"center":i.textAlign="center",s=n.width/2;break;case"right":i.textAlign="right",s=n.width-1-t.wc/2}i.translate(s,e),i.textBaseline="top",i.font=t.R,i.scale(t.Yu,t.Yu),i.fillText(t.Kt,0,t.xc),i.restore(),e+=t.wc*t.Yu}}bc(t,i){const n=this.Sc(t.font);let s=n.get(i);return void 0===s&&(s=t.measureText(i).width,n.set(i,s)),s}Sc(t){let i=this.vc.get(t);return void 0===i&&(i=new Map,this.vc.set(t,i)),i}}class Cn{constructor(t){this.ft=!0,this.Ft={yt:!1,O:"",mc:[],gc:"center",Mc:"center"},this.Wt=new yn(this.Ft),this.jt=t}bt(){this.ft=!0}gt(){return this.ft&&(this.Mt(),this.ft=!1),this.Wt}Mt(){const t=this.jt.W(),i=this.Ft;i.yt=t.visible,i.yt&&(i.O=t.color,i.Mc=t.horzAlign,i.gc=t.vertAlign,i.mc=[{Kt:t.text,R:E(t.fontSize,t.fontFamily,t.fontStyle),wc:1.2*t.fontSize,xc:0,Yu:0}])}}class Tn extends st{constructor(t,i){super(),this.cn=i,this.wn=new Cn(this)}Rn(){return[]}Pn(){return[this.wn]}W(){return this.cn}On(){this.wn.bt()}}var Pn,Rn,Dn,On,Vn;!function(t){t[t.OnTouchEnd=0]="OnTouchEnd",t[t.OnNextTap=1]="OnNextTap"}(Pn||(Pn={}));class Bn{constructor(t,i,n){this.kc=[],this.yc=[],this.o_=0,this.Cc=null,this.Tc=new C,this.Pc=new C,this.Rc=null,this.Dc=t,this.cn=i,this.U_=n,this.Oc=new I(this),this.kl=new Sn(this,i.timeScale,this.cn.localization,n),this.vt=new rt(this,i.crosshair),this.Vc=new Zi(i.crosshair),this.Bc=new Tn(this,i.watermark),this.Ac(),this.kc[0].M_(2e3),this.zc=this.Ec(0),this.Ic=this.Ec(1)}Xl(){this.Lc(lt.es())}$h(){this.Lc(lt.ss())}aa(){this.Lc(new lt(1))}Kl(t){const i=this.Nc(t);this.Lc(i)}Fc(){return this.Cc}Wc(t){const i=this.Cc;this.Cc=t,null!==i&&this.Kl(i.jc),null!==t&&this.Kl(t.jc)}W(){return this.cn}Hh(t){T(this.cn,t),this.kc.forEach((i=>i.m_(t))),void 0!==t.timeScale&&this.kl.Hh(t.timeScale),void 0!==t.localization&&this.kl.ku(t.localization),(t.leftPriceScale||t.rightPriceScale)&&this.Tc.m(),this.zc=this.Ec(0),this.Ic=this.Ec(1),this.Xl()}Hc(t,i){if("left"===t)return void this.Hh({leftPriceScale:i});if("right"===t)return void this.Hh({rightPriceScale:i});const n=this.$c(t);null!==n&&(n.Dt.Hh(i),this.Tc.m())}$c(t){for(const i of this.kc){const n=i.b_(t);if(null!==n)return{Ht:i,Dt:n}}return null}St(){return this.kl}Uc(){return this.kc}qc(){return this.Bc}Yc(){return this.vt}Zc(){return this.Pc}Xc(t,i){t.Eo(i),this.Fu()}x_(t){this.o_=t,this.kl.x_(this.o_),this.kc.forEach((i=>i.x_(t))),this.Fu()}Ac(t){const i=new pn(this.kl,this);void 0!==t?this.kc.splice(t,0,i):this.kc.push(i);const n=void 0===t?this.kc.length-1:t,s=lt.es();return s.Nn(n,{Fn:0,Wn:!0}),this.Lc(s),i}D_(t,i,n){t.D_(i,n)}O_(t,i,n){t.O_(i,n),this.Gl(),this.Lc(this.Kc(t,2))}V_(t,i){t.V_(i),this.Lc(this.Kc(t,2))}B_(t,i,n){i.Do()||t.B_(i,n)}A_(t,i,n){i.Do()||(t.A_(i,n),this.Gl(),this.Lc(this.Kc(t,2)))}z_(t,i){i.Do()||(t.z_(i),this.Lc(this.Kc(t,2)))}I_(t,i){t.I_(i),this.Lc(this.Kc(t,2))}Gc(t){this.kl.Ko(t)}Jc(t,i){const n=this.St();if(n.Ni()||0===i)return;const s=n.Hi();t=Math.max(1,Math.min(t,s)),n.Yu(t,i),this.Fu()}Qc(t){this.td(0),this.nd(t),this.sd()}ed(t){this.kl.Go(t),this.Fu()}rd(){this.kl.Jo(),this.$h()}td(t){this.kl.Qo(t)}nd(t){this.kl.t_(t),this.Fu()}sd(){this.kl.i_(),this.$h()}wt(){return this.yc}hd(t,i,n,s,e){this.vt.gn(t,i);let r=NaN,h=this.kl.Lu(t);const l=this.kl.Zs();null!==l&&(h=Math.min(Math.max(l.Os(),h),l.ui()));const a=s.vn(),o=a.Ct();null!==o&&(r=a.pn(i,o)),r=this.Vc.Oa(r,h,s),this.vt.kn(h,r,s),this.aa(),e||this.Pc.m(this.vt.xt(),{x:t,y:i},n)}ld(t,i,n){const s=n.vn(),e=s.Ct(),r=s.Rt(t,f(e)),h=this.kl.Da(i,!0),l=this.kl.zt(f(h));this.hd(l,r,null,n,!0)}ad(t){this.Yc().Cn(),this.aa(),t||this.Pc.m(null,null,null)}Gl(){const t=this.vt.Ht();if(null!==t){const i=this.vt.xn(),n=this.vt.Sn();this.hd(i,n,null,t)}this.vt.On()}od(t,i,n){const s=this.kl.mn(0);void 0!==i&&void 0!==n&&this.kl.bt(i,n);const e=this.kl.mn(0),r=this.kl.Iu(),h=this.kl.Zs();if(null!==h&&null!==s&&null!==e){const i=h.Xr(r),l=this.U_.key(s)>this.U_.key(e),a=null!==t&&t>r&&!l,o=this.kl.W().allowShiftVisibleRangeOnWhitespaceReplacement,_=i&&(!(void 0===n)||o)&&this.kl.W().shiftVisibleRangeOnNewBar;if(a&&!_){const i=t-r;this.kl.Jn(this.kl.ju()-i)}}this.kl.qu(t)}ta(t){null!==t&&t.N_()}cr(t){const i=this.kc.find((i=>i.$o().includes(t)));return void 0===i?null:i}Fu(){this.Bc.On(),this.kc.forEach((t=>t.N_())),this.Gl()}S(){this.kc.forEach((t=>t.S())),this.kc.length=0,this.cn.localization.priceFormatter=void 0,this.cn.localization.percentageFormatter=void 0,this.cn.localization.timeFormatter=void 0}_d(){return this.Oc}mr(){return this.Oc.W()}w_(){return this.Tc}ud(t,i,n){const s=this.kc[0],e=this.dd(i,t,s,n);return this.yc.push(e),1===this.yc.length?this.Xl():this.$h(),e}fd(t){const i=this.cr(t),n=this.yc.indexOf(t);c(-1!==n,"Series not found"),this.yc.splice(n,1),f(i).Yo(t),t.S&&t.S()}Zl(t,i){const n=f(this.cr(t));n.Yo(t);const s=this.$c(i);if(null===s){const s=t.Xi();n.Uo(t,i,s)}else{const e=s.Ht===n?t.Xi():void 0;s.Ht.Uo(t,i,e)}}rc(){const t=lt.ss();t.$n(),this.Lc(t)}vd(t){const i=lt.ss();i.Yn(t),this.Lc(i)}Kn(){const t=lt.ss();t.Kn(),this.Lc(t)}Gn(t){const i=lt.ss();i.Gn(t),this.Lc(i)}Jn(t){const i=lt.ss();i.Jn(t),this.Lc(i)}Zn(t){const i=lt.ss();i.Zn(t),this.Lc(i)}Un(){const t=lt.ss();t.Un(),this.Lc(t)}pd(){return this.cn.rightPriceScale.visible?"right":"left"}md(){return this.Ic}q(){return this.zc}Bt(t){const i=this.Ic,n=this.zc;if(i===n)return i;if(t=Math.max(0,Math.min(100,Math.round(100*t))),null===this.Rc||this.Rc.Ts!==n||this.Rc.Ps!==i)this.Rc={Ts:n,Ps:i,bd:new Map};else{const i=this.Rc.bd.get(t);if(void 0!==i)return i}const s=function(t,i,n){const[s,e,r,h]=S(t),[l,a,o,_]=S(i),u=[m(s+n*(l-s)),m(e+n*(a-e)),m(r+n*(o-r)),b(h+n*(_-h))];return`rgba(${u[0]}, ${u[1]}, ${u[2]}, ${u[3]})`}(n,i,t/100);return this.Rc.bd.set(t,s),s}Kc(t,i){const n=new lt(i);if(null!==t){const s=this.kc.indexOf(t);n.Nn(s,{Fn:i})}return n}Nc(t,i){return void 0===i&&(i=2),this.Kc(this.cr(t),i)}Lc(t){this.Dc&&this.Dc(t),this.kc.forEach((t=>t.W_().Uh().bt()))}dd(t,i,n,s){const e=new Yi(this,t,i,n,s),r=void 0!==t.priceScaleId?t.priceScaleId:this.pd();return n.Uo(e,r),ht(r)||e.Hh(t),e}Ec(t){const i=this.cn.layout;return"gradient"===i.background.type?0===t?i.background.topColor:i.background.bottomColor:i.background.color}}function An(t){return!P(t)&&!D(t)}function zn(t){return P(t)}!function(t){t[t.Disabled=0]="Disabled",t[t.Continuous=1]="Continuous",t[t.OnDataUpdate=2]="OnDataUpdate"}(Rn||(Rn={})),function(t){t[t.LastBar=0]="LastBar",t[t.LastVisible=1]="LastVisible"}(Dn||(Dn={})),function(t){t.Solid="solid",t.VerticalGradient="gradient"}(On||(On={})),function(t){t[t.Year=0]="Year",t[t.Month=1]="Month",t[t.DayOfMonth=2]="DayOfMonth",t[t.Time=3]="Time",t[t.TimeWithSeconds=4]="TimeWithSeconds"}(Vn||(Vn={}));const En=t=>t.getUTCFullYear();function In(t,i,n){return i.replace(/yyyy/g,(t=>ot(En(t),4))(t)).replace(/yy/g,(t=>ot(En(t)%100,2))(t)).replace(/MMMM/g,((t,i)=>new Date(t.getUTCFullYear(),t.getUTCMonth(),1).toLocaleString(i,{month:"long"}))(t,n)).replace(/MMM/g,((t,i)=>new Date(t.getUTCFullYear(),t.getUTCMonth(),1).toLocaleString(i,{month:"short"}))(t,n)).replace(/MM/g,(t=>ot((t=>t.getUTCMonth()+1)(t),2))(t)).replace(/dd/g,(t=>ot((t=>t.getUTCDate())(t),2))(t))}class Ln{constructor(t="yyyy-MM-dd",i="default"){this.wd=t,this.gd=i}q_(t){return In(t,this.wd,this.gd)}}class Nn{constructor(t){this.Md=t||"%h:%m:%s"}q_(t){return this.Md.replace("%h",ot(t.getUTCHours(),2)).replace("%m",ot(t.getUTCMinutes(),2)).replace("%s",ot(t.getUTCSeconds(),2))}}const Fn={xd:"yyyy-MM-dd",Sd:"%h:%m:%s",kd:" ",yd:"default"};class Wn{constructor(t={}){const i=Object.assign(Object.assign({},Fn),t);this.Cd=new Ln(i.xd,i.yd),this.Td=new Nn(i.Sd),this.Pd=i.kd}q_(t){return`${this.Cd.q_(t)}${this.Pd}${this.Td.q_(t)}`}}function jn(t){return 60*t*60*1e3}function Hn(t){return 60*t*1e3}const $n=[{Rd:(Un=1,1e3*Un),Dd:10},{Rd:Hn(1),Dd:20},{Rd:Hn(5),Dd:21},{Rd:Hn(30),Dd:22},{Rd:jn(1),Dd:30},{Rd:jn(3),Dd:31},{Rd:jn(6),Dd:32},{Rd:jn(12),Dd:33}];var Un;function qn(t,i){if(t.getUTCFullYear()!==i.getUTCFullYear())return 70;if(t.getUTCMonth()!==i.getUTCMonth())return 60;if(t.getUTCDate()!==i.getUTCDate())return 50;for(let n=$n.length-1;n>=0;--n)if(Math.floor(i.getTime()/$n[n].Rd)!==Math.floor(t.getTime()/$n[n].Rd))return $n[n].Dd;return 0}function Yn(t){let i=t;if(D(t)&&(i=Xn(t)),!An(i))throw new Error("time must be of type BusinessDay");const n=new Date(Date.UTC(i.year,i.month-1,i.day,0,0,0,0));return{Od:Math.round(n.getTime()/1e3),Vd:i}}function Zn(t){if(!zn(t))throw new Error("time must be of type isUTCTimestamp");return{Od:t}}function Xn(t){const i=new Date(t);if(isNaN(i.getTime()))throw new Error(`Invalid date string=${t}, expected format=yyyy-mm-dd`);return{day:i.getUTCDate(),month:i.getUTCMonth()+1,year:i.getUTCFullYear()}}function Kn(t){D(t.time)&&(t.time=Xn(t.time))}class Gn{options(){return this.cn}setOptions(t){this.cn=t,this.updateFormatter(t.localization)}preprocessData(t){Array.isArray(t)?function(t){t.forEach(Kn)}(t):Kn(t)}createConverterToInternalObj(t){return f(function(t){return 0===t.length?null:An(t[0].time)||D(t[0].time)?Yn:Zn}(t))}key(t){return"object"==typeof t&&"Od"in t?t.Od:this.key(this.convertHorzItemToInternal(t))}cacheKey(t){const i=t;return void 0===i.Vd?new Date(1e3*i.Od).getTime():new Date(Date.UTC(i.Vd.year,i.Vd.month-1,i.Vd.day)).getTime()}convertHorzItemToInternal(t){return zn(i=t)?Zn(i):An(i)?Yn(i):Yn(Xn(i));var i}updateFormatter(t){if(!this.cn)return;const i=t.dateFormat;this.cn.timeScale.timeVisible?this.Bd=new Wn({xd:i,Sd:this.cn.timeScale.secondsVisible?"%h:%m:%s":"%h:%m",kd:" ",yd:t.locale}):this.Bd=new Ln(i,t.locale)}formatHorzItem(t){const i=t;return this.Bd.q_(new Date(1e3*i.Od))}formatTickmark(t,i){const n=function(t,i,n){switch(t){case 0:case 10:return i?n?4:3:2;case 20:case 21:case 22:case 30:case 31:case 32:case 33:return i?3:2;case 50:return 2;case 60:return 1;case 70:return 0}}(t.weight,this.cn.timeScale.timeVisible,this.cn.timeScale.secondsVisible),s=this.cn.timeScale;if(void 0!==s.tickMarkFormatter){const e=s.tickMarkFormatter(t.originalTime,n,i.locale);if(null!==e)return e}return function(t,i,n){const s={};switch(i){case 0:s.year="numeric";break;case 1:s.month="short";break;case 2:s.day="numeric";break;case 3:s.hour12=!1,s.hour="2-digit",s.minute="2-digit";break;case 4:s.hour12=!1,s.hour="2-digit",s.minute="2-digit",s.second="2-digit"}const e=void 0===t.Vd?new Date(1e3*t.Od):new Date(Date.UTC(t.Vd.year,t.Vd.month-1,t.Vd.day));return new Date(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds()).toLocaleString(n,s)}(t.time,n,i.locale)}maxTickMarkWeight(t){let i=t.reduce(xn,t[0]).weight;return i>30&&i<50&&(i=30),i}fillWeightsForPoints(t,i){!function(t,i=0){if(0===t.length)return;let n=0===i?null:t[i-1].time.Od,s=null!==n?new Date(1e3*n):null,e=0;for(let r=i;r1){const i=Math.ceil(e/(t.length-1)),n=new Date(1e3*(t[0].time.Od-i));t[0].timeWeight=qn(new Date(1e3*t[0].time.Od),n)}}(t,i)}static Ad(t){return T({localization:{dateFormat:"dd MMM 'yy"}},null!=t?t:{})}}function Jn(t){var i=t.width,n=t.height;if(i<0)throw new Error("Negative width is not allowed for Size");if(n<0)throw new Error("Negative height is not allowed for Size");return{width:i,height:n}}function Qn(t,i){return t.width===i.width&&t.height===i.height}var ts=function(){function t(t){var i=this;this._resolutionListener=function(){return i._onResolutionChanged()},this._resolutionMediaQueryList=null,this._observers=[],this._window=t,this._installResolutionListener()}return t.prototype.dispose=function(){this._uninstallResolutionListener(),this._window=null},Object.defineProperty(t.prototype,"value",{get:function(){return this._window.devicePixelRatio},enumerable:!1,configurable:!0}),t.prototype.subscribe=function(t){var i=this,n={next:t};return this._observers.push(n),{unsubscribe:function(){i._observers=i._observers.filter((function(t){return t!==n}))}}},t.prototype._installResolutionListener=function(){if(null!==this._resolutionMediaQueryList)throw new Error("Resolution listener is already installed");var t=this._window.devicePixelRatio;this._resolutionMediaQueryList=this._window.matchMedia("all and (resolution: ".concat(t,"dppx)")),this._resolutionMediaQueryList.addListener(this._resolutionListener)},t.prototype._uninstallResolutionListener=function(){null!==this._resolutionMediaQueryList&&(this._resolutionMediaQueryList.removeListener(this._resolutionListener),this._resolutionMediaQueryList=null)},t.prototype._reinstallResolutionListener=function(){this._uninstallResolutionListener(),this._installResolutionListener()},t.prototype._onResolutionChanged=function(){var t=this;this._observers.forEach((function(i){return i.next(t._window.devicePixelRatio)})),this._reinstallResolutionListener()},t}();var is=function(){function t(t,i,n){var s;this._canvasElement=null,this._bitmapSizeChangedListeners=[],this._suggestedBitmapSize=null,this._suggestedBitmapSizeChangedListeners=[],this._devicePixelRatioObservable=null,this._canvasElementResizeObserver=null,this._canvasElement=t,this._canvasElementClientSize=Jn({width:this._canvasElement.clientWidth,height:this._canvasElement.clientHeight}),this._transformBitmapSize=null!=i?i:function(t){return t},this._allowResizeObserver=null===(s=null==n?void 0:n.allowResizeObserver)||void 0===s||s,this._chooseAndInitObserver()}return t.prototype.dispose=function(){var t,i;if(null===this._canvasElement)throw new Error("Object is disposed");null===(t=this._canvasElementResizeObserver)||void 0===t||t.disconnect(),this._canvasElementResizeObserver=null,null===(i=this._devicePixelRatioObservable)||void 0===i||i.dispose(),this._devicePixelRatioObservable=null,this._suggestedBitmapSizeChangedListeners.length=0,this._bitmapSizeChangedListeners.length=0,this._canvasElement=null},Object.defineProperty(t.prototype,"canvasElement",{get:function(){if(null===this._canvasElement)throw new Error("Object is disposed");return this._canvasElement},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"canvasElementClientSize",{get:function(){return this._canvasElementClientSize},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"bitmapSize",{get:function(){return Jn({width:this.canvasElement.width,height:this.canvasElement.height})},enumerable:!1,configurable:!0}),t.prototype.resizeCanvasElement=function(t){this._canvasElementClientSize=Jn(t),this.canvasElement.style.width="".concat(this._canvasElementClientSize.width,"px"),this.canvasElement.style.height="".concat(this._canvasElementClientSize.height,"px"),this._invalidateBitmapSize()},t.prototype.subscribeBitmapSizeChanged=function(t){this._bitmapSizeChangedListeners.push(t)},t.prototype.unsubscribeBitmapSizeChanged=function(t){this._bitmapSizeChangedListeners=this._bitmapSizeChangedListeners.filter((function(i){return i!==t}))},Object.defineProperty(t.prototype,"suggestedBitmapSize",{get:function(){return this._suggestedBitmapSize},enumerable:!1,configurable:!0}),t.prototype.subscribeSuggestedBitmapSizeChanged=function(t){this._suggestedBitmapSizeChangedListeners.push(t)},t.prototype.unsubscribeSuggestedBitmapSizeChanged=function(t){this._suggestedBitmapSizeChangedListeners=this._suggestedBitmapSizeChangedListeners.filter((function(i){return i!==t}))},t.prototype.applySuggestedBitmapSize=function(){if(null!==this._suggestedBitmapSize){var t=this._suggestedBitmapSize;this._suggestedBitmapSize=null,this._resizeBitmap(t),this._emitSuggestedBitmapSizeChanged(t,this._suggestedBitmapSize)}},t.prototype._resizeBitmap=function(t){var i=this.bitmapSize;Qn(i,t)||(this.canvasElement.width=t.width,this.canvasElement.height=t.height,this._emitBitmapSizeChanged(i,t))},t.prototype._emitBitmapSizeChanged=function(t,i){var n=this;this._bitmapSizeChangedListeners.forEach((function(s){return s.call(n,t,i)}))},t.prototype._suggestNewBitmapSize=function(t){var i=this._suggestedBitmapSize,n=Jn(this._transformBitmapSize(t,this._canvasElementClientSize)),s=Qn(this.bitmapSize,n)?null:n;null===i&&null===s||null!==i&&null!==s&&Qn(i,s)||(this._suggestedBitmapSize=s,this._emitSuggestedBitmapSizeChanged(i,s))},t.prototype._emitSuggestedBitmapSizeChanged=function(t,i){var n=this;this._suggestedBitmapSizeChangedListeners.forEach((function(s){return s.call(n,t,i)}))},t.prototype._chooseAndInitObserver=function(){var t=this;this._allowResizeObserver?new Promise((function(t){var i=new ResizeObserver((function(n){t(n.every((function(t){return"devicePixelContentBoxSize"in t}))),i.disconnect()}));i.observe(document.body,{box:"device-pixel-content-box"})})).catch((function(){return!1})).then((function(i){return i?t._initResizeObserver():t._initDevicePixelRatioObservable()})):this._initDevicePixelRatioObservable()},t.prototype._initDevicePixelRatioObservable=function(){var t=this;if(null!==this._canvasElement){var i=ns(this._canvasElement);if(null===i)throw new Error("No window is associated with the canvas");this._devicePixelRatioObservable=function(t){return new ts(t)}(i),this._devicePixelRatioObservable.subscribe((function(){return t._invalidateBitmapSize()})),this._invalidateBitmapSize()}},t.prototype._invalidateBitmapSize=function(){var t,i;if(null!==this._canvasElement){var n=ns(this._canvasElement);if(null!==n){var s=null!==(i=null===(t=this._devicePixelRatioObservable)||void 0===t?void 0:t.value)&&void 0!==i?i:n.devicePixelRatio,e=this._canvasElement.getClientRects(),r=void 0!==e[0]?function(t,i){return Jn({width:Math.round(t.left*i+t.width*i)-Math.round(t.left*i),height:Math.round(t.top*i+t.height*i)-Math.round(t.top*i)})}(e[0],s):Jn({width:this._canvasElementClientSize.width*s,height:this._canvasElementClientSize.height*s});this._suggestNewBitmapSize(r)}}},t.prototype._initResizeObserver=function(){var t=this;null!==this._canvasElement&&(this._canvasElementResizeObserver=new ResizeObserver((function(i){var n=i.find((function(i){return i.target===t._canvasElement}));if(n&&n.devicePixelContentBoxSize&&n.devicePixelContentBoxSize[0]){var s=n.devicePixelContentBoxSize[0],e=Jn({width:s.inlineSize,height:s.blockSize});t._suggestNewBitmapSize(e)}})),this._canvasElementResizeObserver.observe(this._canvasElement,{box:"device-pixel-content-box"}))},t}();function ns(t){return t.ownerDocument.defaultView}var ss=function(){function t(t,i,n){if(0===i.width||0===i.height)throw new TypeError("Rendering target could only be created on a media with positive width and height");if(this._mediaSize=i,0===n.width||0===n.height)throw new TypeError("Rendering target could only be created using a bitmap with positive integer width and height");this._bitmapSize=n,this._context=t}return t.prototype.useMediaCoordinateSpace=function(t){try{return this._context.save(),this._context.setTransform(1,0,0,1,0,0),this._context.scale(this._horizontalPixelRatio,this._verticalPixelRatio),t({context:this._context,mediaSize:this._mediaSize})}finally{this._context.restore()}},t.prototype.useBitmapCoordinateSpace=function(t){try{return this._context.save(),this._context.setTransform(1,0,0,1,0,0),t({context:this._context,mediaSize:this._mediaSize,bitmapSize:this._bitmapSize,horizontalPixelRatio:this._horizontalPixelRatio,verticalPixelRatio:this._verticalPixelRatio})}finally{this._context.restore()}},Object.defineProperty(t.prototype,"_horizontalPixelRatio",{get:function(){return this._bitmapSize.width/this._mediaSize.width},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"_verticalPixelRatio",{get:function(){return this._bitmapSize.height/this._mediaSize.height},enumerable:!1,configurable:!0}),t}();function es(t,i){var n=t.canvasElementClientSize;if(0===n.width||0===n.height)return null;var s=t.bitmapSize;if(0===s.width||0===s.height)return null;var e=t.canvasElement.getContext("2d",i);return null===e?null:new ss(e,n,s)}const rs="undefined"!=typeof window;function hs(){return!!rs&&window.navigator.userAgent.toLowerCase().indexOf("firefox")>-1}function ls(){return!!rs&&/iPhone|iPad|iPod/.test(window.navigator.platform)}function as(t){return t+t%2}function os(t,i){return t.zd-i.zd}function _s(t,i,n){const s=(t.zd-i.zd)/(t.ot-i.ot);return Math.sign(s)*Math.min(Math.abs(s),n)}class us{constructor(t,i,n,s){this.Ed=null,this.Id=null,this.Ld=null,this.Nd=null,this.Fd=null,this.Wd=0,this.jd=0,this.Hd=t,this.$d=i,this.Ud=n,this.rs=s}qd(t,i){if(null!==this.Ed){if(this.Ed.ot===i)return void(this.Ed.zd=t);if(Math.abs(this.Ed.zd-t)50)return;let n=0;const s=_s(this.Ed,this.Id,this.$d),e=os(this.Ed,this.Id),r=[s],h=[e];if(n+=e,null!==this.Ld){const t=_s(this.Id,this.Ld,this.$d);if(Math.sign(t)===Math.sign(s)){const i=os(this.Id,this.Ld);if(r.push(t),h.push(i),n+=i,null!==this.Nd){const t=_s(this.Ld,this.Nd,this.$d);if(Math.sign(t)===Math.sign(s)){const i=os(this.Ld,this.Nd);r.push(t),h.push(i),n+=i}}}}let l=0;for(let t=0;t160?"dark":"light"}nf(){return this.Jd.W().layout.attributionLogo}ef(){const t=new URL(location.href);return t.hostname?"&utm_source="+t.hostname+t.pathname:""}Qd(){this.if()&&(this.tf(),this.en=this.nf(),this.en&&(this.Kd=this.sf(),this.Xd=document.createElement("style"),this.Xd.innerText="a#tv-attr-logo{--fill:#131722;--stroke:#fff;position:absolute;left:10px;bottom:10px;height:19px;width:35px;margin:0;padding:0;border:0;z-index:3;}a#tv-attr-logo[data-dark]{--fill:#D1D4DC;--stroke:#131722;}",this.Zd=document.createElement("a"),this.Zd.href=`https://www.tradingview.com/?utm_medium=lwc-link&utm_campaign=lwc-chart${this.ef()}`,this.Zd.title="Charting by TradingView",this.Zd.id="tv-attr-logo",this.Zd.target="_blank",this.Zd.innerHTML=' ',this.Zd.toggleAttribute("data-dark","dark"===this.Kd),this.Gd.appendChild(this.Xd),this.Gd.appendChild(this.Zd)))}}function ds(t,i){const n=f(t.ownerDocument).createElement("canvas");t.appendChild(n);const s=function(t,i){if("device-pixel-content-box"===i.type)return new is(t,i.transform,i.options);throw new Error("Unsupported binding target")}(n,{type:"device-pixel-content-box",options:{allowResizeObserver:!1},transform:(t,i)=>({width:Math.max(t.width,i.width),height:Math.max(t.height,i.height)})});return s.resizeCanvasElement(i),s}function fs(t){var i;t.width=1,t.height=1,null===(i=t.getContext("2d"))||void 0===i||i.clearRect(0,0,1,1)}function vs(t,i,n,s){t.wl&&t.wl(i,n,s)}function ps(t,i,n,s){t.X(i,n,s)}function ms(t,i,n,s){const e=t(n,s);for(const t of e){const n=t.gt();null!==n&&i(n)}}function bs(t){rs&&void 0!==window.chrome&&t.addEventListener("mousedown",(t=>{if(1===t.button)return t.preventDefault(),!1}))}class ws{constructor(t,i,n){this.rf=0,this.hf=null,this.lf={nt:Number.NEGATIVE_INFINITY,st:Number.POSITIVE_INFINITY},this.af=0,this._f=null,this.uf={nt:Number.NEGATIVE_INFINITY,st:Number.POSITIVE_INFINITY},this.cf=null,this.df=!1,this.ff=null,this.vf=null,this.pf=!1,this.mf=!1,this.bf=!1,this.wf=null,this.gf=null,this.Mf=null,this.xf=null,this.Sf=null,this.kf=null,this.yf=null,this.Cf=0,this.Tf=!1,this.Pf=!1,this.Rf=!1,this.Df=0,this.Of=null,this.Vf=!ls(),this.Bf=t=>{this.Af(t)},this.zf=t=>{if(this.Ef(t)){const i=this.If(t);if(++this.af,this._f&&this.af>1){const{Lf:n}=this.Nf(xs(t),this.uf);n<30&&!this.bf&&this.Ff(i,this.jf.Wf),this.Hf()}}else{const i=this.If(t);if(++this.rf,this.hf&&this.rf>1){const{Lf:n}=this.Nf(xs(t),this.lf);n<5&&!this.mf&&this.$f(i,this.jf.Uf),this.qf()}}},this.Yf=t,this.jf=i,this.cn=n,this.Zf()}S(){null!==this.wf&&(this.wf(),this.wf=null),null!==this.gf&&(this.gf(),this.gf=null),null!==this.xf&&(this.xf(),this.xf=null),null!==this.Sf&&(this.Sf(),this.Sf=null),null!==this.kf&&(this.kf(),this.kf=null),null!==this.Mf&&(this.Mf(),this.Mf=null),this.Xf(),this.qf()}Kf(t){this.xf&&this.xf();const i=this.Gf.bind(this);if(this.xf=()=>{this.Yf.removeEventListener("mousemove",i)},this.Yf.addEventListener("mousemove",i),this.Ef(t))return;const n=this.If(t);this.$f(n,this.jf.Jf),this.Vf=!0}qf(){null!==this.hf&&clearTimeout(this.hf),this.rf=0,this.hf=null,this.lf={nt:Number.NEGATIVE_INFINITY,st:Number.POSITIVE_INFINITY}}Hf(){null!==this._f&&clearTimeout(this._f),this.af=0,this._f=null,this.uf={nt:Number.NEGATIVE_INFINITY,st:Number.POSITIVE_INFINITY}}Gf(t){if(this.Rf||null!==this.vf)return;if(this.Ef(t))return;const i=this.If(t);this.$f(i,this.jf.Qf),this.Vf=!0}tv(t){const i=ks(t.changedTouches,f(this.Of));if(null===i)return;if(this.Df=Ss(t),null!==this.yf)return;if(this.Pf)return;this.Tf=!0;const n=this.Nf(xs(i),f(this.vf)),{iv:s,nv:e,Lf:r}=n;if(this.pf||!(r<5)){if(!this.pf){const t=.5*s,i=e>=t&&!this.cn.sv(),n=t>e&&!this.cn.ev();i||n||(this.Pf=!0),this.pf=!0,this.bf=!0,this.Xf(),this.Hf()}if(!this.Pf){const n=this.If(t,i);this.Ff(n,this.jf.rv),Ms(t)}}}hv(t){if(0!==t.button)return;const i=this.Nf(xs(t),f(this.ff)),{Lf:n}=i;if(n>=5&&(this.mf=!0,this.qf()),this.mf){const i=this.If(t);this.$f(i,this.jf.lv)}}Nf(t,i){const n=Math.abs(i.nt-t.nt),s=Math.abs(i.st-t.st);return{iv:n,nv:s,Lf:n+s}}av(t){let i=ks(t.changedTouches,f(this.Of));if(null===i&&0===t.touches.length&&(i=t.changedTouches[0]),null===i)return;this.Of=null,this.Df=Ss(t),this.Xf(),this.vf=null,this.kf&&(this.kf(),this.kf=null);const n=this.If(t,i);if(this.Ff(n,this.jf.ov),++this.af,this._f&&this.af>1){const{Lf:t}=this.Nf(xs(i),this.uf);t<30&&!this.bf&&this.Ff(n,this.jf.Wf),this.Hf()}else this.bf||(this.Ff(n,this.jf._v),this.jf._v&&Ms(t));0===this.af&&Ms(t),0===t.touches.length&&this.df&&(this.df=!1,Ms(t))}Af(t){if(0!==t.button)return;const i=this.If(t);if(this.ff=null,this.Rf=!1,this.Sf&&(this.Sf(),this.Sf=null),hs()){this.Yf.ownerDocument.documentElement.removeEventListener("mouseleave",this.Bf)}if(!this.Ef(t))if(this.$f(i,this.jf.uv),++this.rf,this.hf&&this.rf>1){const{Lf:n}=this.Nf(xs(t),this.lf);n<5&&!this.mf&&this.$f(i,this.jf.Uf),this.qf()}else this.mf||this.$f(i,this.jf.cv)}Xf(){null!==this.cf&&(clearTimeout(this.cf),this.cf=null)}dv(t){if(null!==this.Of)return;const i=t.changedTouches[0];this.Of=i.identifier,this.Df=Ss(t);const n=this.Yf.ownerDocument.documentElement;this.bf=!1,this.pf=!1,this.Pf=!1,this.vf=xs(i),this.kf&&(this.kf(),this.kf=null);{const i=this.tv.bind(this),s=this.av.bind(this);this.kf=()=>{n.removeEventListener("touchmove",i),n.removeEventListener("touchend",s)},n.addEventListener("touchmove",i,{passive:!1}),n.addEventListener("touchend",s,{passive:!1}),this.Xf(),this.cf=setTimeout(this.fv.bind(this,t),240)}const s=this.If(t,i);this.Ff(s,this.jf.vv),this._f||(this.af=0,this._f=setTimeout(this.Hf.bind(this),500),this.uf=xs(i))}pv(t){if(0!==t.button)return;const i=this.Yf.ownerDocument.documentElement;hs()&&i.addEventListener("mouseleave",this.Bf),this.mf=!1,this.ff=xs(t),this.Sf&&(this.Sf(),this.Sf=null);{const t=this.hv.bind(this),n=this.Af.bind(this);this.Sf=()=>{i.removeEventListener("mousemove",t),i.removeEventListener("mouseup",n)},i.addEventListener("mousemove",t),i.addEventListener("mouseup",n)}if(this.Rf=!0,this.Ef(t))return;const n=this.If(t);this.$f(n,this.jf.mv),this.hf||(this.rf=0,this.hf=setTimeout(this.qf.bind(this),500),this.lf=xs(t))}Zf(){this.Yf.addEventListener("mouseenter",this.Kf.bind(this)),this.Yf.addEventListener("touchcancel",this.Xf.bind(this));{const t=this.Yf.ownerDocument,i=t=>{this.jf.bv&&(t.composed&&this.Yf.contains(t.composedPath()[0])||t.target&&this.Yf.contains(t.target)||this.jf.bv())};this.gf=()=>{t.removeEventListener("touchstart",i)},this.wf=()=>{t.removeEventListener("mousedown",i)},t.addEventListener("mousedown",i),t.addEventListener("touchstart",i,{passive:!0})}ls()&&(this.Mf=()=>{this.Yf.removeEventListener("dblclick",this.zf)},this.Yf.addEventListener("dblclick",this.zf)),this.Yf.addEventListener("mouseleave",this.wv.bind(this)),this.Yf.addEventListener("touchstart",this.dv.bind(this),{passive:!0}),bs(this.Yf),this.Yf.addEventListener("mousedown",this.pv.bind(this)),this.gv(),this.Yf.addEventListener("touchmove",(()=>{}),{passive:!1})}gv(){void 0===this.jf.Mv&&void 0===this.jf.xv&&void 0===this.jf.Sv||(this.Yf.addEventListener("touchstart",(t=>this.kv(t.touches)),{passive:!0}),this.Yf.addEventListener("touchmove",(t=>{if(2===t.touches.length&&null!==this.yf&&void 0!==this.jf.xv){const i=gs(t.touches[0],t.touches[1])/this.Cf;this.jf.xv(this.yf,i),Ms(t)}}),{passive:!1}),this.Yf.addEventListener("touchend",(t=>{this.kv(t.touches)})))}kv(t){1===t.length&&(this.Tf=!1),2!==t.length||this.Tf||this.df?this.yv():this.Cv(t)}Cv(t){const i=this.Yf.getBoundingClientRect()||{left:0,top:0};this.yf={nt:(t[0].clientX-i.left+(t[1].clientX-i.left))/2,st:(t[0].clientY-i.top+(t[1].clientY-i.top))/2},this.Cf=gs(t[0],t[1]),void 0!==this.jf.Mv&&this.jf.Mv(),this.Xf()}yv(){null!==this.yf&&(this.yf=null,void 0!==this.jf.Sv&&this.jf.Sv())}wv(t){if(this.xf&&this.xf(),this.Ef(t))return;if(!this.Vf)return;const i=this.If(t);this.$f(i,this.jf.Tv),this.Vf=!ls()}fv(t){const i=ks(t.touches,f(this.Of));if(null===i)return;const n=this.If(t,i);this.Ff(n,this.jf.Pv),this.bf=!0,this.df=!0}Ef(t){return t.sourceCapabilities&&void 0!==t.sourceCapabilities.firesTouchEvents?t.sourceCapabilities.firesTouchEvents:Ss(t){"touchstart"!==t.type&&Ms(t)}}}}function gs(t,i){const n=t.clientX-i.clientX,s=t.clientY-i.clientY;return Math.sqrt(n*n+s*s)}function Ms(t){t.cancelable&&t.preventDefault()}function xs(t){return{nt:t.pageX,st:t.pageY}}function Ss(t){return t.timeStamp||performance.now()}function ks(t,i){for(let n=0;n{var s,e,r,h;return(null!==(e=null===(s=n.Dt())||void 0===s?void 0:s.Ta())&&void 0!==e?e:"")!==i?[]:null!==(h=null===(r=n.ca)||void 0===r?void 0:r.call(n,t))&&void 0!==h?h:[]}}function Ps(t,i,n,s){if(!t.length)return;let e=0;const r=n/2,h=t[0].At(s,!0);let l=1===i?r-(t[0].Oi()-h/2):t[0].Oi()-h/2-r;l=Math.max(0,l);for(let r=1;ru-o:_n)&&l>0){const s=1===i?-1-r:r-n,h=Math.min(s,l);for(let n=e;n{this.Wv||this.tn.Hv().$t().$h()},this.$v=()=>{this.Wv||this.tn.Hv().$t().$h()},this.tn=t,this.cn=i,this.So=i.layout,this.Oc=n,this.Uv="left"===s,this.qv=Ts("normal",s),this.Yv=Ts("top",s),this.Zv=Ts("bottom",s),this.Xv=document.createElement("div"),this.Xv.style.height="100%",this.Xv.style.overflow="hidden",this.Xv.style.width="25px",this.Xv.style.left="0",this.Xv.style.position="relative",this.Kv=ds(this.Xv,Jn({width:16,height:16})),this.Kv.subscribeSuggestedBitmapSizeChanged(this.jv);const e=this.Kv.canvasElement;e.style.position="absolute",e.style.zIndex="1",e.style.left="0",e.style.top="0",this.Gv=ds(this.Xv,Jn({width:16,height:16})),this.Gv.subscribeSuggestedBitmapSizeChanged(this.$v);const r=this.Gv.canvasElement;r.style.position="absolute",r.style.zIndex="2",r.style.left="0",r.style.top="0";const h={mv:this.Jv.bind(this),vv:this.Jv.bind(this),lv:this.Qv.bind(this),rv:this.Qv.bind(this),bv:this.tp.bind(this),uv:this.ip.bind(this),ov:this.ip.bind(this),Uf:this.np.bind(this),Wf:this.np.bind(this),Jf:this.sp.bind(this),Tv:this.ep.bind(this)};this.rp=new ws(this.Gv.canvasElement,h,{sv:()=>!this.cn.handleScroll.vertTouchDrag,ev:()=>!0})}S(){this.rp.S(),this.Gv.unsubscribeSuggestedBitmapSizeChanged(this.$v),fs(this.Gv.canvasElement),this.Gv.dispose(),this.Kv.unsubscribeSuggestedBitmapSizeChanged(this.jv),fs(this.Kv.canvasElement),this.Kv.dispose(),null!==this.Ii&&this.Ii.Xo().p(this),this.Ii=null}hp(){return this.Xv}P(){return this.So.fontSize}lp(){const t=this.Oc.W();return this.Jr!==t.R&&(this.Nv.ir(),this.Jr=t.R),t}ap(){if(null===this.Ii)return 0;let t=0;const i=this.lp(),n=f(this.Kv.canvasElement.getContext("2d"));n.save();const s=this.Ii.ja();n.font=this.op(),s.length>0&&(t=Math.max(this.Nv.xi(n,s[0].no),this.Nv.xi(n,s[s.length-1].no)));const e=this._p();for(let i=e.length;i--;){const s=this.Nv.xi(n,e[i].Kt());s>t&&(t=s)}const r=this.Ii.Ct();if(null!==r&&null!==this.Iv){const i=this.Ii.pn(1,r),s=this.Ii.pn(this.Iv.height-2,r);t=Math.max(t,this.Nv.xi(n,this.Ii.Fi(Math.floor(Math.min(i,s))+.11111111111111,r)),this.Nv.xi(n,this.Ii.Fi(Math.ceil(Math.max(i,s))-.11111111111111,r)))}n.restore();const h=t||34;return as(Math.ceil(i.C+i.T+i.A+i.I+5+h))}up(t){null!==this.Iv&&Qn(this.Iv,t)||(this.Iv=t,this.Wv=!0,this.Kv.resizeCanvasElement(t),this.Gv.resizeCanvasElement(t),this.Wv=!1,this.Xv.style.width=`${t.width}px`,this.Xv.style.height=`${t.height}px`)}cp(){return f(this.Iv).width}Gi(t){this.Ii!==t&&(null!==this.Ii&&this.Ii.Xo().p(this),this.Ii=t,t.Xo().l(this.do.bind(this),this))}Dt(){return this.Ii}ir(){const t=this.tn.dp();this.tn.Hv().$t().I_(t,f(this.Dt()))}fp(t){if(null===this.Iv)return;if(1!==t){this.vp(),this.Kv.applySuggestedBitmapSize();const t=es(this.Kv);null!==t&&(t.useBitmapCoordinateSpace((t=>{this.pp(t),this.Ae(t)})),this.tn.mp(t,this.Zv),this.bp(t),this.tn.mp(t,this.qv),this.wp(t))}this.Gv.applySuggestedBitmapSize();const i=es(this.Gv);null!==i&&(i.useBitmapCoordinateSpace((({context:t,bitmapSize:i})=>{t.clearRect(0,0,i.width,i.height)})),this.gp(i),this.tn.mp(i,this.Yv))}Mp(){return this.Kv.bitmapSize}xp(t,i,n){const s=this.Mp();s.width>0&&s.height>0&&t.drawImage(this.Kv.canvasElement,i,n)}bt(){var t;null===(t=this.Ii)||void 0===t||t.ja()}Jv(t){if(null===this.Ii||this.Ii.Ni()||!this.cn.handleScale.axisPressedMouseMove.price)return;const i=this.tn.Hv().$t(),n=this.tn.dp();this.Lv=!0,i.D_(n,this.Ii,t.localY)}Qv(t){if(null===this.Ii||!this.cn.handleScale.axisPressedMouseMove.price)return;const i=this.tn.Hv().$t(),n=this.tn.dp(),s=this.Ii;i.O_(n,s,t.localY)}tp(){if(null===this.Ii||!this.cn.handleScale.axisPressedMouseMove.price)return;const t=this.tn.Hv().$t(),i=this.tn.dp(),n=this.Ii;this.Lv&&(this.Lv=!1,t.V_(i,n))}ip(t){if(null===this.Ii||!this.cn.handleScale.axisPressedMouseMove.price)return;const i=this.tn.Hv().$t(),n=this.tn.dp();this.Lv=!1,i.V_(n,this.Ii)}np(t){this.cn.handleScale.axisDoubleClickReset.price&&this.ir()}sp(t){if(null===this.Ii)return;!this.tn.Hv().$t().W().handleScale.axisPressedMouseMove.price||this.Ii.gh()||this.Ii.Oo()||this.Sp(1)}ep(t){this.Sp(0)}_p(){const t=[],i=null===this.Ii?void 0:this.Ii;return(n=>{for(let s=0;s{t.fillStyle=n.borderColor;const l=Math.max(1,Math.floor(h)),a=Math.floor(.5*h),o=Math.round(s.T*r);t.beginPath();for(const n of i)t.rect(Math.floor(e*r),Math.round(n.Ia*h)-a,o,l);t.fill()})),t.useMediaCoordinateSpace((({context:t})=>{var r;t.font=this.op(),t.fillStyle=null!==(r=n.textColor)&&void 0!==r?r:this.So.textColor,t.textAlign=this.Uv?"right":"left",t.textBaseline="middle";const h=this.Uv?Math.round(e-s.A):Math.round(e+s.T+s.A),l=i.map((i=>this.Nv.Mi(t,i.no)));for(let n=i.length;n--;){const s=i[n];t.fillText(s.no,h,s.Ia+l[n])}}))}vp(){if(null===this.Iv||null===this.Ii)return;const t=[],i=this.Ii.$o().slice(),n=this.tn.dp(),s=this.lp();this.Ii===n.vr()&&this.tn.dp().$o().forEach((t=>{n.dr(t)&&i.push(t)}));const e=this.Ii;i.forEach((i=>{i.Rn(n,e).forEach((i=>{i.Vi(null),i.Bi()&&t.push(i)}))})),t.forEach((t=>t.Vi(t.ki())));this.Ii.W().alignLabels&&this.kp(t,s)}kp(t,i){if(null===this.Iv)return;const n=this.Iv.height/2,s=t.filter((t=>t.ki()<=n)),e=t.filter((t=>t.ki()>n));s.sort(((t,i)=>i.ki()-t.ki())),e.sort(((t,i)=>t.ki()-i.ki()));for(const n of t){const t=Math.floor(n.At(i)/2),s=n.ki();s>-t&&sthis.Iv.height-t&&s{if(i.Ai()){i.gt(f(this.Ii)).X(t,n,this.Nv,s)}}))}gp(t){if(null===this.Iv||null===this.Ii)return;const i=this.tn.Hv().$t(),n=[],s=this.tn.dp(),e=i.Yc().Rn(s,this.Ii);e.length&&n.push(e);const r=this.lp(),h=this.Uv?"right":"left";n.forEach((i=>{i.forEach((i=>{i.gt(f(this.Ii)).X(t,r,this.Nv,h)}))}))}Sp(t){this.Xv.style.cursor=1===t?"ns-resize":"default"}do(){const t=this.ap();this.Fv{this.Wv||null===this.Lp||this.$i().$h()},this.$v=()=>{this.Wv||null===this.Lp||this.$i().$h()},this.Jd=t,this.Lp=i,this.Lp.F_().l(this.Np.bind(this),this,!0),this.Fp=document.createElement("td"),this.Fp.style.padding="0",this.Fp.style.position="relative";const n=document.createElement("div");n.style.width="100%",n.style.height="100%",n.style.position="relative",n.style.overflow="hidden",this.Wp=document.createElement("td"),this.Wp.style.padding="0",this.jp=document.createElement("td"),this.jp.style.padding="0",this.Fp.appendChild(n),this.Kv=ds(n,Jn({width:16,height:16})),this.Kv.subscribeSuggestedBitmapSizeChanged(this.jv);const s=this.Kv.canvasElement;s.style.position="absolute",s.style.zIndex="1",s.style.left="0",s.style.top="0",this.Gv=ds(n,Jn({width:16,height:16})),this.Gv.subscribeSuggestedBitmapSizeChanged(this.$v);const e=this.Gv.canvasElement;e.style.position="absolute",e.style.zIndex="2",e.style.left="0",e.style.top="0",this.Hp=document.createElement("tr"),this.Hp.appendChild(this.Wp),this.Hp.appendChild(this.Fp),this.Hp.appendChild(this.jp),this.$p(),this.rp=new ws(this.Gv.canvasElement,this,{sv:()=>null===this.Ap&&!this.Jd.W().handleScroll.vertTouchDrag,ev:()=>null===this.Ap&&!this.Jd.W().handleScroll.horzTouchDrag})}S(){null!==this.yp&&this.yp.S(),null!==this.Cp&&this.Cp.S(),this.Tp=null,this.Gv.unsubscribeSuggestedBitmapSizeChanged(this.$v),fs(this.Gv.canvasElement),this.Gv.dispose(),this.Kv.unsubscribeSuggestedBitmapSizeChanged(this.jv),fs(this.Kv.canvasElement),this.Kv.dispose(),null!==this.Lp&&this.Lp.F_().p(this),this.rp.S()}dp(){return f(this.Lp)}Up(t){var i,n;null!==this.Lp&&this.Lp.F_().p(this),this.Lp=t,null!==this.Lp&&this.Lp.F_().l(As.prototype.Np.bind(this),this,!0),this.$p(),this.Jd.qp().indexOf(this)===this.Jd.qp().length-1?(this.Tp=null!==(i=this.Tp)&&void 0!==i?i:new cs(this.Fp,this.Jd),this.Tp.bt()):(null===(n=this.Tp)||void 0===n||n.tf(),this.Tp=null)}Hv(){return this.Jd}hp(){return this.Hp}$p(){if(null!==this.Lp&&(this.Yp(),0!==this.$i().wt().length)){if(null!==this.yp){const t=this.Lp.P_();this.yp.Gi(f(t))}if(null!==this.Cp){const t=this.Lp.R_();this.Cp.Gi(f(t))}}}Zp(){null!==this.yp&&this.yp.bt(),null!==this.Cp&&this.Cp.bt()}g_(){return null!==this.Lp?this.Lp.g_():0}M_(t){this.Lp&&this.Lp.M_(t)}Jf(t){if(!this.Lp)return;this.Xp();const i=t.localX,n=t.localY;this.Kp(i,n,t)}mv(t){this.Xp(),this.Gp(),this.Kp(t.localX,t.localY,t)}Qf(t){var i;if(!this.Lp)return;this.Xp();const n=t.localX,s=t.localY;this.Kp(n,s,t);const e=this.br(n,s);this.Jd.Jp(null!==(i=null==e?void 0:e.Ev)&&void 0!==i?i:null),this.$i().Wc(e&&{jc:e.jc,Av:e.Av})}cv(t){null!==this.Lp&&(this.Xp(),this.Qp(t))}Uf(t){null!==this.Lp&&this.tm(this.Op,t)}Wf(t){this.Uf(t)}lv(t){this.Xp(),this.im(t),this.Kp(t.localX,t.localY,t)}uv(t){null!==this.Lp&&(this.Xp(),this.Bp=!1,this.nm(t))}_v(t){null!==this.Lp&&this.Qp(t)}Pv(t){if(this.Bp=!0,null===this.Ap){const i={x:t.localX,y:t.localY};this.sm(i,i,t)}}Tv(t){null!==this.Lp&&(this.Xp(),this.Lp.$t().Wc(null),this.rm())}hm(){return this.Dp}lm(){return this.Op}Mv(){this.Vp=1,this.$i().Un()}xv(t,i){if(!this.Jd.W().handleScale.pinch)return;const n=5*(i-this.Vp);this.Vp=i,this.$i().Jc(t.nt,n)}vv(t){this.Bp=!1,this.zp=null!==this.Ap,this.Gp();const i=this.$i().Yc();null!==this.Ap&&i.yt()&&(this.Ep={x:i.Yt(),y:i.Zt()},this.Ap={x:t.localX,y:t.localY})}rv(t){if(null===this.Lp)return;const i=t.localX,n=t.localY;if(null===this.Ap)this.im(t);else{this.zp=!1;const s=f(this.Ep),e=s.x+(i-this.Ap.x),r=s.y+(n-this.Ap.y);this.Kp(e,r,t)}}ov(t){0===this.Hv().W().trackingMode.exitMode&&(this.zp=!0),this.am(),this.nm(t)}br(t,i){const n=this.Lp;return null===n?null:function(t,i,n){const s=t.$o(),e=function(t,i,n){var s,e;let r,h;for(const o of t){const t=null!==(e=null===(s=o.fa)||void 0===s?void 0:s.call(o,i,n))&&void 0!==e?e:[];for(const i of t)l=i.zOrder,(!(a=null==r?void 0:r.zOrder)||"top"===l&&"top"!==a||"normal"===l&&"bottom"===a)&&(r=i,h=o)}var l,a;return r&&h?{zv:r,jc:h}:null}(s,i,n);if("top"===(null==e?void 0:e.zv.zOrder))return ys(e);for(const r of s){if(e&&e.jc===r&&"bottom"!==e.zv.zOrder&&!e.zv.isBackground)return ys(e);const s=Cs(r.Pn(t),i,n);if(null!==s)return{jc:r,Vv:s.Vv,Av:s.Av};if(e&&e.jc===r&&"bottom"!==e.zv.zOrder&&e.zv.isBackground)return ys(e)}return(null==e?void 0:e.zv)?ys(e):null}(n,t,i)}om(t,i){f("left"===i?this.yp:this.Cp).up(Jn({width:t,height:this.Iv.height}))}_m(){return this.Iv}up(t){Qn(this.Iv,t)||(this.Iv=t,this.Wv=!0,this.Kv.resizeCanvasElement(t),this.Gv.resizeCanvasElement(t),this.Wv=!1,this.Fp.style.width=t.width+"px",this.Fp.style.height=t.height+"px")}um(){const t=f(this.Lp);t.T_(t.P_()),t.T_(t.R_());for(const i of t.Va())if(t.dr(i)){const n=i.Dt();null!==n&&t.T_(n),i.On()}}Mp(){return this.Kv.bitmapSize}xp(t,i,n){const s=this.Mp();s.width>0&&s.height>0&&t.drawImage(this.Kv.canvasElement,i,n)}fp(t){if(0===t)return;if(null===this.Lp)return;if(t>1&&this.um(),null!==this.yp&&this.yp.fp(t),null!==this.Cp&&this.Cp.fp(t),1!==t){this.Kv.applySuggestedBitmapSize();const t=es(this.Kv);null!==t&&(t.useBitmapCoordinateSpace((t=>{this.pp(t)})),this.Lp&&(this.dm(t,Ds),this.fm(t),this.vm(t),this.dm(t,Os),this.dm(t,Vs)))}this.Gv.applySuggestedBitmapSize();const i=es(this.Gv);null!==i&&(i.useBitmapCoordinateSpace((({context:t,bitmapSize:i})=>{t.clearRect(0,0,i.width,i.height)})),this.pm(i),this.dm(i,Bs))}bm(){return this.yp}wm(){return this.Cp}mp(t,i){this.dm(t,i)}Np(){null!==this.Lp&&this.Lp.F_().p(this),this.Lp=null}Qp(t){this.tm(this.Dp,t)}tm(t,i){const n=i.localX,s=i.localY;t.M()&&t.m(this.$i().St().Lu(n),{x:n,y:s},i)}pp({context:t,bitmapSize:i}){const{width:n,height:s}=i,e=this.$i(),r=e.q(),h=e.md();r===h?Y(t,0,0,n,s,h):K(t,0,0,n,s,r,h)}fm(t){const i=f(this.Lp).W_().Uh().gt();null!==i&&i.X(t,!1)}vm(t){const i=this.$i().qc();this.gm(t,Os,vs,i),this.gm(t,Os,ps,i)}pm(t){this.gm(t,Os,ps,this.$i().Yc())}dm(t,i){const n=f(this.Lp).$o();for(const s of n)this.gm(t,i,vs,s);for(const s of n)this.gm(t,i,ps,s)}gm(t,i,n,s){const e=f(this.Lp),r=e.$t().Fc(),h=null!==r&&r.jc===s,l=null!==r&&h&&void 0!==r.Av?r.Av.gr:void 0;ms(i,(i=>n(i,t,h,l)),s,e)}Yp(){if(null===this.Lp)return;const t=this.Jd,i=this.Lp.P_().W().visible,n=this.Lp.R_().W().visible;i||null===this.yp||(this.Wp.removeChild(this.yp.hp()),this.yp.S(),this.yp=null),n||null===this.Cp||(this.jp.removeChild(this.Cp.hp()),this.Cp.S(),this.Cp=null);const s=t.$t()._d();i&&null===this.yp&&(this.yp=new Rs(this,t.W(),s,"left"),this.Wp.appendChild(this.yp.hp())),n&&null===this.Cp&&(this.Cp=new Rs(this,t.W(),s,"right"),this.jp.appendChild(this.Cp.hp()))}Mm(t){return t.Rv&&this.Bp||null!==this.Ap}xm(t){return Math.max(0,Math.min(t,this.Iv.width-1))}Sm(t){return Math.max(0,Math.min(t,this.Iv.height-1))}Kp(t,i,n){this.$i().hd(this.xm(t),this.Sm(i),n,f(this.Lp))}rm(){this.$i().ad()}am(){this.zp&&(this.Ap=null,this.rm())}sm(t,i,n){this.Ap=t,this.zp=!1,this.Kp(i.x,i.y,n);const s=this.$i().Yc();this.Ep={x:s.Yt(),y:s.Zt()}}$i(){return this.Jd.$t()}nm(t){if(!this.Rp)return;const i=this.$i(),n=this.dp();if(i.z_(n,n.vn()),this.Pp=null,this.Rp=!1,i.sd(),null!==this.Ip){const t=performance.now(),n=i.St();this.Ip.Dr(n.ju(),t),this.Ip.Ju(t)||i.Zn(this.Ip)}}Xp(){this.Ap=null}Gp(){if(!this.Lp)return;if(this.$i().Un(),document.activeElement!==document.body&&document.activeElement!==document.documentElement)f(document.activeElement).blur();else{const t=document.getSelection();null!==t&&t.removeAllRanges()}!this.Lp.vn().Ni()&&this.$i().St().Ni()}im(t){if(null===this.Lp)return;const i=this.$i(),n=i.St();if(n.Ni())return;const s=this.Jd.W(),e=s.handleScroll,r=s.kineticScroll;if((!e.pressedMouseMove||t.Rv)&&(!e.horzTouchDrag&&!e.vertTouchDrag||!t.Rv))return;const h=this.Lp.vn(),l=performance.now();if(null!==this.Pp||this.Mm(t)||(this.Pp={x:t.clientX,y:t.clientY,Od:l,km:t.localX,ym:t.localY}),null!==this.Pp&&!this.Rp&&(this.Pp.x!==t.clientX||this.Pp.y!==t.clientY)){if(t.Rv&&r.touch||!t.Rv&&r.mouse){const t=n.he();this.Ip=new us(.2/t,7/t,.997,15/t),this.Ip.qd(n.ju(),this.Pp.Od)}else this.Ip=null;h.Ni()||i.B_(this.Lp,h,t.localY),i.td(t.localX),this.Rp=!0}this.Rp&&(h.Ni()||i.A_(this.Lp,h,t.localY),i.nd(t.localX),null!==this.Ip&&this.Ip.qd(n.ju(),l))}}class zs{constructor(t,i,n,s,e){this.ft=!0,this.Iv=Jn({width:0,height:0}),this.jv=()=>this.fp(3),this.Uv="left"===t,this.Oc=n._d,this.cn=i,this.Cm=s,this.Tm=e,this.Xv=document.createElement("div"),this.Xv.style.width="25px",this.Xv.style.height="100%",this.Xv.style.overflow="hidden",this.Kv=ds(this.Xv,Jn({width:16,height:16})),this.Kv.subscribeSuggestedBitmapSizeChanged(this.jv)}S(){this.Kv.unsubscribeSuggestedBitmapSizeChanged(this.jv),fs(this.Kv.canvasElement),this.Kv.dispose()}hp(){return this.Xv}_m(){return this.Iv}up(t){Qn(this.Iv,t)||(this.Iv=t,this.Kv.resizeCanvasElement(t),this.Xv.style.width=`${t.width}px`,this.Xv.style.height=`${t.height}px`,this.ft=!0)}fp(t){if(t<3&&!this.ft)return;if(0===this.Iv.width||0===this.Iv.height)return;this.ft=!1,this.Kv.applySuggestedBitmapSize();const i=es(this.Kv);null!==i&&i.useBitmapCoordinateSpace((t=>{this.pp(t),this.Ae(t)}))}Mp(){return this.Kv.bitmapSize}xp(t,i,n){const s=this.Mp();s.width>0&&s.height>0&&t.drawImage(this.Kv.canvasElement,i,n)}Ae({context:t,bitmapSize:i,horizontalPixelRatio:n,verticalPixelRatio:s}){if(!this.Cm())return;t.fillStyle=this.cn.timeScale.borderColor;const e=Math.floor(this.Oc.W().C*n),r=Math.floor(this.Oc.W().C*s),h=this.Uv?i.width-e:0;t.fillRect(h,0,e,r)}pp({context:t,bitmapSize:i}){Y(t,0,0,i.width,i.height,this.Tm())}}function Es(t){return i=>{var n,s;return null!==(s=null===(n=i.da)||void 0===n?void 0:n.call(i,t))&&void 0!==s?s:[]}}const Is=Es("normal"),Ls=Es("top"),Ns=Es("bottom");class Fs{constructor(t,i){this.Pm=null,this.Rm=null,this.k=null,this.Dm=!1,this.Iv=Jn({width:0,height:0}),this.Om=new C,this.Nv=new Jt(5),this.Wv=!1,this.jv=()=>{this.Wv||this.Jd.$t().$h()},this.$v=()=>{this.Wv||this.Jd.$t().$h()},this.Jd=t,this.U_=i,this.cn=t.W().layout,this.Zd=document.createElement("tr"),this.Vm=document.createElement("td"),this.Vm.style.padding="0",this.Bm=document.createElement("td"),this.Bm.style.padding="0",this.Xv=document.createElement("td"),this.Xv.style.height="25px",this.Xv.style.padding="0",this.Am=document.createElement("div"),this.Am.style.width="100%",this.Am.style.height="100%",this.Am.style.position="relative",this.Am.style.overflow="hidden",this.Xv.appendChild(this.Am),this.Kv=ds(this.Am,Jn({width:16,height:16})),this.Kv.subscribeSuggestedBitmapSizeChanged(this.jv);const n=this.Kv.canvasElement;n.style.position="absolute",n.style.zIndex="1",n.style.left="0",n.style.top="0",this.Gv=ds(this.Am,Jn({width:16,height:16})),this.Gv.subscribeSuggestedBitmapSizeChanged(this.$v);const s=this.Gv.canvasElement;s.style.position="absolute",s.style.zIndex="2",s.style.left="0",s.style.top="0",this.Zd.appendChild(this.Vm),this.Zd.appendChild(this.Xv),this.Zd.appendChild(this.Bm),this.zm(),this.Jd.$t().w_().l(this.zm.bind(this),this),this.rp=new ws(this.Gv.canvasElement,this,{sv:()=>!0,ev:()=>!this.Jd.W().handleScroll.horzTouchDrag})}S(){this.rp.S(),null!==this.Pm&&this.Pm.S(),null!==this.Rm&&this.Rm.S(),this.Gv.unsubscribeSuggestedBitmapSizeChanged(this.$v),fs(this.Gv.canvasElement),this.Gv.dispose(),this.Kv.unsubscribeSuggestedBitmapSizeChanged(this.jv),fs(this.Kv.canvasElement),this.Kv.dispose()}hp(){return this.Zd}Em(){return this.Pm}Im(){return this.Rm}mv(t){if(this.Dm)return;this.Dm=!0;const i=this.Jd.$t();!i.St().Ni()&&this.Jd.W().handleScale.axisPressedMouseMove.time&&i.Gc(t.localX)}vv(t){this.mv(t)}bv(){const t=this.Jd.$t();!t.St().Ni()&&this.Dm&&(this.Dm=!1,this.Jd.W().handleScale.axisPressedMouseMove.time&&t.rd())}lv(t){const i=this.Jd.$t();!i.St().Ni()&&this.Jd.W().handleScale.axisPressedMouseMove.time&&i.ed(t.localX)}rv(t){this.lv(t)}uv(){this.Dm=!1;const t=this.Jd.$t();t.St().Ni()&&!this.Jd.W().handleScale.axisPressedMouseMove.time||t.rd()}ov(){this.uv()}Uf(){this.Jd.W().handleScale.axisDoubleClickReset.time&&this.Jd.$t().Kn()}Wf(){this.Uf()}Jf(){this.Jd.$t().W().handleScale.axisPressedMouseMove.time&&this.Sp(1)}Tv(){this.Sp(0)}_m(){return this.Iv}Lm(){return this.Om}Nm(t,i,n){Qn(this.Iv,t)||(this.Iv=t,this.Wv=!0,this.Kv.resizeCanvasElement(t),this.Gv.resizeCanvasElement(t),this.Wv=!1,this.Xv.style.width=`${t.width}px`,this.Xv.style.height=`${t.height}px`,this.Om.m(t)),null!==this.Pm&&this.Pm.up(Jn({width:i,height:t.height})),null!==this.Rm&&this.Rm.up(Jn({width:n,height:t.height}))}Fm(){const t=this.Wm();return Math.ceil(t.C+t.T+t.P+t.L+t.B+t.jm)}bt(){this.Jd.$t().St().ja()}Mp(){return this.Kv.bitmapSize}xp(t,i,n){const s=this.Mp();s.width>0&&s.height>0&&t.drawImage(this.Kv.canvasElement,i,n)}fp(t){if(0===t)return;if(1!==t){this.Kv.applySuggestedBitmapSize();const i=es(this.Kv);null!==i&&(i.useBitmapCoordinateSpace((t=>{this.pp(t),this.Ae(t),this.Hm(i,Ns)})),this.bp(i),this.Hm(i,Is)),null!==this.Pm&&this.Pm.fp(t),null!==this.Rm&&this.Rm.fp(t)}this.Gv.applySuggestedBitmapSize();const i=es(this.Gv);null!==i&&(i.useBitmapCoordinateSpace((({context:t,bitmapSize:i})=>{t.clearRect(0,0,i.width,i.height)})),this.$m([...this.Jd.$t().wt(),this.Jd.$t().Yc()],i),this.Hm(i,Ls))}Hm(t,i){const n=this.Jd.$t().wt();for(const s of n)ms(i,(i=>vs(i,t,!1,void 0)),s,void 0);for(const s of n)ms(i,(i=>ps(i,t,!1,void 0)),s,void 0)}pp({context:t,bitmapSize:i}){Y(t,0,0,i.width,i.height,this.Jd.$t().md())}Ae({context:t,bitmapSize:i,verticalPixelRatio:n}){if(this.Jd.W().timeScale.borderVisible){t.fillStyle=this.Um();const s=Math.max(1,Math.floor(this.Wm().C*n));t.fillRect(0,0,i.width,s)}}bp(t){const i=this.Jd.$t().St(),n=i.ja();if(!n||0===n.length)return;const s=this.U_.maxTickMarkWeight(n),e=this.Wm(),r=i.W();r.borderVisible&&r.ticksVisible&&t.useBitmapCoordinateSpace((({context:t,horizontalPixelRatio:i,verticalPixelRatio:s})=>{t.strokeStyle=this.Um(),t.fillStyle=this.Um();const r=Math.max(1,Math.floor(i)),h=Math.floor(.5*i);t.beginPath();const l=Math.round(e.T*s);for(let s=n.length;s--;){const e=Math.round(n[s].coord*i);t.rect(e-h,0,r,l)}t.fill()})),t.useMediaCoordinateSpace((({context:t})=>{const i=e.C+e.T+e.L+e.P/2;t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.$(),t.font=this.op();for(const e of n)if(e.weight=s){const n=e.needAlignCoordinate?this.qm(t,e.coord,e.label):e.coord;t.fillText(e.label,n,i)}}))}qm(t,i,n){const s=this.Nv.xi(t,n),e=s/2,r=Math.floor(i-e)+.5;return r<0?i+=Math.abs(0-r):r+s>this.Iv.width&&(i-=Math.abs(this.Iv.width-(r+s))),i}$m(t,i){const n=this.Wm();for(const s of t)for(const t of s.Qi())t.gt().X(i,n)}Um(){return this.Jd.W().timeScale.borderColor}$(){return this.cn.textColor}j(){return this.cn.fontSize}op(){return E(this.j(),this.cn.fontFamily)}Ym(){return E(this.j(),this.cn.fontFamily,"bold")}Wm(){null===this.k&&(this.k={C:1,N:NaN,L:NaN,B:NaN,ji:NaN,T:5,P:NaN,R:"",Wi:new Jt,jm:0});const t=this.k,i=this.op();if(t.R!==i){const n=this.j();t.P=n,t.R=i,t.L=3*n/12,t.B=3*n/12,t.ji=9*n/12,t.N=0,t.jm=4*n/12,t.Wi.ir()}return this.k}Sp(t){this.Xv.style.cursor=1===t?"ew-resize":"default"}zm(){const t=this.Jd.$t(),i=t.W();i.leftPriceScale.visible||null===this.Pm||(this.Vm.removeChild(this.Pm.hp()),this.Pm.S(),this.Pm=null),i.rightPriceScale.visible||null===this.Rm||(this.Bm.removeChild(this.Rm.hp()),this.Rm.S(),this.Rm=null);const n={_d:this.Jd.$t()._d()},s=()=>i.leftPriceScale.borderVisible&&t.St().W().borderVisible,e=()=>t.md();i.leftPriceScale.visible&&null===this.Pm&&(this.Pm=new zs("left",i,n,s,e),this.Vm.appendChild(this.Pm.hp())),i.rightPriceScale.visible&&null===this.Rm&&(this.Rm=new zs("right",i,n,s,e),this.Bm.appendChild(this.Rm.hp()))}}const Ws=!!rs&&!!navigator.userAgentData&&navigator.userAgentData.brands.some((t=>t.brand.includes("Chromium")))&&!!rs&&((null===(js=null===navigator||void 0===navigator?void 0:navigator.userAgentData)||void 0===js?void 0:js.platform)?"Windows"===navigator.userAgentData.platform:navigator.userAgent.toLowerCase().indexOf("win")>=0);var js;class Hs{constructor(t,i,n){var s;this.Zm=[],this.Xm=0,this.ro=0,this.o_=0,this.Km=0,this.Gm=0,this.Jm=null,this.Qm=!1,this.Dp=new C,this.Op=new C,this.Pc=new C,this.tb=null,this.ib=null,this.Gd=t,this.cn=i,this.U_=n,this.Zd=document.createElement("div"),this.Zd.classList.add("tv-lightweight-charts"),this.Zd.style.overflow="hidden",this.Zd.style.direction="ltr",this.Zd.style.width="100%",this.Zd.style.height="100%",(s=this.Zd).style.userSelect="none",s.style.webkitUserSelect="none",s.style.msUserSelect="none",s.style.MozUserSelect="none",s.style.webkitTapHighlightColor="transparent",this.nb=document.createElement("table"),this.nb.setAttribute("cellspacing","0"),this.Zd.appendChild(this.nb),this.sb=this.eb.bind(this),$s(this.cn)&&this.rb(!0),this.$i=new Bn(this.Dc.bind(this),this.cn,n),this.$t().Zc().l(this.hb.bind(this),this),this.lb=new Fs(this,this.U_),this.nb.appendChild(this.lb.hp());const e=i.autoSize&&this.ab();let r=this.cn.width,h=this.cn.height;if(e||0===r||0===h){const i=t.getBoundingClientRect();r=r||i.width,h=h||i.height}this.ob(r,h),this._b(),t.appendChild(this.Zd),this.ub(),this.$i.St().sc().l(this.$i.Xl.bind(this.$i),this),this.$i.w_().l(this.$i.Xl.bind(this.$i),this)}$t(){return this.$i}W(){return this.cn}qp(){return this.Zm}cb(){return this.lb}S(){this.rb(!1),0!==this.Xm&&window.cancelAnimationFrame(this.Xm),this.$i.Zc().p(this),this.$i.St().sc().p(this),this.$i.w_().p(this),this.$i.S();for(const t of this.Zm)this.nb.removeChild(t.hp()),t.hm().p(this),t.lm().p(this),t.S();this.Zm=[],f(this.lb).S(),null!==this.Zd.parentElement&&this.Zd.parentElement.removeChild(this.Zd),this.Pc.S(),this.Dp.S(),this.Op.S(),this.fb()}ob(t,i,n=!1){if(this.ro===i&&this.o_===t)return;const s=function(t){const i=Math.floor(t.width),n=Math.floor(t.height);return Jn({width:i-i%2,height:n-n%2})}(Jn({width:t,height:i}));this.ro=s.height,this.o_=s.width;const e=this.ro+"px",r=this.o_+"px";f(this.Zd).style.height=e,f(this.Zd).style.width=r,this.nb.style.height=e,this.nb.style.width=r,n?this.pb(lt.es(),performance.now()):this.$i.Xl()}fp(t){void 0===t&&(t=lt.es());for(let i=0;i{let s=0;for(let e=0;e{f("left"===i?this.lb.Em():this.lb.Im()).xp(f(t),n,s)};if(this.cn.timeScale.visible){const i=this.lb.Mp();if(null!==t){let e=0;this.Mb()&&(r("left",e,n),e=f(s.bm()).Mp().width),this.lb.xp(t,e,n),e+=i.width,this.xb()&&r("right",e,n)}n+=i.height}return Jn({width:i,height:n})}Tb(){let t=0,i=0,n=0;for(const s of this.Zm)this.Mb()&&(i=Math.max(i,f(s.bm()).ap(),this.cn.leftPriceScale.minimumWidth)),this.xb()&&(n=Math.max(n,f(s.wm()).ap(),this.cn.rightPriceScale.minimumWidth)),t+=s.g_();i=as(i),n=as(n);const s=this.o_,e=this.ro,r=Math.max(s-i-n,0),h=this.cn.timeScale.visible;let l=h?Math.max(this.lb.Fm(),this.cn.timeScale.minimumHeight):0;var a;l=(a=l)+a%2;const o=0+l,_=e{t.Zp()})),3===(null===(n=this.Jm)||void 0===n?void 0:n.jn())&&(this.Jm.ts(t),this.Rb(),this.Db(this.Jm),this.Ob(this.Jm,i),t=this.Jm,this.Jm=null)),this.fp(t)}Ob(t,i){for(const n of t.Qn())this.ns(n,i)}Db(t){const i=this.$i.Uc();for(let n=0;n{if(this.Qm=!1,this.Xm=0,null!==this.Jm){const i=this.Jm;this.Jm=null,this.pb(i,t);for(const n of i.Qn())if(5===n.qn&&!n.Ot.Ju(t)){this.$t().Zn(n.Ot);break}}})))}Rb(){this._b()}_b(){const t=this.$i.Uc(),i=t.length,n=this.Zm.length;for(let t=i;t{const n=i.zn().hl(t);null!==n&&e.set(i,n)}))}let r;if(null!==t){const i=null===(s=this.$i.St().Ui(t))||void 0===s?void 0:s.originalTime;void 0!==i&&(r=i)}const h=this.$t().Fc(),l=null!==h&&h.jc instanceof Yi?h.jc:void 0,a=null!==h&&void 0!==h.Av?h.Av.wr:void 0;return{zb:r,se:null!=t?t:void 0,Eb:null!=i?i:void 0,Ib:l,Lb:e,Nb:a,Fb:null!=n?n:void 0}}Vb(t,i,n){this.Dp.m((()=>this.Ab(t,i,n)))}Bb(t,i,n){this.Op.m((()=>this.Ab(t,i,n)))}hb(t,i,n){this.Pc.m((()=>this.Ab(t,i,n)))}ub(){const t=this.cn.timeScale.visible?"":"none";this.lb.hp().style.display=t}Mb(){return this.Zm[0].dp().P_().W().visible}xb(){return this.Zm[0].dp().R_().W().visible}ab(){return"ResizeObserver"in window&&(this.tb=new ResizeObserver((t=>{const i=t.find((t=>t.target===this.Gd));i&&this.ob(i.contentRect.width,i.contentRect.height)})),this.tb.observe(this.Gd,{box:"border-box"}),!0)}fb(){null!==this.tb&&this.tb.disconnect(),this.tb=null}}function $s(t){return Boolean(t.handleScroll.mouseWheel||t.handleScale.mouseWheel)}function Us(t){return function(t){return void 0!==t.open}(t)||function(t){return void 0!==t.value}(t)}function qs(t,i){var n={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&i.indexOf(s)<0&&(n[s]=t[s]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var e=0;for(s=Object.getOwnPropertySymbols(t);efunction(t,i){return i?i(t):void 0===(n=t).open&&void 0===n.value;var n}(s,h)?te({ot:i,se:n,zb:e},s):te(t(i,n,s,e,r),s)}function ne(t){return{Candlestick:ie(Gs),Bar:ie(Ks),Area:ie(Zs),Baseline:ie(Xs),Histogram:ie(Ys),Line:ie(Ys),Custom:ie(Js)}[t]}function se(t){return{se:0,jb:new Map,ha:t}}function ee(t,i){if(void 0!==t&&0!==t.length)return{Hb:i.key(t[0].ot),$b:i.key(t[t.length-1].ot)}}function re(t){let i;return t.forEach((t=>{void 0===i&&(i=t.zb)})),d(i)}class he{constructor(t){this.Ub=new Map,this.qb=new Map,this.Yb=new Map,this.Zb=[],this.U_=t}S(){this.Ub.clear(),this.qb.clear(),this.Yb.clear(),this.Zb=[]}Xb(t,i){let n=0!==this.Ub.size,s=!1;const e=this.qb.get(t);if(void 0!==e)if(1===this.qb.size)n=!1,s=!0,this.Ub.clear();else for(const i of this.Zb)i.pointData.jb.delete(t)&&(s=!0);let r=[];if(0!==i.length){const n=i.map((t=>t.time)),e=this.U_.createConverterToInternalObj(i),h=ne(t.Jh()),l=t.ya(),a=t.Ca();r=i.map(((i,r)=>{const o=e(i.time),_=this.U_.key(o);let u=this.Ub.get(_);void 0===u&&(u=se(o),this.Ub.set(_,u),s=!0);const c=h(o,u.se,i,n[r],l,a);return u.jb.set(t,c),c}))}n&&this.Kb(),this.Gb(t,r);let h=-1;if(s){const t=[];this.Ub.forEach((i=>{t.push({timeWeight:0,time:i.ha,pointData:i,originalTime:re(i.jb)})})),t.sort(((t,i)=>this.U_.key(t.time)-this.U_.key(i.time))),h=this.Jb(t)}return this.Qb(t,h,function(t,i,n){const s=ee(t,n),e=ee(i,n);if(void 0!==s&&void 0!==e)return{Ql:s.$b>=e.$b&&s.Hb>=e.Hb}}(this.qb.get(t),e,this.U_))}fd(t){return this.Xb(t,[])}tw(t,i){const n=i;!function(t){void 0===t.zb&&(t.zb=t.time)}(n),this.U_.preprocessData(i);const s=this.U_.createConverterToInternalObj([i])(i.time),e=this.Yb.get(t);if(void 0!==e&&this.U_.key(s)this.U_.key(t.time)this.U_.key(s.ot)?Qs(i)&&n.push(i):Qs(i)?n[n.length-1]=i:n.splice(-1,1),this.Yb.set(t,i.ot)}Gb(t,i){0!==i.length?(this.qb.set(t,i.filter(Qs)),this.Yb.set(t,i[i.length-1].ot)):(this.qb.delete(t),this.Yb.delete(t))}Kb(){for(const t of this.Zb)0===t.pointData.jb.size&&this.Ub.delete(this.U_.key(t.time))}Jb(t){let i=-1;for(let n=0;n{0!==i.length&&(t=Math.max(t,i[i.length-1].se))})),t}Qb(t,i,n){const s={sw:new Map,St:{Iu:this.nw()}};if(-1!==i)this.qb.forEach(((i,e)=>{s.sw.set(e,{He:i,ew:e===t?n:void 0})})),this.qb.has(t)||s.sw.set(t,{He:[],ew:n}),s.St.rw=this.Zb,s.St.hw=i;else{const i=this.qb.get(t);s.sw.set(t,{He:i||[],ew:n})}return s}}function le(t,i){t.se=i,t.jb.forEach((t=>{t.se=i}))}function ae(t){const i={value:t.Ot[3],time:t.zb};return void 0!==t.Wb&&(i.customValues=t.Wb),i}function oe(t){const i=ae(t);return void 0!==t.O&&(i.color=t.O),i}function _e(t){const i=ae(t);return void 0!==t.lt&&(i.lineColor=t.lt),void 0!==t.Ts&&(i.topColor=t.Ts),void 0!==t.Ps&&(i.bottomColor=t.Ps),i}function ue(t){const i=ae(t);return void 0!==t.Pe&&(i.topLineColor=t.Pe),void 0!==t.Re&&(i.bottomLineColor=t.Re),void 0!==t.Se&&(i.topFillColor1=t.Se),void 0!==t.ke&&(i.topFillColor2=t.ke),void 0!==t.ye&&(i.bottomFillColor1=t.ye),void 0!==t.Ce&&(i.bottomFillColor2=t.Ce),i}function ce(t){const i={open:t.Ot[0],high:t.Ot[1],low:t.Ot[2],close:t.Ot[3],time:t.zb};return void 0!==t.Wb&&(i.customValues=t.Wb),i}function de(t){const i=ce(t);return void 0!==t.O&&(i.color=t.O),i}function fe(t){const i=ce(t),{O:n,Vt:s,Zh:e}=t;return void 0!==n&&(i.color=n),void 0!==s&&(i.borderColor=s),void 0!==e&&(i.wickColor=e),i}function ve(t){return{Area:_e,Line:oe,Baseline:ue,Histogram:oe,Bar:de,Candlestick:fe,Custom:pe}[t]}function pe(t){const i=t.zb;return Object.assign(Object.assign({},t.He),{time:i})}const me={vertLine:{color:"#9598A1",width:1,style:3,visible:!0,labelVisible:!0,labelBackgroundColor:"#131722"},horzLine:{color:"#9598A1",width:1,style:3,visible:!0,labelVisible:!0,labelBackgroundColor:"#131722"},mode:1},be={vertLines:{color:"#D6DCDE",style:0,visible:!0},horzLines:{color:"#D6DCDE",style:0,visible:!0}},we={background:{type:"solid",color:"#FFFFFF"},textColor:"#191919",fontSize:12,fontFamily:z,attributionLogo:!0},ge={autoScale:!0,mode:0,invertScale:!1,alignLabels:!0,borderVisible:!0,borderColor:"#2B2B43",entireTextOnly:!1,visible:!1,ticksVisible:!1,scaleMargins:{bottom:.1,top:.2},minimumWidth:0},Me={rightOffset:0,barSpacing:6,minBarSpacing:.5,fixLeftEdge:!1,fixRightEdge:!1,lockVisibleTimeRangeOnResize:!1,rightBarStaysOnScroll:!1,borderVisible:!0,borderColor:"#2B2B43",visible:!0,timeVisible:!1,secondsVisible:!0,shiftVisibleRangeOnNewBar:!0,allowShiftVisibleRangeOnWhitespaceReplacement:!1,ticksVisible:!1,uniformDistribution:!1,minimumHeight:0,allowBoldLabels:!0},xe={color:"rgba(0, 0, 0, 0)",visible:!1,fontSize:48,fontFamily:z,fontStyle:"",text:"",horzAlign:"center",vertAlign:"center"};function Se(){return{width:0,height:0,autoSize:!1,layout:we,crosshair:me,grid:be,overlayPriceScales:Object.assign({},ge),leftPriceScale:Object.assign(Object.assign({},ge),{visible:!1}),rightPriceScale:Object.assign(Object.assign({},ge),{visible:!0}),timeScale:Me,watermark:xe,localization:{locale:rs?navigator.language:"",dateFormat:"dd MMM 'yy"},handleScroll:{mouseWheel:!0,pressedMouseMove:!0,horzTouchDrag:!0,vertTouchDrag:!0},handleScale:{axisPressedMouseMove:{time:!0,price:!0},axisDoubleClickReset:{time:!0,price:!0},mouseWheel:!0,pinch:!0},kineticScroll:{mouse:!1,touch:!0},trackingMode:{exitMode:1}}}class ke{constructor(t,i){this.lw=t,this.aw=i}applyOptions(t){this.lw.$t().Hc(this.aw,t)}options(){return this.Ii().W()}width(){return ht(this.aw)?this.lw.gb(this.aw):0}Ii(){return f(this.lw.$t().$c(this.aw)).Dt}}function ye(t,i,n){const s=qs(t,["time","originalTime"]),e=Object.assign({time:i},s);return void 0!==n&&(e.originalTime=n),e}const Ce={color:"#FF0000",price:0,lineStyle:2,lineWidth:1,lineVisible:!0,axisLabelVisible:!0,title:"",axisLabelColor:"",axisLabelTextColor:""};class Te{constructor(t){this.Lh=t}applyOptions(t){this.Lh.Hh(t)}options(){return this.Lh.W()}ow(){return this.Lh}}class Pe{constructor(t,i,n,s,e){this._w=new C,this.Is=t,this.uw=i,this.cw=n,this.U_=e,this.dw=s}S(){this._w.S()}priceFormatter(){return this.Is.ma()}priceToCoordinate(t){const i=this.Is.Ct();return null===i?null:this.Is.Dt().Rt(t,i.Ot)}coordinateToPrice(t){const i=this.Is.Ct();return null===i?null:this.Is.Dt().pn(t,i.Ot)}barsInLogicalRange(t){if(null===t)return null;const i=new Mn(new bn(t.from,t.to)).hu(),n=this.Is.zn();if(n.Ni())return null;const s=n.hl(i.Os(),1),e=n.hl(i.ui(),-1),r=f(n.sl()),h=f(n.An());if(null!==s&&null!==e&&s.se>e.se)return{barsBefore:t.from-r,barsAfter:h-t.to};const l={barsBefore:null===s||s.se===r?t.from-r:s.se-r,barsAfter:null===e||e.se===h?h-t.to:h-e.se};return null!==s&&null!==e&&(l.from=s.zb,l.to=e.zb),l}setData(t){this.U_,this.Is.Jh(),this.uw.fw(this.Is,t),this.pw("full")}update(t){this.Is.Jh(),this.uw.mw(this.Is,t),this.pw("update")}dataByIndex(t,i){const n=this.Is.zn().hl(t,i);if(null===n)return null;return ve(this.seriesType())(n)}data(){const t=ve(this.seriesType());return this.Is.zn().ie().map((i=>t(i)))}subscribeDataChanged(t){this._w.l(t)}unsubscribeDataChanged(t){this._w.v(t)}setMarkers(t){this.U_;const i=t.map((t=>ye(t,this.U_.convertHorzItemToInternal(t.time),t.time)));this.Is.ia(i)}markers(){return this.Is.na().map((t=>ye(t,t.originalTime,void 0)))}applyOptions(t){this.Is.Hh(t)}options(){return V(this.Is.W())}priceScale(){return this.cw.priceScale(this.Is.Dt().Ta())}createPriceLine(t){const i=T(V(Ce),t),n=this.Is.sa(i);return new Te(n)}removePriceLine(t){this.Is.ea(t.ow())}seriesType(){return this.Is.Jh()}attachPrimitive(t){this.Is.Sa(t),t.attached&&t.attached({chart:this.dw,series:this,requestUpdate:()=>this.Is.$t().Xl()})}detachPrimitive(t){this.Is.ka(t),t.detached&&t.detached()}pw(t){this._w.M()&&this._w.m(t)}}class Re{constructor(t,i,n){this.bw=new C,this.pu=new C,this.Om=new C,this.$i=t,this.kl=t.St(),this.lb=i,this.kl.tc().l(this.ww.bind(this)),this.kl.nc().l(this.gw.bind(this)),this.lb.Lm().l(this.Mw.bind(this)),this.U_=n}S(){this.kl.tc().p(this),this.kl.nc().p(this),this.lb.Lm().p(this),this.bw.S(),this.pu.S(),this.Om.S()}scrollPosition(){return this.kl.ju()}scrollToPosition(t,i){i?this.kl.Gu(t,1e3):this.$i.Jn(t)}scrollToRealTime(){this.kl.Ku()}getVisibleRange(){const t=this.kl.Du();return null===t?null:{from:t.from.originalTime,to:t.to.originalTime}}setVisibleRange(t){const i={from:this.U_.convertHorzItemToInternal(t.from),to:this.U_.convertHorzItemToInternal(t.to)},n=this.kl.Au(i);this.$i.vd(n)}getVisibleLogicalRange(){const t=this.kl.Ru();return null===t?null:{from:t.Os(),to:t.ui()}}setVisibleLogicalRange(t){c(t.from<=t.to,"The from index cannot be after the to index."),this.$i.vd(t)}resetTimeScale(){this.$i.Kn()}fitContent(){this.$i.rc()}logicalToCoordinate(t){const i=this.$i.St();return i.Ni()?null:i.zt(t)}coordinateToLogical(t){return this.kl.Ni()?null:this.kl.Lu(t)}timeToCoordinate(t){const i=this.U_.convertHorzItemToInternal(t),n=this.kl.Da(i,!1);return null===n?null:this.kl.zt(n)}coordinateToTime(t){const i=this.$i.St(),n=i.Lu(t),s=i.Ui(n);return null===s?null:s.originalTime}width(){return this.lb._m().width}height(){return this.lb._m().height}subscribeVisibleTimeRangeChange(t){this.bw.l(t)}unsubscribeVisibleTimeRangeChange(t){this.bw.v(t)}subscribeVisibleLogicalRangeChange(t){this.pu.l(t)}unsubscribeVisibleLogicalRangeChange(t){this.pu.v(t)}subscribeSizeChange(t){this.Om.l(t)}unsubscribeSizeChange(t){this.Om.v(t)}applyOptions(t){this.kl.Hh(t)}options(){return Object.assign(Object.assign({},V(this.kl.W())),{barSpacing:this.kl.he()})}ww(){this.bw.M()&&this.bw.m(this.getVisibleRange())}gw(){this.pu.M()&&this.pu.m(this.getVisibleLogicalRange())}Mw(t){this.Om.m(t.width,t.height)}}function De(t){if(void 0===t||"custom"===t.type)return;const i=t;void 0!==i.minMove&&void 0===i.precision&&(i.precision=function(t){if(t>=1)return 0;let i=0;for(;i<8;i++){const n=Math.round(t);if(Math.abs(n-t)<1e-8)return i;t*=10}return i}(i.minMove))}function Oe(t){return function(t){if(O(t.handleScale)){const i=t.handleScale;t.handleScale={axisDoubleClickReset:{time:i,price:i},axisPressedMouseMove:{time:i,price:i},mouseWheel:i,pinch:i}}else if(void 0!==t.handleScale){const{axisPressedMouseMove:i,axisDoubleClickReset:n}=t.handleScale;O(i)&&(t.handleScale.axisPressedMouseMove={time:i,price:i}),O(n)&&(t.handleScale.axisDoubleClickReset={time:n,price:n})}const i=t.handleScroll;O(i)&&(t.handleScroll={horzTouchDrag:i,vertTouchDrag:i,mouseWheel:i,pressedMouseMove:i})}(t),t}class Ve{constructor(t,i,n){this.xw=new Map,this.Sw=new Map,this.kw=new C,this.yw=new C,this.Cw=new C,this.Tw=new he(i);const s=void 0===n?V(Se()):T(V(Se()),Oe(n));this.U_=i,this.lw=new Hs(t,s,i),this.lw.hm().l((t=>{this.kw.M()&&this.kw.m(this.Pw(t()))}),this),this.lw.lm().l((t=>{this.yw.M()&&this.yw.m(this.Pw(t()))}),this),this.lw.Zc().l((t=>{this.Cw.M()&&this.Cw.m(this.Pw(t()))}),this);const e=this.lw.$t();this.Rw=new Re(e,this.lw.cb(),this.U_)}remove(){this.lw.hm().p(this),this.lw.lm().p(this),this.lw.Zc().p(this),this.Rw.S(),this.lw.S(),this.xw.clear(),this.Sw.clear(),this.kw.S(),this.yw.S(),this.Cw.S(),this.Tw.S()}resize(t,i,n){this.autoSizeActive()||this.lw.ob(t,i,n)}addCustomSeries(t,i){const n=v(t),s=Object.assign(Object.assign({},h),n.defaultOptions());return this.Dw("Custom",s,i,n)}addAreaSeries(t){return this.Dw("Area",s,t)}addBaselineSeries(t){return this.Dw("Baseline",e,t)}addBarSeries(t){return this.Dw("Bar",i,t)}addCandlestickSeries(i={}){return function(t){void 0!==t.borderColor&&(t.borderUpColor=t.borderColor,t.borderDownColor=t.borderColor),void 0!==t.wickColor&&(t.wickUpColor=t.wickColor,t.wickDownColor=t.wickColor)}(i),this.Dw("Candlestick",t,i)}addHistogramSeries(t){return this.Dw("Histogram",r,t)}addLineSeries(t){return this.Dw("Line",n,t)}removeSeries(t){const i=d(this.xw.get(t)),n=this.Tw.fd(i);this.lw.$t().fd(i),this.Ow(n),this.xw.delete(t),this.Sw.delete(i)}fw(t,i){this.Ow(this.Tw.Xb(t,i))}mw(t,i){this.Ow(this.Tw.tw(t,i))}subscribeClick(t){this.kw.l(t)}unsubscribeClick(t){this.kw.v(t)}subscribeCrosshairMove(t){this.Cw.l(t)}unsubscribeCrosshairMove(t){this.Cw.v(t)}subscribeDblClick(t){this.yw.l(t)}unsubscribeDblClick(t){this.yw.v(t)}priceScale(t){return new ke(this.lw,t)}timeScale(){return this.Rw}applyOptions(t){this.lw.Hh(Oe(t))}options(){return this.lw.W()}takeScreenshot(){return this.lw.bb()}autoSizeActive(){return this.lw.Sb()}chartElement(){return this.lw.kb()}paneSize(){const t=this.lw.Cb();return{height:t.height,width:t.width}}setCrosshairPosition(t,i,n){const s=this.xw.get(n);if(void 0===s)return;const e=this.lw.$t().cr(s);null!==e&&this.lw.$t().ld(t,i,e)}clearCrosshairPosition(){this.lw.$t().ad(!0)}Dw(t,i,n={},s){De(n.priceFormat);const e=T(V(l),V(i),n),r=this.lw.$t().ud(t,e,s),h=new Pe(r,this,this,this,this.U_);return this.xw.set(h,r),this.Sw.set(r,h),h}Ow(t){const i=this.lw.$t();i.od(t.St.Iu,t.St.rw,t.St.hw),t.sw.forEach(((t,i)=>i.J(t.He,t.ew))),i.Fu()}Vw(t){return d(this.Sw.get(t))}Pw(t){const i=new Map;t.Lb.forEach(((t,n)=>{const s=n.Jh(),e=ve(s)(t);if("Custom"!==s)c(Us(e));else{const t=n.Ca();c(!t||!1===t(e))}i.set(this.Vw(n),e)}));const n=void 0!==t.Ib&&this.Sw.has(t.Ib)?this.Vw(t.Ib):void 0;return{time:t.zb,logical:t.se,point:t.Eb,hoveredSeries:n,hoveredObjectId:t.Nb,seriesData:i,sourceEvent:t.Fb}}}function Be(t,i,n){let s;if(D(t)){const i=document.getElementById(t);c(null!==i,`Cannot find element in DOM with id=${t}`),s=i}else s=t;const e=new Ve(s,i,n);return i.setOptions(e.options()),e}function Ae(t,i){return Be(t,new Gn,Gn.Ad(i))}function ze(){return Gn}const Ee=Object.assign(Object.assign({},l),h);function Ie(){return"4.2.0"}export{On as ColorType,et as CrosshairMode,Rn as LastPriceAnimationMode,o as LineStyle,a as LineType,Bi as MismatchDirection,Dn as PriceLineSource,cn as PriceScaleMode,Vn as TickMarkType,Pn as TrackingModeExitMode,Ae as createChart,Be as createChartEx,Ee as customSeriesDefaultOptions,ze as defaultHorzScaleBehavior,An as isBusinessDay,zn as isUTCTimestamp,Ie as version};
\ No newline at end of file
diff --git a/app-html/libraries/lightweight-charts/types.d.ts b/app-html/libraries/lightweight-charts/types.d.ts
new file mode 100644
index 000000000..d721b13fc
--- /dev/null
+++ b/app-html/libraries/lightweight-charts/types.d.ts
@@ -0,0 +1,3881 @@
+// Generated by dts-bundle-generator v8.0.1
+
+type CanvasRenderingTarget2D = any;
+
+export declare const customSeriesDefaultOptions: CustomSeriesOptions;
+/**
+ * Represents a type of color.
+ */
+export declare enum ColorType {
+ /** Solid color */
+ Solid = "solid",
+ /** Vertical gradient color */
+ VerticalGradient = "gradient",
+}
+/**
+ * Represents the crosshair mode.
+ */
+export declare enum CrosshairMode {
+ /**
+ * This mode allows crosshair to move freely on the chart.
+ */
+ Normal = 0,
+ /**
+ * This mode sticks crosshair's horizontal line to the price value of a single-value series or to the close price of OHLC-based series.
+ */
+ Magnet = 1,
+ /**
+ * This mode disables rendering of the crosshair.
+ */
+ Hidden = 2,
+}
+/**
+ * Represents the type of the last price animation for series such as area or line.
+ */
+export declare enum LastPriceAnimationMode {
+ /**
+ * Animation is always disabled
+ */
+ Disabled = 0,
+ /**
+ * Animation is always enabled.
+ */
+ Continuous = 1,
+ /**
+ * Animation is active after new data.
+ */
+ OnDataUpdate = 2,
+}
+/**
+ * Represents the possible line styles.
+ */
+export declare enum LineStyle {
+ /**
+ * A solid line.
+ */
+ Solid = 0,
+ /**
+ * A dotted line.
+ */
+ Dotted = 1,
+ /**
+ * A dashed line.
+ */
+ Dashed = 2,
+ /**
+ * A dashed line with bigger dashes.
+ */
+ LargeDashed = 3,
+ /**
+ * A dotted line with more space between dots.
+ */
+ SparseDotted = 4,
+}
+/**
+ * Represents the possible line types.
+ */
+export declare enum LineType {
+ /**
+ * A line.
+ */
+ Simple = 0,
+ /**
+ * A stepped line.
+ */
+ WithSteps = 1,
+ /**
+ * A curved line.
+ */
+ Curved = 2,
+}
+/**
+ * Search direction if no data found at provided index
+ */
+export declare enum MismatchDirection {
+ /**
+ * Search the nearest left item
+ */
+ NearestLeft = -1,
+ /**
+ * Do not search
+ */
+ None = 0,
+ /**
+ * Search the nearest right item
+ */
+ NearestRight = 1,
+}
+/**
+ * Represents the source of data to be used for the horizontal price line.
+ */
+export declare enum PriceLineSource {
+ /**
+ * Use the last bar data.
+ */
+ LastBar = 0,
+ /**
+ * Use the last visible data of the chart viewport.
+ */
+ LastVisible = 1,
+}
+/**
+ * Represents the price scale mode.
+ */
+export declare enum PriceScaleMode {
+ /**
+ * Price scale shows prices. Price range changes linearly.
+ */
+ Normal = 0,
+ /**
+ * Price scale shows prices. Price range changes logarithmically.
+ */
+ Logarithmic = 1,
+ /**
+ * Price scale shows percentage values according the first visible value of the price scale.
+ * The first visible value is 0% in this mode.
+ */
+ Percentage = 2,
+ /**
+ * The same as percentage mode, but the first value is moved to 100.
+ */
+ IndexedTo100 = 3,
+}
+/**
+ * Represents the type of a tick mark on the time axis.
+ */
+export declare enum TickMarkType {
+ /**
+ * The start of the year (e.g. it's the first tick mark in a year).
+ */
+ Year = 0,
+ /**
+ * The start of the month (e.g. it's the first tick mark in a month).
+ */
+ Month = 1,
+ /**
+ * A day of the month.
+ */
+ DayOfMonth = 2,
+ /**
+ * A time without seconds.
+ */
+ Time = 3,
+ /**
+ * A time with seconds.
+ */
+ TimeWithSeconds = 4,
+}
+/**
+ * Determine how to exit the tracking mode.
+ *
+ * By default, mobile users will long press to deactivate the scroll and have the ability to check values and dates.
+ * Another press is required to activate the scroll, be able to move left/right, zoom, etc.
+ */
+export declare enum TrackingModeExitMode {
+ /**
+ * Tracking Mode will be deactivated on touch end event.
+ */
+ OnTouchEnd = 0,
+ /**
+ * Tracking Mode will be deactivated on the next tap event.
+ */
+ OnNextTap = 1,
+}
+/**
+ * This function is the simplified main entry point of the Lightweight Charting Library with time points for the horizontal scale.
+ *
+ * @param container - ID of HTML element or element itself
+ * @param options - Any subset of options to be applied at start.
+ * @returns An interface to the created chart
+ */
+export declare function createChart(
+ container: string | HTMLElement,
+ options?: DeepPartial
+): IChartApi;
+/**
+ * This function is the main entry point of the Lightweight Charting Library. If you are using time values
+ * for the horizontal scale then it is recommended that you rather use the {@link createChart} function.
+ *
+ * @template HorzScaleItem - type of points on the horizontal scale
+ * @template THorzScaleBehavior - type of horizontal axis strategy that encapsulate all the specific behaviors of the horizontal scale type
+ *
+ * @param container - ID of HTML element or element itself
+ * @param horzScaleBehavior - Horizontal scale behavior
+ * @param options - Any subset of options to be applied at start.
+ * @returns An interface to the created chart
+ */
+export declare function createChartEx<
+ HorzScaleItem,
+ THorzScaleBehavior extends IHorzScaleBehavior
+>(
+ container: string | HTMLElement,
+ horzScaleBehavior: THorzScaleBehavior,
+ options?: DeepPartial>
+): IChartApiBase;
+/**
+ * Provides the default implementation of the horizontal scale (time-based) that can be used as a base for extending the horizontal scale with custom behavior.
+ * This allows for the introduction of custom functionality without re-implementing the entire {@link IHorzScaleBehavior}<{@link Time}> interface.
+ *
+ * For further details, refer to the {@link createChartEx} chart constructor method.
+ *
+ * @returns An uninitialized class implementing the {@link IHorzScaleBehavior}<{@link Time}> interface
+ */
+export declare function defaultHorzScaleBehavior(): new () => IHorzScaleBehavior;
+/**
+ * Check if a time value is a business day object.
+ *
+ * @param time - The time to check.
+ * @returns `true` if `time` is a {@link BusinessDay} object, false otherwise.
+ */
+export declare function isBusinessDay(time: Time): time is BusinessDay;
+/**
+ * Check if a time value is a UTC timestamp number.
+ *
+ * @param time - The time to check.
+ * @returns `true` if `time` is a {@link UTCTimestamp} number, false otherwise.
+ */
+export declare function isUTCTimestamp(time: Time): time is UTCTimestamp;
+/**
+ * Returns the current version as a string. For example `'3.3.0'`.
+ */
+export declare function version(): string;
+/**
+ * Structure describing a single item of data for area series
+ */
+export interface AreaData
+ extends SingleValueData {
+ /**
+ * Optional line color value for certain data item. If missed, color from options is used
+ */
+ lineColor?: string;
+ /**
+ * Optional top color value for certain data item. If missed, color from options is used
+ */
+ topColor?: string;
+ /**
+ * Optional bottom color value for certain data item. If missed, color from options is used
+ */
+ bottomColor?: string;
+}
+/**
+ * Represents style options for an area series.
+ */
+export interface AreaStyleOptions {
+ /**
+ * Color of the top part of the area.
+ *
+ * @defaultValue `'rgba( 46, 220, 135, 0.4)'`
+ */
+ topColor: string;
+ /**
+ * Color of the bottom part of the area.
+ *
+ * @defaultValue `'rgba( 40, 221, 100, 0)'`
+ */
+ bottomColor: string;
+ /**
+ * Invert the filled area. Fills the area above the line if set to true.
+ *
+ * @defaultValue `false`
+ */
+ invertFilledArea: boolean;
+ /**
+ * Line color.
+ *
+ * @defaultValue `'#33D778'`
+ */
+ lineColor: string;
+ /**
+ * Line style.
+ *
+ * @defaultValue {@link LineStyle.Solid}
+ */
+ lineStyle: LineStyle;
+ /**
+ * Line width in pixels.
+ *
+ * @defaultValue `3`
+ */
+ lineWidth: LineWidth;
+ /**
+ * Line type.
+ *
+ * @defaultValue {@link LineType.Simple}
+ */
+ lineType: LineType;
+ /**
+ * Show series line.
+ *
+ * @defaultValue `true`
+ */
+ lineVisible: boolean;
+ /**
+ * Show circle markers on each point.
+ *
+ * @defaultValue `false`
+ */
+ pointMarkersVisible: boolean;
+ /**
+ * Circle markers radius in pixels.
+ *
+ * @defaultValue `undefined`
+ */
+ pointMarkersRadius?: number;
+ /**
+ * Show the crosshair marker.
+ *
+ * @defaultValue `true`
+ */
+ crosshairMarkerVisible: boolean;
+ /**
+ * Crosshair marker radius in pixels.
+ *
+ * @defaultValue `4`
+ */
+ crosshairMarkerRadius: number;
+ /**
+ * Crosshair marker border color. An empty string falls back to the color of the series under the crosshair.
+ *
+ * @defaultValue `''`
+ */
+ crosshairMarkerBorderColor: string;
+ /**
+ * The crosshair marker background color. An empty string falls back to the color of the series under the crosshair.
+ *
+ * @defaultValue `''`
+ */
+ crosshairMarkerBackgroundColor: string;
+ /**
+ * Crosshair marker border width in pixels.
+ *
+ * @defaultValue `2`
+ */
+ crosshairMarkerBorderWidth: number;
+ /**
+ * Last price animation mode.
+ *
+ * @defaultValue {@link LastPriceAnimationMode.Disabled}
+ */
+ lastPriceAnimation: LastPriceAnimationMode;
+}
+/**
+ * Represents the margin used when updating a price scale.
+ */
+export interface AutoScaleMargins {
+ /** The number of pixels for bottom margin */
+ below: number;
+ /** The number of pixels for top margin */
+ above: number;
+}
+/**
+ * Represents information used to update a price scale.
+ */
+export interface AutoscaleInfo {
+ /**
+ * Price range.
+ */
+ priceRange: PriceRange;
+ /**
+ * Scale margins.
+ */
+ margins?: AutoScaleMargins;
+}
+/**
+ * Represents options for how the time and price axes react to mouse double click.
+ */
+export interface AxisDoubleClickOptions {
+ /**
+ * Enable resetting scaling the time axis by double-clicking the left mouse button.
+ *
+ * @defaultValue `true`
+ */
+ time: boolean;
+ /**
+ * Enable reseting scaling the price axis by by double-clicking the left mouse button.
+ *
+ * @defaultValue `true`
+ */
+ price: boolean;
+}
+/**
+ * Represents options for how the time and price axes react to mouse movements.
+ */
+export interface AxisPressedMouseMoveOptions {
+ /**
+ * Enable scaling the time axis by holding down the left mouse button and moving the mouse.
+ *
+ * @defaultValue `true`
+ */
+ time: boolean;
+ /**
+ * Enable scaling the price axis by holding down the left mouse button and moving the mouse.
+ *
+ * @defaultValue `true`
+ */
+ price: boolean;
+}
+/**
+ * Structure describing a single item of data for bar series
+ */
+export interface BarData extends OhlcData {
+ /**
+ * Optional color value for certain data item. If missed, color from options is used
+ */
+ color?: string;
+}
+/**
+ * Represents style options for a bar series.
+ */
+export interface BarStyleOptions {
+ /**
+ * Color of rising bars.
+ *
+ * @defaultValue `'#26a69a'`
+ */
+ upColor: string;
+ /**
+ * Color of falling bars.
+ *
+ * @defaultValue `'#ef5350'`
+ */
+ downColor: string;
+ /**
+ * Show open lines on bars.
+ *
+ * @defaultValue `true`
+ */
+ openVisible: boolean;
+ /**
+ * Show bars as sticks.
+ *
+ * @defaultValue `true`
+ */
+ thinBars: boolean;
+}
+/**
+ * Represents a range of bars and the number of bars outside the range.
+ */
+export interface BarsInfo extends Partial> {
+ /**
+ * The number of bars before the start of the range.
+ * Positive value means that there are some bars before (out of logical range from the left) the {@link Range.from} logical index in the series.
+ * Negative value means that the first series' bar is inside the passed logical range, and between the first series' bar and the {@link Range.from} logical index are some bars.
+ */
+ barsBefore: number;
+ /**
+ * The number of bars after the end of the range.
+ * Positive value in the `barsAfter` field means that there are some bars after (out of logical range from the right) the {@link Range.to} logical index in the series.
+ * Negative value means that the last series' bar is inside the passed logical range, and between the last series' bar and the {@link Range.to} logical index are some bars.
+ */
+ barsAfter: number;
+}
+/**
+ * Represents a type of priced base value of baseline series type.
+ */
+export interface BaseValuePrice {
+ /**
+ * Distinguished type value.
+ */
+ type: "price";
+ /**
+ * Price value.
+ */
+ price: number;
+}
+/**
+ * Structure describing a single item of data for baseline series
+ */
+export interface BaselineData
+ extends SingleValueData {
+ /**
+ * Optional top area top fill color value for certain data item. If missed, color from options is used
+ */
+ topFillColor1?: string;
+ /**
+ * Optional top area bottom fill color value for certain data item. If missed, color from options is used
+ */
+ topFillColor2?: string;
+ /**
+ * Optional top area line color value for certain data item. If missed, color from options is used
+ */
+ topLineColor?: string;
+ /**
+ * Optional bottom area top fill color value for certain data item. If missed, color from options is used
+ */
+ bottomFillColor1?: string;
+ /**
+ * Optional bottom area bottom fill color value for certain data item. If missed, color from options is used
+ */
+ bottomFillColor2?: string;
+ /**
+ * Optional bottom area line color value for certain data item. If missed, color from options is used
+ */
+ bottomLineColor?: string;
+}
+/**
+ * Represents style options for a baseline series.
+ */
+export interface BaselineStyleOptions {
+ /**
+ * Base value of the series.
+ *
+ * @defaultValue `{ type: 'price', price: 0 }`
+ */
+ baseValue: BaseValueType;
+ /**
+ * The first color of the top area.
+ *
+ * @defaultValue `'rgba(38, 166, 154, 0.28)'`
+ */
+ topFillColor1: string;
+ /**
+ * The second color of the top area.
+ *
+ * @defaultValue `'rgba(38, 166, 154, 0.05)'`
+ */
+ topFillColor2: string;
+ /**
+ * The line color of the top area.
+ *
+ * @defaultValue `'rgba(38, 166, 154, 1)'`
+ */
+ topLineColor: string;
+ /**
+ * The first color of the bottom area.
+ *
+ * @defaultValue `'rgba(239, 83, 80, 0.05)'`
+ */
+ bottomFillColor1: string;
+ /**
+ * The second color of the bottom area.
+ *
+ * @defaultValue `'rgba(239, 83, 80, 0.28)'`
+ */
+ bottomFillColor2: string;
+ /**
+ * The line color of the bottom area.
+ *
+ * @defaultValue `'rgba(239, 83, 80, 1)'`
+ */
+ bottomLineColor: string;
+ /**
+ * Line width.
+ *
+ * @defaultValue `3`
+ */
+ lineWidth: LineWidth;
+ /**
+ * Line style.
+ *
+ * @defaultValue {@link LineStyle.Solid}
+ */
+ lineStyle: LineStyle;
+ /**
+ * Line type.
+ *
+ * @defaultValue {@link LineType.Simple}
+ */
+ lineType: LineType;
+ /**
+ * Show series line.
+ *
+ * @defaultValue `true`
+ */
+ lineVisible: boolean;
+ /**
+ * Show circle markers on each point.
+ *
+ * @defaultValue `false`
+ */
+ pointMarkersVisible: boolean;
+ /**
+ * Circle markers radius in pixels.
+ *
+ * @defaultValue `undefined`
+ */
+ pointMarkersRadius?: number;
+ /**
+ * Show the crosshair marker.
+ *
+ * @defaultValue `true`
+ */
+ crosshairMarkerVisible: boolean;
+ /**
+ * Crosshair marker radius in pixels.
+ *
+ * @defaultValue `4`
+ */
+ crosshairMarkerRadius: number;
+ /**
+ * Crosshair marker border color. An empty string falls back to the color of the series under the crosshair.
+ *
+ * @defaultValue `''`
+ */
+ crosshairMarkerBorderColor: string;
+ /**
+ * The crosshair marker background color. An empty string falls back to the color of the series under the crosshair.
+ *
+ * @defaultValue `''`
+ */
+ crosshairMarkerBackgroundColor: string;
+ /**
+ * Crosshair marker border width in pixels.
+ *
+ * @defaultValue `2`
+ */
+ crosshairMarkerBorderWidth: number;
+ /**
+ * Last price animation mode.
+ *
+ * @defaultValue {@link LastPriceAnimationMode.Disabled}
+ */
+ lastPriceAnimation: LastPriceAnimationMode;
+}
+/**
+ * Represents a time as a day/month/year.
+ *
+ * @example
+ * ```js
+ * const day = { year: 2019, month: 6, day: 1 }; // June 1, 2019
+ * ```
+ */
+export interface BusinessDay {
+ /**
+ * The year.
+ */
+ year: number;
+ /**
+ * The month.
+ */
+ month: number;
+ /**
+ * The day.
+ */
+ day: number;
+}
+/**
+ * Structure describing a single item of data for candlestick series
+ */
+export interface CandlestickData
+ extends OhlcData {
+ /**
+ * Optional color value for certain data item. If missed, color from options is used
+ */
+ color?: string;
+ /**
+ * Optional border color value for certain data item. If missed, color from options is used
+ */
+ borderColor?: string;
+ /**
+ * Optional wick color value for certain data item. If missed, color from options is used
+ */
+ wickColor?: string;
+}
+/**
+ * Represents style options for a candlestick series.
+ */
+export interface CandlestickStyleOptions {
+ /**
+ * Color of rising candles.
+ *
+ * @defaultValue `'#26a69a'`
+ */
+ upColor: string;
+ /**
+ * Color of falling candles.
+ *
+ * @defaultValue `'#ef5350'`
+ */
+ downColor: string;
+ /**
+ * Enable high and low prices candle wicks.
+ *
+ * @defaultValue `true`
+ */
+ wickVisible: boolean;
+ /**
+ * Enable candle borders.
+ *
+ * @defaultValue `true`
+ */
+ borderVisible: boolean;
+ /**
+ * Border color.
+ *
+ * @defaultValue `'#378658'`
+ */
+ borderColor: string;
+ /**
+ * Border color of rising candles.
+ *
+ * @defaultValue `'#26a69a'`
+ */
+ borderUpColor: string;
+ /**
+ * Border color of falling candles.
+ *
+ * @defaultValue `'#ef5350'`
+ */
+ borderDownColor: string;
+ /**
+ * Wick color.
+ *
+ * @defaultValue `'#737375'`
+ */
+ wickColor: string;
+ /**
+ * Wick color of rising candles.
+ *
+ * @defaultValue `'#26a69a'`
+ */
+ wickUpColor: string;
+ /**
+ * Wick color of falling candles.
+ *
+ * @defaultValue `'#ef5350'`
+ */
+ wickDownColor: string;
+}
+/**
+ * Represents common chart options
+ */
+export interface ChartOptionsBase {
+ /**
+ * Width of the chart in pixels
+ *
+ * @defaultValue If `0` (default) or none value provided, then a size of the widget will be calculated based its container's size.
+ */
+ width: number;
+ /**
+ * Height of the chart in pixels
+ *
+ * @defaultValue If `0` (default) or none value provided, then a size of the widget will be calculated based its container's size.
+ */
+ height: number;
+ /**
+ * Setting this flag to `true` will make the chart watch the chart container's size and automatically resize the chart to fit its container whenever the size changes.
+ *
+ * This feature requires [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) class to be available in the global scope.
+ * Note that calling code is responsible for providing a polyfill if required. If the global scope does not have `ResizeObserver`, a warning will appear and the flag will be ignored.
+ *
+ * Please pay attention that `autoSize` option and explicit sizes options `width` and `height` don't conflict with one another.
+ * If you specify `autoSize` flag, then `width` and `height` options will be ignored unless `ResizeObserver` has failed. If it fails then the values will be used as fallback.
+ *
+ * The flag `autoSize` could also be set with and unset with `applyOptions` function.
+ * ```js
+ * const chart = LightweightCharts.createChart(document.body, {
+ * autoSize: true,
+ * });
+ * ```
+ */
+ autoSize: boolean;
+ /**
+ * Watermark options.
+ *
+ * A watermark is a background label that includes a brief description of the drawn data. Any text can be added to it.
+ *
+ * Please make sure you enable it and set an appropriate font color and size to make your watermark visible in the background of the chart.
+ * We recommend a semi-transparent color and a large font. Also note that watermark position can be aligned vertically and horizontally.
+ */
+ watermark: WatermarkOptions;
+ /**
+ * Layout options
+ */
+ layout: LayoutOptions;
+ /**
+ * Left price scale options
+ */
+ leftPriceScale: VisiblePriceScaleOptions;
+ /**
+ * Right price scale options
+ */
+ rightPriceScale: VisiblePriceScaleOptions;
+ /**
+ * Overlay price scale options
+ */
+ overlayPriceScales: OverlayPriceScaleOptions;
+ /**
+ * Time scale options
+ */
+ timeScale: HorzScaleOptions;
+ /**
+ * The crosshair shows the intersection of the price and time scale values at any point on the chart.
+ *
+ */
+ crosshair: CrosshairOptions;
+ /**
+ * A grid is represented in the chart background as a vertical and horizontal lines drawn at the levels of visible marks of price and the time scales.
+ */
+ grid: GridOptions;
+ /**
+ * Scroll options, or a boolean flag that enables/disables scrolling
+ */
+ handleScroll: HandleScrollOptions | boolean;
+ /**
+ * Scale options, or a boolean flag that enables/disables scaling
+ */
+ handleScale: HandleScaleOptions | boolean;
+ /**
+ * Kinetic scroll options
+ */
+ kineticScroll: KineticScrollOptions;
+ /** @inheritDoc TrackingModeOptions
+ */
+ trackingMode: TrackingModeOptions;
+ /**
+ * Basic localization options
+ */
+ localization: LocalizationOptionsBase;
+}
+/**
+ * Structure describing options of the chart. Series options are to be set separately
+ */
+export interface ChartOptionsImpl extends ChartOptionsBase {
+ /**
+ * Localization options.
+ */
+ localization: LocalizationOptions;
+}
+/** Structure describing a crosshair line (vertical or horizontal) */
+export interface CrosshairLineOptions {
+ /**
+ * Crosshair line color.
+ *
+ * @defaultValue `'#758696'`
+ */
+ color: string;
+ /**
+ * Crosshair line width.
+ *
+ * @defaultValue `1`
+ */
+ width: LineWidth;
+ /**
+ * Crosshair line style.
+ *
+ * @defaultValue {@link LineStyle.LargeDashed}
+ */
+ style: LineStyle;
+ /**
+ * Display the crosshair line.
+ *
+ * Note that disabling crosshair lines does not disable crosshair marker on Line and Area series.
+ * It can be disabled by using `crosshairMarkerVisible` option of a relevant series.
+ *
+ * @see {@link LineStyleOptions.crosshairMarkerVisible}
+ * @see {@link AreaStyleOptions.crosshairMarkerVisible}
+ * @see {@link BaselineStyleOptions.crosshairMarkerVisible}
+ * @defaultValue `true`
+ */
+ visible: boolean;
+ /**
+ * Display the crosshair label on the relevant scale.
+ *
+ * @defaultValue `true`
+ */
+ labelVisible: boolean;
+ /**
+ * Crosshair label background color.
+ *
+ * @defaultValue `'#4c525e'`
+ */
+ labelBackgroundColor: string;
+}
+/** Structure describing crosshair options */
+export interface CrosshairOptions {
+ /**
+ * Crosshair mode
+ *
+ * @defaultValue {@link CrosshairMode.Magnet}
+ */
+ mode: CrosshairMode;
+ /**
+ * Vertical line options.
+ */
+ vertLine: CrosshairLineOptions;
+ /**
+ * Horizontal line options.
+ */
+ horzLine: CrosshairLineOptions;
+}
+/**
+ * Renderer data for an item within the custom series.
+ */
+export interface CustomBarItemData<
+ HorzScaleItem,
+ TData extends CustomData = CustomData
+> {
+ /**
+ * Horizontal coordinate for the item. Measured from the left edge of the pane in pixels.
+ */
+ x: number;
+ /**
+ * Time scale index for the item. This isn't the timestamp but rather the logical index.
+ */
+ time: number;
+ /**
+ * Original data for the item.
+ */
+ originalData: TData;
+ /**
+ * Color assigned for the item, typically used for price line and price scale label.
+ */
+ barColor: string;
+}
+/**
+ * Base structure describing a single item of data for a custom series.
+ *
+ * This type allows for any properties to be defined
+ * within the interface. It is recommended that you extend this interface with
+ * the required data structure.
+ */
+export interface CustomData
+ extends CustomSeriesWhitespaceData {
+ /**
+ * If defined then this color will be used for the price line and price scale line
+ * for this specific data item of the custom series.
+ */
+ color?: string;
+}
+/**
+ * Represents a whitespace data item, which is a data point without a value.
+ */
+export interface CustomSeriesWhitespaceData {
+ /**
+ * The time of the data.
+ */
+ time: HorzScaleItem;
+ /**
+ * Additional custom values which will be ignored by the library, but
+ * could be used by plugins.
+ */
+ customValues?: Record;
+}
+/**
+ * Represents style options for a custom series.
+ */
+export interface CustomStyleOptions {
+ /**
+ * Color used for the price line and price scale label.
+ */
+ color: string;
+}
+/** Grid line options. */
+export interface GridLineOptions {
+ /**
+ * Line color.
+ *
+ * @defaultValue `'#D6DCDE'`
+ */
+ color: string;
+ /**
+ * Line style.
+ *
+ * @defaultValue {@link LineStyle.Solid}
+ */
+ style: LineStyle;
+ /**
+ * Display the lines.
+ *
+ * @defaultValue `true`
+ */
+ visible: boolean;
+}
+/** Structure describing grid options. */
+export interface GridOptions {
+ /**
+ * Vertical grid line options.
+ */
+ vertLines: GridLineOptions;
+ /**
+ * Horizontal grid line options.
+ */
+ horzLines: GridLineOptions;
+}
+/**
+ * Represents options for how the chart is scaled by the mouse and touch gestures.
+ */
+export interface HandleScaleOptions {
+ /**
+ * Enable scaling with the mouse wheel.
+ *
+ * @defaultValue `true`
+ */
+ mouseWheel: boolean;
+ /**
+ * Enable scaling with pinch/zoom gestures.
+ *
+ * @defaultValue `true`
+ */
+ pinch: boolean;
+ /**
+ * Enable scaling the price and/or time scales by holding down the left mouse button and moving the mouse.
+ */
+ axisPressedMouseMove: AxisPressedMouseMoveOptions | boolean;
+ /**
+ * Enable resetting scaling by double-clicking the left mouse button.
+ */
+ axisDoubleClickReset: AxisDoubleClickOptions | boolean;
+}
+/**
+ * Represents options for how the chart is scrolled by the mouse and touch gestures.
+ */
+export interface HandleScrollOptions {
+ /**
+ * Enable scrolling with the mouse wheel.
+ *
+ * @defaultValue `true`
+ */
+ mouseWheel: boolean;
+ /**
+ * Enable scrolling by holding down the left mouse button and moving the mouse.
+ *
+ * @defaultValue `true`
+ */
+ pressedMouseMove: boolean;
+ /**
+ * Enable horizontal touch scrolling.
+ *
+ * When enabled the chart handles touch gestures that would normally scroll the webpage horizontally.
+ *
+ * @defaultValue `true`
+ */
+ horzTouchDrag: boolean;
+ /**
+ * Enable vertical touch scrolling.
+ *
+ * When enabled the chart handles touch gestures that would normally scroll the webpage vertically.
+ *
+ * @defaultValue `true`
+ */
+ vertTouchDrag: boolean;
+}
+/**
+ * Structure describing a single item of data for histogram series
+ */
+export interface HistogramData
+ extends SingleValueData {
+ /**
+ * Optional color value for certain data item. If missed, color from options is used
+ */
+ color?: string;
+}
+/**
+ * Represents style options for a histogram series.
+ */
+export interface HistogramStyleOptions {
+ /**
+ * Column color.
+ *
+ * @defaultValue `'#26a69a'`
+ */
+ color: string;
+ /**
+ * Initial level of histogram columns.
+ *
+ * @defaultValue `0`
+ */
+ base: number;
+}
+/**
+ * Options for the time scale; the horizontal scale at the bottom of the chart that displays the time of data.
+ */
+export interface HorzScaleOptions {
+ /**
+ * The margin space in bars from the right side of the chart.
+ *
+ * @defaultValue `0`
+ */
+ rightOffset: number;
+ /**
+ * The space between bars in pixels.
+ *
+ * @defaultValue `6`
+ */
+ barSpacing: number;
+ /**
+ * The minimum space between bars in pixels.
+ *
+ * @defaultValue `0.5`
+ */
+ minBarSpacing: number;
+ /**
+ * Prevent scrolling to the left of the first bar.
+ *
+ * @defaultValue `false`
+ */
+ fixLeftEdge: boolean;
+ /**
+ * Prevent scrolling to the right of the most recent bar.
+ *
+ * @defaultValue `false`
+ */
+ fixRightEdge: boolean;
+ /**
+ * Prevent changing the visible time range during chart resizing.
+ *
+ * @defaultValue `false`
+ */
+ lockVisibleTimeRangeOnResize: boolean;
+ /**
+ * Prevent the hovered bar from moving when scrolling.
+ *
+ * @defaultValue `false`
+ */
+ rightBarStaysOnScroll: boolean;
+ /**
+ * Show the time scale border.
+ *
+ * @defaultValue `true`
+ */
+ borderVisible: boolean;
+ /**
+ * The time scale border color.
+ *
+ * @defaultValue `'#2B2B43'`
+ */
+ borderColor: string;
+ /**
+ * Show the time scale.
+ *
+ * @defaultValue `true`
+ */
+ visible: boolean;
+ /**
+ * Show the time, not just the date, in the time scale and vertical crosshair label.
+ *
+ * @defaultValue `false`
+ */
+ timeVisible: boolean;
+ /**
+ * Show seconds in the time scale and vertical crosshair label in `hh:mm:ss` format for intraday data.
+ *
+ * @defaultValue `true`
+ */
+ secondsVisible: boolean;
+ /**
+ * Shift the visible range to the right (into the future) by the number of new bars when new data is added.
+ *
+ * Note that this only applies when the last bar is visible.
+ *
+ * @defaultValue `true`
+ */
+ shiftVisibleRangeOnNewBar: boolean;
+ /**
+ * Allow the visible range to be shifted to the right when a new bar is added which
+ * is replacing an existing whitespace time point on the chart.
+ *
+ * Note that this only applies when the last bar is visible & `shiftVisibleRangeOnNewBar` is enabled.
+ *
+ * @defaultValue `false`
+ */
+ allowShiftVisibleRangeOnWhitespaceReplacement: boolean;
+ /**
+ * Draw small vertical line on time axis labels.
+ *
+ * @defaultValue `false`
+ */
+ ticksVisible: boolean;
+ /**
+ * Maximum tick mark label length. Used to override the default 8 character maximum length.
+ *
+ * @defaultValue `undefined`
+ */
+ tickMarkMaxCharacterLength?: number;
+ /**
+ * Changes horizontal scale marks generation.
+ * With this flag equal to `true`, marks of the same weight are either all drawn or none are drawn at all.
+ */
+ uniformDistribution: boolean;
+ /**
+ * Define a minimum height for the time scale.
+ * Note: This value will be exceeded if the
+ * time scale needs more space to display it's contents.
+ *
+ * Setting a minimum height could be useful for ensuring that
+ * multiple charts positioned in a horizontal stack each have
+ * an identical time scale height, or for plugins which
+ * require a bit more space within the time scale pane.
+ *
+ * @defaultValue 0
+ */
+ minimumHeight: number;
+ /**
+ * Allow major time scale labels to be rendered in a bolder font weight.
+ *
+ * @defaultValue true
+ */
+ allowBoldLabels: boolean;
+}
+/**
+ * The main interface of a single chart using time for horizontal scale.
+ */
+export interface IChartApi extends IChartApiBase {
+ /**
+ * Applies new options to the chart
+ *
+ * @param options - Any subset of options.
+ */
+ applyOptions(options: DeepPartial): void;
+}
+/**
+ * The main interface of a single chart.
+ */
+export interface IChartApiBase {
+ /**
+ * Removes the chart object including all DOM elements. This is an irreversible operation, you cannot do anything with the chart after removing it.
+ */
+ remove(): void;
+ /**
+ * Sets fixed size of the chart. By default chart takes up 100% of its container.
+ *
+ * If chart has the `autoSize` option enabled, and the ResizeObserver is available then
+ * the width and height values will be ignored.
+ *
+ * @param width - Target width of the chart.
+ * @param height - Target height of the chart.
+ * @param forceRepaint - True to initiate resize immediately. One could need this to get screenshot immediately after resize.
+ */
+ resize(width: number, height: number, forceRepaint?: boolean): void;
+ /**
+ * Creates a custom series with specified parameters.
+ *
+ * A custom series is a generic series which can be extended with a custom renderer to
+ * implement chart types which the library doesn't support by default.
+ *
+ * @param customPaneView - A custom series pane view which implements the custom renderer.
+ * @param customOptions - Customization parameters of the series being created.
+ * ```js
+ * const series = chart.addCustomSeries(myCustomPaneView);
+ * ```
+ */
+ addCustomSeries<
+ TData extends CustomData,
+ TOptions extends CustomSeriesOptions,
+ TPartialOptions extends SeriesPartialOptions = SeriesPartialOptions
+ >(
+ customPaneView: ICustomSeriesPaneView,
+ customOptions?: SeriesPartialOptions
+ ): ISeriesApi<
+ "Custom",
+ HorzScaleItem,
+ TData | WhitespaceData,
+ TOptions,
+ TPartialOptions
+ >;
+ /**
+ * Creates an area series with specified parameters.
+ *
+ * @param areaOptions - Customization parameters of the series being created.
+ * @returns An interface of the created series.
+ * @example
+ * ```js
+ * const series = chart.addAreaSeries();
+ * ```
+ */
+ addAreaSeries(
+ areaOptions?: AreaSeriesPartialOptions
+ ): ISeriesApi<"Area", HorzScaleItem>;
+ /**
+ * Creates a baseline series with specified parameters.
+ *
+ * @param baselineOptions - Customization parameters of the series being created.
+ * @returns An interface of the created series.
+ * @example
+ * ```js
+ * const series = chart.addBaselineSeries();
+ * ```
+ */
+ addBaselineSeries(
+ baselineOptions?: BaselineSeriesPartialOptions
+ ): ISeriesApi<"Baseline", HorzScaleItem>;
+ /**
+ * Creates a bar series with specified parameters.
+ *
+ * @param barOptions - Customization parameters of the series being created.
+ * @returns An interface of the created series.
+ * @example
+ * ```js
+ * const series = chart.addBarSeries();
+ * ```
+ */
+ addBarSeries(
+ barOptions?: BarSeriesPartialOptions
+ ): ISeriesApi<"Bar", HorzScaleItem>;
+ /**
+ * Creates a candlestick series with specified parameters.
+ *
+ * @param candlestickOptions - Customization parameters of the series being created.
+ * @returns An interface of the created series.
+ * @example
+ * ```js
+ * const series = chart.addCandlestickSeries();
+ * ```
+ */
+ addCandlestickSeries(
+ candlestickOptions?: CandlestickSeriesPartialOptions
+ ): ISeriesApi<"Candlestick", HorzScaleItem>;
+ /**
+ * Creates a histogram series with specified parameters.
+ *
+ * @param histogramOptions - Customization parameters of the series being created.
+ * @returns An interface of the created series.
+ * @example
+ * ```js
+ * const series = chart.addHistogramSeries();
+ * ```
+ */
+ addHistogramSeries(
+ histogramOptions?: HistogramSeriesPartialOptions
+ ): ISeriesApi<"Histogram", HorzScaleItem>;
+ /**
+ * Creates a line series with specified parameters.
+ *
+ * @param lineOptions - Customization parameters of the series being created.
+ * @returns An interface of the created series.
+ * @example
+ * ```js
+ * const series = chart.addLineSeries();
+ * ```
+ */
+ addLineSeries(
+ lineOptions?: LineSeriesPartialOptions
+ ): ISeriesApi<"Line", HorzScaleItem>;
+ /**
+ * Removes a series of any type. This is an irreversible operation, you cannot do anything with the series after removing it.
+ *
+ * @example
+ * ```js
+ * chart.removeSeries(series);
+ * ```
+ */
+ removeSeries(seriesApi: ISeriesApi): void;
+ /**
+ * Subscribe to the chart click event.
+ *
+ * @param handler - Handler to be called on mouse click.
+ * @example
+ * ```js
+ * function myClickHandler(param) {
+ * if (!param.point) {
+ * return;
+ * }
+ *
+ * console.log(`Click at ${param.point.x}, ${param.point.y}. The time is ${param.time}.`);
+ * }
+ *
+ * chart.subscribeClick(myClickHandler);
+ * ```
+ */
+ subscribeClick(handler: MouseEventHandler): void;
+ /**
+ * Unsubscribe a handler that was previously subscribed using {@link subscribeClick}.
+ *
+ * @param handler - Previously subscribed handler
+ * @example
+ * ```js
+ * chart.unsubscribeClick(myClickHandler);
+ * ```
+ */
+ unsubscribeClick(handler: MouseEventHandler): void;
+ /**
+ * Subscribe to the chart double-click event.
+ *
+ * @param handler - Handler to be called on mouse double-click.
+ * @example
+ * ```js
+ * function myDblClickHandler(param) {
+ * if (!param.point) {
+ * return;
+ * }
+ *
+ * console.log(`Double Click at ${param.point.x}, ${param.point.y}. The time is ${param.time}.`);
+ * }
+ *
+ * chart.subscribeDblClick(myDblClickHandler);
+ * ```
+ */
+ subscribeDblClick(handler: MouseEventHandler): void;
+ /**
+ * Unsubscribe a handler that was previously subscribed using {@link subscribeDblClick}.
+ *
+ * @param handler - Previously subscribed handler
+ * @example
+ * ```js
+ * chart.unsubscribeDblClick(myDblClickHandler);
+ * ```
+ */
+ unsubscribeDblClick(handler: MouseEventHandler): void;
+ /**
+ * Subscribe to the crosshair move event.
+ *
+ * @param handler - Handler to be called on crosshair move.
+ * @example
+ * ```js
+ * function myCrosshairMoveHandler(param) {
+ * if (!param.point) {
+ * return;
+ * }
+ *
+ * console.log(`Crosshair moved to ${param.point.x}, ${param.point.y}. The time is ${param.time}.`);
+ * }
+ *
+ * chart.subscribeCrosshairMove(myCrosshairMoveHandler);
+ * ```
+ */
+ subscribeCrosshairMove(handler: MouseEventHandler): void;
+ /**
+ * Unsubscribe a handler that was previously subscribed using {@link subscribeCrosshairMove}.
+ *
+ * @param handler - Previously subscribed handler
+ * @example
+ * ```js
+ * chart.unsubscribeCrosshairMove(myCrosshairMoveHandler);
+ * ```
+ */
+ unsubscribeCrosshairMove(handler: MouseEventHandler): void;
+ /**
+ * Returns API to manipulate a price scale.
+ *
+ * @param priceScaleId - ID of the price scale.
+ * @returns Price scale API.
+ */
+ priceScale(priceScaleId: string): IPriceScaleApi;
+ /**
+ * Returns API to manipulate the time scale
+ *
+ * @returns Target API
+ */
+ timeScale(): ITimeScaleApi;
+ /**
+ * Applies new options to the chart
+ *
+ * @param options - Any subset of options.
+ */
+ applyOptions(options: DeepPartial>): void;
+ /**
+ * Returns currently applied options
+ *
+ * @returns Full set of currently applied options, including defaults
+ */
+ options(): Readonly>;
+ /**
+ * Make a screenshot of the chart with all the elements excluding crosshair.
+ *
+ * @returns A canvas with the chart drawn on. Any `Canvas` methods like `toDataURL()` or `toBlob()` can be used to serialize the result.
+ */
+ takeScreenshot(): HTMLCanvasElement;
+ /**
+ * Returns the active state of the `autoSize` option. This can be used to check
+ * whether the chart is handling resizing automatically with a `ResizeObserver`.
+ *
+ * @returns Whether the `autoSize` option is enabled and the active.
+ */
+ autoSizeActive(): boolean;
+ /**
+ * Returns the generated div element containing the chart. This can be used for adding your own additional event listeners, or for measuring the
+ * elements dimensions and position within the document.
+ *
+ * @returns generated div element containing the chart.
+ */
+ chartElement(): HTMLDivElement;
+ /**
+ * Set the crosshair position within the chart.
+ *
+ * Usually the crosshair position is set automatically by the user's actions. However in some cases you may want to set it explicitly.
+ *
+ * For example if you want to synchronise the crosshairs of two separate charts.
+ *
+ * @param price - The price (vertical coordinate) of the new crosshair position.
+ * @param horizontalPosition - The horizontal coordinate (time by default) of the new crosshair position.
+ */
+ setCrosshairPosition(
+ price: number,
+ horizontalPosition: HorzScaleItem,
+ seriesApi: ISeriesApi
+ ): void;
+ /**
+ * Clear the crosshair position within the chart.
+ */
+ clearCrosshairPosition(): void;
+ /**
+ * Returns the dimensions of the chart pane (the plot surface which excludes time and price scales).
+ * This would typically only be useful for plugin development.
+ *
+ * @returns Dimensions of the chart pane
+ */
+ paneSize(): PaneSize;
+}
+/**
+ * Renderer for the custom series. This paints on the main chart pane.
+ */
+export interface ICustomSeriesPaneRenderer {
+ /**
+ * Draw function for the renderer.
+ *
+ * @param target - canvas context to draw on, refer to FancyCanvas library for more details about this class.
+ * @param priceConverter - converter function for changing prices into vertical coordinate values.
+ * @param isHovered - Whether the series is hovered.
+ * @param hitTestData - Optional hit test data for the series.
+ */
+ draw(
+ target: CanvasRenderingTarget2D,
+ priceConverter: PriceToCoordinateConverter,
+ isHovered: boolean,
+ hitTestData?: unknown
+ ): void;
+}
+/**
+ * This interface represents the view for the custom series
+ */
+export interface ICustomSeriesPaneView<
+ HorzScaleItem = Time,
+ TData extends CustomData = CustomData,
+ TSeriesOptions extends CustomSeriesOptions = CustomSeriesOptions
+> {
+ /**
+ * This method returns a renderer - special object to draw data for the series
+ * on the main chart pane.
+ *
+ * @returns an renderer object to be used for drawing.
+ */
+ renderer(): ICustomSeriesPaneRenderer;
+ /**
+ * This method will be called with the latest data for the renderer to use
+ * during the next paint.
+ */
+ update(
+ data: PaneRendererCustomData,
+ seriesOptions: TSeriesOptions
+ ): void;
+ /**
+ * A function for interpreting the custom series data and returning an array of numbers
+ * representing the price values for the item. These price values are used
+ * by the chart to determine the auto-scaling (to ensure the items are in view) and the crosshair
+ * and price line positions. The last value in the array will be used as the current value. You shouldn't need to
+ * have more than 3 values in this array since the library only needs a largest, smallest, and current value.
+ */
+ priceValueBuilder(plotRow: TData): CustomSeriesPricePlotValues;
+ /**
+ * A function for testing whether a data point should be considered fully specified, or if it should
+ * be considered as whitespace. Should return `true` if is whitespace.
+ *
+ * @param data - data point to be tested
+ */
+ isWhitespace(
+ data: TData | CustomSeriesWhitespaceData
+ ): data is CustomSeriesWhitespaceData;
+ /**
+ * Default options
+ */
+ defaultOptions(): TSeriesOptions;
+ /**
+ * This method will be evoked when the series has been removed from the chart. This method should be used to
+ * clean up any objects, references, and other items that could potentially cause memory leaks.
+ *
+ * This method should contain all the necessary code to clean up the object before it is removed from memory.
+ * This includes removing any event listeners or timers that are attached to the object, removing any references
+ * to other objects, and resetting any values or properties that were modified during the lifetime of the object.
+ */
+ destroy?(): void;
+}
+/**
+ * Class interface for Horizontal scale behavior
+ */
+export interface IHorzScaleBehavior {
+ /**
+ * Structure describing options of the chart.
+ *
+ * @returns ChartOptionsBase
+ */
+ options(): ChartOptionsImpl;
+ /**
+ * Set the chart options. Note that this is different to `applyOptions` since the provided options will overwrite the current options
+ * instead of merging with the current options.
+ *
+ * @param options - Chart options to be set
+ * @returns void
+ */
+ setOptions(options: ChartOptionsImpl): void;
+ /**
+ * Method to preprocess the data.
+ *
+ * @param data - Data items for the series
+ * @returns void
+ */
+ preprocessData(
+ data: DataItem | DataItem[]
+ ): void;
+ /**
+ * Convert horizontal scale item into an internal horizontal scale item.
+ *
+ * @param item - item to be converted
+ * @returns InternalHorzScaleItem
+ */
+ convertHorzItemToInternal(item: HorzScaleItem): InternalHorzScaleItem;
+ /**
+ * Creates and returns a converter for changing series data into internal horizontal scale items.
+ *
+ * @param data - series data
+ * @returns HorzScaleItemConverterToInternalObj
+ */
+ createConverterToInternalObj(
+ data: SeriesDataItemTypeMap[SeriesType][]
+ ): HorzScaleItemConverterToInternalObj;
+ /**
+ * Returns the key for the specified horizontal scale item.
+ *
+ * @param internalItem - horizontal scale item for which the key should be returned
+ * @returns InternalHorzScaleItemKey
+ */
+ key(
+ internalItem: InternalHorzScaleItem | HorzScaleItem
+ ): InternalHorzScaleItemKey;
+ /**
+ * Returns the cache key for the specified horizontal scale item.
+ *
+ * @param internalItem - horizontal scale item for which the cache key should be returned
+ * @returns number
+ */
+ cacheKey(internalItem: InternalHorzScaleItem): number;
+ /**
+ * Update the formatter with the localization options.
+ *
+ * @param options - Localization options
+ * @returns void
+ */
+ updateFormatter(options: LocalizationOptions): void;
+ /**
+ * Format the horizontal scale item into a display string.
+ *
+ * @param item - horizontal scale item to be formatted as a string
+ * @returns string
+ */
+ formatHorzItem(item: InternalHorzScaleItem): string;
+ /**
+ * Format the horizontal scale tickmark into a display string.
+ *
+ * @param item - tickmark item
+ * @param localizationOptions - Localization options
+ * @returns string
+ */
+ formatTickmark(
+ item: TickMark,
+ localizationOptions: LocalizationOptions
+ ): string;
+ /**
+ * Returns the maximum tickmark weight value for the specified tickmarks on the time scale.
+ *
+ * @param marks - Timescale tick marks
+ * @returns TickMarkWeightValue
+ */
+ maxTickMarkWeight(marks: TimeMark[]): TickMarkWeightValue;
+ /**
+ * Fill the weights for the sorted time scale points.
+ *
+ * @param sortedTimePoints - sorted time scale points
+ * @param startIndex - starting index
+ * @returns void
+ */
+ fillWeightsForPoints(
+ sortedTimePoints: readonly Mutable[],
+ startIndex: number
+ ): void;
+ /**
+ * If returns true, then the tick mark formatter will be called for all the visible
+ * tick marks even if the formatter has previously been called for a specific tick mark.
+ * This allows you to change the formatting on all the tick marks.
+ *
+ * @param tickMarks - array of tick marks
+ * @returns boolean
+ */
+ shouldResetTickmarkLabels?(tickMarks: readonly TickMark[]): boolean;
+}
+/** Interface to be implemented by the object in order to be used as a price formatter */
+export interface IPriceFormatter {
+ /**
+ * Formatting function
+ *
+ * @param price - Original price to be formatted
+ * @returns Formatted price
+ */
+ format(price: number): string;
+}
+/**
+ * Represents the interface for interacting with price lines.
+ */
+export interface IPriceLine {
+ /**
+ * Apply options to the price line.
+ *
+ * @param options - Any subset of options.
+ * @example
+ * ```js
+ * priceLine.applyOptions({
+ * price: 90.0,
+ * color: 'red',
+ * lineWidth: 3,
+ * lineStyle: LightweightCharts.LineStyle.Dashed,
+ * axisLabelVisible: false,
+ * title: 'P/L 600',
+ * });
+ * ```
+ */
+ applyOptions(options: Partial): void;
+ /**
+ * Get the currently applied options.
+ */
+ options(): Readonly;
+}
+/** Interface to control chart's price scale */
+export interface IPriceScaleApi {
+ /**
+ * Applies new options to the price scale
+ *
+ * @param options - Any subset of options.
+ */
+ applyOptions(options: DeepPartial): void;
+ /**
+ * Returns currently applied options of the price scale
+ *
+ * @returns Full set of currently applied options, including defaults
+ */
+ options(): Readonly;
+ /**
+ * Returns a width of the price scale if it's visible or 0 if invisible.
+ */
+ width(): number;
+}
+/**
+ * Represents the interface for interacting with series.
+ */
+export interface ISeriesApi<
+ TSeriesType extends SeriesType,
+ HorzScaleItem = Time,
+ TData = SeriesDataItemTypeMap[TSeriesType],
+ TOptions = SeriesOptionsMap[TSeriesType],
+ TPartialOptions = SeriesPartialOptionsMap[TSeriesType]
+> {
+ /**
+ * Returns current price formatter
+ *
+ * @returns Interface to the price formatter object that can be used to format prices in the same way as the chart does
+ */
+ priceFormatter(): IPriceFormatter;
+ /**
+ * Converts specified series price to pixel coordinate according to the series price scale
+ *
+ * @param price - Input price to be converted
+ * @returns Pixel coordinate of the price level on the chart
+ */
+ priceToCoordinate(price: number): Coordinate | null;
+ /**
+ * Converts specified coordinate to price value according to the series price scale
+ *
+ * @param coordinate - Input coordinate to be converted
+ * @returns Price value of the coordinate on the chart
+ */
+ coordinateToPrice(coordinate: number): BarPrice | null;
+ /**
+ * Returns bars information for the series in the provided [logical range](/time-scale.md#logical-range) or `null`, if no series data has been found in the requested range.
+ * This method can be used, for instance, to implement downloading historical data while scrolling to prevent a user from seeing empty space.
+ *
+ * @param range - The [logical range](/time-scale.md#logical-range) to retrieve info for.
+ * @returns The bars info for the given logical range.
+ * @example Getting bars info for current visible range
+ * ```js
+ * const barsInfo = series.barsInLogicalRange(chart.timeScale().getVisibleLogicalRange());
+ * console.log(barsInfo);
+ * ```
+ * @example Implementing downloading historical data while scrolling
+ * ```js
+ * function onVisibleLogicalRangeChanged(newVisibleLogicalRange) {
+ * const barsInfo = series.barsInLogicalRange(newVisibleLogicalRange);
+ * // if there less than 50 bars to the left of the visible area
+ * if (barsInfo !== null && barsInfo.barsBefore < 50) {
+ * // try to load additional historical data and prepend it to the series data
+ * }
+ * }
+ *
+ * chart.timeScale().subscribeVisibleLogicalRangeChange(onVisibleLogicalRangeChanged);
+ * ```
+ */
+ barsInLogicalRange(range: Range): BarsInfo | null;
+ /**
+ * Applies new options to the existing series
+ * You can set options initially when you create series or use the `applyOptions` method of the series to change the existing options.
+ * Note that you can only pass options you want to change.
+ *
+ * @param options - Any subset of options.
+ */
+ applyOptions(options: TPartialOptions): void;
+ /**
+ * Returns currently applied options
+ *
+ * @returns Full set of currently applied options, including defaults
+ */
+ options(): Readonly;
+ /**
+ * Returns interface of the price scale the series is currently attached
+ *
+ * @returns IPriceScaleApi object to control the price scale
+ */
+ priceScale(): IPriceScaleApi;
+ /**
+ * Sets or replaces series data.
+ *
+ * @param data - Ordered (earlier time point goes first) array of data items. Old data is fully replaced with the new one.
+ * @example Setting data to a line series
+ * ```js
+ * lineSeries.setData([
+ * { time: '2018-12-12', value: 24.11 },
+ * { time: '2018-12-13', value: 31.74 },
+ * ]);
+ * ```
+ * @example Setting data to a bars (or candlestick) series
+ * ```js
+ * barSeries.setData([
+ * { time: '2018-12-19', open: 141.77, high: 170.39, low: 120.25, close: 145.72 },
+ * { time: '2018-12-20', open: 145.72, high: 147.99, low: 100.11, close: 108.19 },
+ * ]);
+ * ```
+ */
+ setData(data: TData[]): void;
+ /**
+ * Adds new data item to the existing set (or updates the latest item if times of the passed/latest items are equal).
+ *
+ * @param bar - A single data item to be added. Time of the new item must be greater or equal to the latest existing time point.
+ * If the new item's time is equal to the last existing item's time, then the existing item is replaced with the new one.
+ * @example Updating line series data
+ * ```js
+ * lineSeries.update({
+ * time: '2018-12-12',
+ * value: 24.11,
+ * });
+ * ```
+ * @example Updating bar (or candlestick) series data
+ * ```js
+ * barSeries.update({
+ * time: '2018-12-19',
+ * open: 141.77,
+ * high: 170.39,
+ * low: 120.25,
+ * close: 145.72,
+ * });
+ * ```
+ */
+ update(bar: TData): void;
+ /**
+ * Returns a bar data by provided logical index.
+ *
+ * @param logicalIndex - Logical index
+ * @param mismatchDirection - Search direction if no data found at provided logical index.
+ * @returns Original data item provided via setData or update methods.
+ * @example
+ * ```js
+ * const originalData = series.dataByIndex(10, LightweightCharts.MismatchDirection.NearestLeft);
+ * ```
+ */
+ dataByIndex(
+ logicalIndex: number,
+ mismatchDirection?: MismatchDirection
+ ): TData | null;
+ /**
+ * Returns all the bar data for the series.
+ *
+ * @returns Original data items provided via setData or update methods.
+ * @example
+ * ```js
+ * const originalData = series.data();
+ * ```
+ */
+ data(): readonly TData[];
+ /**
+ * Subscribe to the data changed event. This event is fired whenever the `update` or `setData` method is evoked
+ * on the series.
+ *
+ * @param handler - Handler to be called on a data changed event.
+ * @example
+ * ```js
+ * function myHandler() {
+ * const data = series.data();
+ * console.log(`The data has changed. New Data length: ${data.length}`);
+ * }
+ *
+ * series.subscribeDataChanged(myHandler);
+ * ```
+ */
+ subscribeDataChanged(handler: DataChangedHandler): void;
+ /**
+ * Unsubscribe a handler that was previously subscribed using {@link subscribeDataChanged}.
+ *
+ * @param handler - Previously subscribed handler
+ * @example
+ * ```js
+ * chart.unsubscribeDataChanged(myHandler);
+ * ```
+ */
+ unsubscribeDataChanged(handler: DataChangedHandler): void;
+ /**
+ * Allows to set/replace all existing series markers with new ones.
+ *
+ * @param data - An array of series markers. This array should be sorted by time. Several markers with same time are allowed.
+ * @example
+ * ```js
+ * series.setMarkers([
+ * {
+ * time: '2019-04-09',
+ * position: 'aboveBar',
+ * color: 'black',
+ * shape: 'arrowDown',
+ * },
+ * {
+ * time: '2019-05-31',
+ * position: 'belowBar',
+ * color: 'red',
+ * shape: 'arrowUp',
+ * id: 'id3',
+ * },
+ * {
+ * time: '2019-05-31',
+ * position: 'belowBar',
+ * color: 'orange',
+ * shape: 'arrowUp',
+ * id: 'id4',
+ * text: 'example',
+ * size: 2,
+ * },
+ * ]);
+ *
+ * chart.subscribeCrosshairMove(param => {
+ * console.log(param.hoveredObjectId);
+ * });
+ *
+ * chart.subscribeClick(param => {
+ * console.log(param.hoveredObjectId);
+ * });
+ * ```
+ */
+ setMarkers(data: SeriesMarker[]): void;
+ /**
+ * Returns an array of series markers.
+ */
+ markers(): SeriesMarker[];
+ /**
+ * Creates a new price line
+ *
+ * @param options - Any subset of options, however `price` is required.
+ * @example
+ * ```js
+ * const priceLine = series.createPriceLine({
+ * price: 80.0,
+ * color: 'green',
+ * lineWidth: 2,
+ * lineStyle: LightweightCharts.LineStyle.Dotted,
+ * axisLabelVisible: true,
+ * title: 'P/L 500',
+ * });
+ * ```
+ */
+ createPriceLine(options: CreatePriceLineOptions): IPriceLine;
+ /**
+ * Removes the price line that was created before.
+ *
+ * @param line - A line to remove.
+ * @example
+ * ```js
+ * const priceLine = series.createPriceLine({ price: 80.0 });
+ * series.removePriceLine(priceLine);
+ * ```
+ */
+ removePriceLine(line: IPriceLine): void;
+ /**
+ * Return current series type.
+ *
+ * @returns Type of the series.
+ * @example
+ * ```js
+ * const lineSeries = chart.addLineSeries();
+ * console.log(lineSeries.seriesType()); // "Line"
+ *
+ * const candlestickSeries = chart.addCandlestickSeries();
+ * console.log(candlestickSeries.seriesType()); // "Candlestick"
+ * ```
+ */
+ seriesType(): TSeriesType;
+ /**
+ * Attaches additional drawing primitive to the series
+ *
+ * @param primitive - any implementation of ISeriesPrimitive interface
+ */
+ attachPrimitive(primitive: ISeriesPrimitive): void;
+ /**
+ * Detaches additional drawing primitive from the series
+ *
+ * @param primitive - implementation of ISeriesPrimitive interface attached before
+ * Does nothing if specified primitive was not attached
+ */
+ detachPrimitive(primitive: ISeriesPrimitive): void;
+}
+/**
+ * This interface represents a label on the price or time axis
+ */
+export interface ISeriesPrimitiveAxisView {
+ /**
+ * The desired coordinate for the label. Note that the label will be automatically moved to prevent overlapping with other labels. If you would like the label to be drawn at the
+ * exact coordinate under all circumstances then rather use `fixedCoordinate`.
+ * For a price axis the value returned will represent the vertical distance (pixels) from the top. For a time axis the value will represent the horizontal distance from the left.
+ *
+ * @returns coordinate. distance from top for price axis, or distance from left for time axis.
+ */
+ coordinate(): number;
+ /**
+ * fixed coordinate of the label. A label with a fixed coordinate value will always be drawn at the specified coordinate and will appear above any 'unfixed' labels. If you supply
+ * a fixed coordinate then you should return a large negative number for `coordinate` so that the automatic placement of unfixed labels doesn't leave a blank space for this label.
+ * For a price axis the value returned will represent the vertical distance (pixels) from the top. For a time axis the value will represent the horizontal distance from the left.
+ *
+ * @returns coordinate. distance from top for price axis, or distance from left for time axis.
+ */
+ fixedCoordinate?(): number | undefined;
+ /**
+ * @returns text of the label
+ */
+ text(): string;
+ /**
+ * @returns text color of the label
+ */
+ textColor(): string;
+ /**
+ * @returns background color of the label
+ */
+ backColor(): string;
+ /**
+ * @returns whether the label should be visible (default: `true`)
+ */
+ visible?(): boolean;
+ /**
+ * @returns whether the tick mark line should be visible (default: `true`)
+ */
+ tickVisible?(): boolean;
+}
+/**
+ * Base interface for series primitives. It must be implemented to add some external graphics to series
+ */
+export interface ISeriesPrimitiveBase {
+ /**
+ * This method is called when viewport has been changed, so primitive have to recalculate / invalidate its data
+ */
+ updateAllViews?(): void;
+ /**
+ * Returns array of labels to be drawn on the price axis used by the series
+ *
+ * @returns array of objects; each of then must implement ISeriesPrimitiveAxisView interface
+ *
+ * For performance reasons, the lightweight library uses internal caches based on references to arrays
+ * So, this method must return new array if set of views has changed and should try to return the same array if nothing changed
+ */
+ priceAxisViews?(): readonly ISeriesPrimitiveAxisView[];
+ /**
+ * Returns array of labels to be drawn on the time axis
+ *
+ * @returns array of objects; each of then must implement ISeriesPrimitiveAxisView interface
+ *
+ * For performance reasons, the lightweight library uses internal caches based on references to arrays
+ * So, this method must return new array if set of views has changed and should try to return the same array if nothing changed
+ */
+ timeAxisViews?(): readonly ISeriesPrimitiveAxisView[];
+ /**
+ * Returns array of objects representing primitive in the main area of the chart
+ *
+ * @returns array of objects; each of then must implement ISeriesPrimitivePaneView interface
+ *
+ * For performance reasons, the lightweight library uses internal caches based on references to arrays
+ * So, this method must return new array if set of views has changed and should try to return the same array if nothing changed
+ */
+ paneViews?(): readonly ISeriesPrimitivePaneView[];
+ /**
+ * Returns array of objects representing primitive in the price axis area of the chart
+ *
+ * @returns array of objects; each of then must implement ISeriesPrimitivePaneView interface
+ *
+ * For performance reasons, the lightweight library uses internal caches based on references to arrays
+ * So, this method must return new array if set of views has changed and should try to return the same array if nothing changed
+ */
+ priceAxisPaneViews?(): readonly ISeriesPrimitivePaneView[];
+ /**
+ * Returns array of objects representing primitive in the time axis area of the chart
+ *
+ * @returns array of objects; each of then must implement ISeriesPrimitivePaneView interface
+ *
+ * For performance reasons, the lightweight library uses internal caches based on references to arrays
+ * So, this method must return new array if set of views has changed and should try to return the same array if nothing changed
+ */
+ timeAxisPaneViews?(): readonly ISeriesPrimitivePaneView[];
+ /**
+ * Return autoscaleInfo which will be merged with the series base autoscaleInfo. You can use this to expand the autoscale range
+ * to include visual elements drawn outside of the series' current visible price range.
+ *
+ * **Important**: Please note that this method will be evoked very often during scrolling and zooming of the chart, thus it
+ * is recommended that this method is either simple to execute, or makes use of optimisations such as caching to ensure that
+ * the chart remains responsive.
+ *
+ * @param startTimePoint - start time point for the current visible range
+ * @param endTimePoint - end time point for the current visible range
+ * @returns AutoscaleInfo
+ */
+ autoscaleInfo?(
+ startTimePoint: Logical,
+ endTimePoint: Logical
+ ): AutoscaleInfo | null;
+ /**
+ * Attached Lifecycle hook.
+ *
+ * @param param - An object containing useful references for the attached primitive to use.
+ * @returns void
+ */
+ attached?(param: TSeriesAttachedParameters): void;
+ /**
+ * Detached Lifecycle hook.
+ *
+ * @returns void
+ */
+ detached?(): void;
+ /**
+ * Hit test method which will be called by the library when the cursor is moved.
+ * Use this to register object ids being hovered for use within the crosshairMoved
+ * and click events emitted by the chart. Additionally, the hit test result can
+ * specify a preferred cursor type to display for the main chart pane. This method
+ * should return the top most hit for this primitive if more than one object is
+ * being intersected.
+ *
+ * @param x - x Coordinate of mouse event
+ * @param y - y Coordinate of mouse event
+ */
+ hitTest?(x: number, y: number): PrimitiveHoveredItem | null;
+}
+/**
+ * This interface represents rendering some element on the canvas
+ */
+export interface ISeriesPrimitivePaneRenderer {
+ /**
+ * Method to draw main content of the element
+ *
+ * @param target - canvas context to draw on, refer to FancyCanvas library for more details about this class
+ *
+ */
+ draw(target: CanvasRenderingTarget2D): void;
+ /**
+ * Optional method to draw the background.
+ * Some elements could implement this method to draw on the background of the chart.
+ * Usually this is some kind of watermarks or time areas highlighting.
+ *
+ * @param target - canvas context to draw on, refer FancyCanvas library for more details about this class
+ */
+ drawBackground?(target: CanvasRenderingTarget2D): void;
+}
+/**
+ * This interface represents the primitive for one of the pane of the chart (main chart area, time scale, price scale).
+ */
+export interface ISeriesPrimitivePaneView {
+ /**
+ * Defines where in the visual layer stack the renderer should be executed. Default is `'normal'`.
+ *
+ * @returns the desired position in the visual layer stack. @see {@link SeriesPrimitivePaneViewZOrder}
+ */
+ zOrder?(): SeriesPrimitivePaneViewZOrder;
+ /**
+ * This method returns a renderer - special object to draw data
+ *
+ * @returns an renderer object to be used for drawing, or `null` if we have nothing to draw.
+ */
+ renderer(): ISeriesPrimitivePaneRenderer | null;
+}
+/** Interface to chart time scale */
+export interface ITimeScaleApi {
+ /**
+ * Return the distance from the right edge of the time scale to the lastest bar of the series measured in bars.
+ */
+ scrollPosition(): number;
+ /**
+ * Scrolls the chart to the specified position.
+ *
+ * @param position - Target data position
+ * @param animated - Setting this to true makes the chart scrolling smooth and adds animation
+ */
+ scrollToPosition(position: number, animated: boolean): void;
+ /**
+ * Restores default scroll position of the chart. This process is always animated.
+ */
+ scrollToRealTime(): void;
+ /**
+ * Returns current visible time range of the chart.
+ *
+ * Note that this method cannot extrapolate time and will use the only currently existent data.
+ * To get complete information about current visible range, please use {@link getVisibleLogicalRange} and {@link ISeriesApi.barsInLogicalRange}.
+ *
+ * @returns Visible range or null if the chart has no data at all.
+ */
+ getVisibleRange(): Range | null;
+ /**
+ * Sets visible range of data.
+ *
+ * Note that this method cannot extrapolate time and will use the only currently existent data.
+ * Thus, for example, if currently a chart doesn't have data prior `2018-01-01` date and you set visible range with `from` date `2016-01-01`, it will be automatically adjusted to `2018-01-01` (and the same for `to` date).
+ *
+ * But if you can approximate indexes on your own - you could use {@link setVisibleLogicalRange} instead.
+ *
+ * @param range - Target visible range of data.
+ * @example
+ * ```js
+ * chart.timeScale().setVisibleRange({
+ * from: (new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0))).getTime() / 1000,
+ * to: (new Date(Date.UTC(2018, 1, 1, 0, 0, 0, 0))).getTime() / 1000,
+ * });
+ * ```
+ */
+ setVisibleRange(range: Range): void;
+ /**
+ * Returns the current visible [logical range](/time-scale.md#logical-range) of the chart as an object with the first and last time points of the logical range, or returns `null` if the chart has no data.
+ *
+ * @returns Visible range or null if the chart has no data at all.
+ */
+ getVisibleLogicalRange(): LogicalRange | null;
+ /**
+ * Sets visible [logical range](/time-scale.md#logical-range) of data.
+ *
+ * @param range - Target visible logical range of data.
+ * @example
+ * ```js
+ * chart.timeScale().setVisibleLogicalRange({ from: 0, to: Date.now() / 1000 });
+ * ```
+ */
+ setVisibleLogicalRange(range: Range): void;
+ /**
+ * Restores default zoom level and scroll position of the time scale.
+ */
+ resetTimeScale(): void;
+ /**
+ * Automatically calculates the visible range to fit all data from all series.
+ */
+ fitContent(): void;
+ /**
+ * Converts a logical index to local x coordinate.
+ *
+ * @param logical - Logical index needs to be converted
+ * @returns x coordinate of that time or `null` if the chart doesn't have data
+ */
+ logicalToCoordinate(logical: Logical): Coordinate | null;
+ /**
+ * Converts a coordinate to logical index.
+ *
+ * @param x - Coordinate needs to be converted
+ * @returns Logical index that is located on that coordinate or `null` if the chart doesn't have data
+ */
+ coordinateToLogical(x: number): Logical | null;
+ /**
+ * Converts a time to local x coordinate.
+ *
+ * @param time - Time needs to be converted
+ * @returns X coordinate of that time or `null` if no time found on time scale
+ */
+ timeToCoordinate(time: HorzScaleItem): Coordinate | null;
+ /**
+ * Converts a coordinate to time.
+ *
+ * @param x - Coordinate needs to be converted.
+ * @returns Time of a bar that is located on that coordinate or `null` if there are no bars found on that coordinate.
+ */
+ coordinateToTime(x: number): HorzScaleItem | null;
+ /**
+ * Returns a width of the time scale.
+ */
+ width(): number;
+ /**
+ * Returns a height of the time scale.
+ */
+ height(): number;
+ /**
+ * Subscribe to the visible time range change events.
+ *
+ * The argument passed to the handler function is an object with `from` and `to` properties of type {@link Time}, or `null` if there is no visible data.
+ *
+ * @param handler - Handler (function) to be called when the visible indexes change.
+ * @example
+ * ```js
+ * function myVisibleTimeRangeChangeHandler(newVisibleTimeRange) {
+ * if (newVisibleTimeRange === null) {
+ * // handle null
+ * }
+ *
+ * // handle new logical range
+ * }
+ *
+ * chart.timeScale().subscribeVisibleTimeRangeChange(myVisibleTimeRangeChangeHandler);
+ * ```
+ */
+ subscribeVisibleTimeRangeChange(
+ handler: TimeRangeChangeEventHandler
+ ): void;
+ /**
+ * Unsubscribe a handler that was previously subscribed using {@link subscribeVisibleTimeRangeChange}.
+ *
+ * @param handler - Previously subscribed handler
+ * @example
+ * ```js
+ * chart.timeScale().unsubscribeVisibleTimeRangeChange(myVisibleTimeRangeChangeHandler);
+ * ```
+ */
+ unsubscribeVisibleTimeRangeChange(
+ handler: TimeRangeChangeEventHandler
+ ): void;
+ /**
+ * Subscribe to the visible logical range change events.
+ *
+ * The argument passed to the handler function is an object with `from` and `to` properties of type `number`, or `null` if there is no visible data.
+ *
+ * @param handler - Handler (function) to be called when the visible indexes change.
+ * @example
+ * ```js
+ * function myVisibleLogicalRangeChangeHandler(newVisibleLogicalRange) {
+ * if (newVisibleLogicalRange === null) {
+ * // handle null
+ * }
+ *
+ * // handle new logical range
+ * }
+ *
+ * chart.timeScale().subscribeVisibleLogicalRangeChange(myVisibleLogicalRangeChangeHandler);
+ * ```
+ */
+ subscribeVisibleLogicalRangeChange(
+ handler: LogicalRangeChangeEventHandler
+ ): void;
+ /**
+ * Unsubscribe a handler that was previously subscribed using {@link subscribeVisibleLogicalRangeChange}.
+ *
+ * @param handler - Previously subscribed handler
+ * @example
+ * ```js
+ * chart.timeScale().unsubscribeVisibleLogicalRangeChange(myVisibleLogicalRangeChangeHandler);
+ * ```
+ */
+ unsubscribeVisibleLogicalRangeChange(
+ handler: LogicalRangeChangeEventHandler
+ ): void;
+ /**
+ * Adds a subscription to time scale size changes
+ *
+ * @param handler - Handler (function) to be called when the time scale size changes
+ */
+ subscribeSizeChange(handler: SizeChangeEventHandler): void;
+ /**
+ * Removes a subscription to time scale size changes
+ *
+ * @param handler - Previously subscribed handler
+ */
+ unsubscribeSizeChange(handler: SizeChangeEventHandler): void;
+ /**
+ * Applies new options to the time scale.
+ *
+ * @param options - Any subset of options.
+ */
+ applyOptions(options: DeepPartial): void;
+ /**
+ * Returns current options
+ *
+ * @returns Currently applied options
+ */
+ options(): Readonly;
+}
+/**
+ * Represents options for enabling or disabling kinetic scrolling with mouse and touch gestures.
+ */
+export interface KineticScrollOptions {
+ /**
+ * Enable kinetic scroll with touch gestures.
+ *
+ * @defaultValue `true`
+ */
+ touch: boolean;
+ /**
+ * Enable kinetic scroll with the mouse.
+ *
+ * @defaultValue `false`
+ */
+ mouse: boolean;
+}
+/** Represents layout options */
+export interface LayoutOptions {
+ /**
+ * Chart and scales background color.
+ *
+ * @defaultValue `{ type: ColorType.Solid, color: '#FFFFFF' }`
+ */
+ background: Background;
+ /**
+ * Color of text on the scales.
+ *
+ * @defaultValue `'#191919'`
+ */
+ textColor: string;
+ /**
+ * Font size of text on scales in pixels.
+ *
+ * @defaultValue `12`
+ */
+ fontSize: number;
+ /**
+ * Font family of text on the scales.
+ *
+ * @defaultValue `-apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif`
+ */
+ fontFamily: string;
+ /**
+ * Display the TradingView attribution logo on the main chart pane.
+ *
+ * The licence for library specifies that you add the "attribution notice"
+ * from the NOTICE file to your code and a link to https://www.tradingview.com/ to
+ * the page of your website or mobile application that is available to your users.
+ * Using this attribution logo is sufficient for meeting this linking requirement.
+ * However, if you already fulfill this requirement then you can disable this
+ * attribution logo.
+ *
+ * @defaultValue true
+ */
+ attributionLogo: boolean;
+}
+/**
+ * Structure describing a single item of data for line series
+ */
+export interface LineData
+ extends SingleValueData {
+ /**
+ * Optional color value for certain data item. If missed, color from options is used
+ */
+ color?: string;
+}
+/**
+ * Represents style options for a line series.
+ */
+export interface LineStyleOptions {
+ /**
+ * Line color.
+ *
+ * @defaultValue `'#2196f3'`
+ */
+ color: string;
+ /**
+ * Line style.
+ *
+ * @defaultValue {@link LineStyle.Solid}
+ */
+ lineStyle: LineStyle;
+ /**
+ * Line width in pixels.
+ *
+ * @defaultValue `3`
+ */
+ lineWidth: LineWidth;
+ /**
+ * Line type.
+ *
+ * @defaultValue {@link LineType.Simple}
+ */
+ lineType: LineType;
+ /**
+ * Show series line.
+ *
+ * @defaultValue `true`
+ */
+ lineVisible: boolean;
+ /**
+ * Show circle markers on each point.
+ *
+ * @defaultValue `false`
+ */
+ pointMarkersVisible: boolean;
+ /**
+ * Circle markers radius in pixels.
+ *
+ * @defaultValue `undefined`
+ */
+ pointMarkersRadius?: number;
+ /**
+ * Show the crosshair marker.
+ *
+ * @defaultValue `true`
+ */
+ crosshairMarkerVisible: boolean;
+ /**
+ * Crosshair marker radius in pixels.
+ *
+ * @defaultValue `4`
+ */
+ crosshairMarkerRadius: number;
+ /**
+ * Crosshair marker border color. An empty string falls back to the color of the series under the crosshair.
+ *
+ * @defaultValue `''`
+ */
+ crosshairMarkerBorderColor: string;
+ /**
+ * The crosshair marker background color. An empty string falls back to the color of the series under the crosshair.
+ *
+ * @defaultValue `''`
+ */
+ crosshairMarkerBackgroundColor: string;
+ /**
+ * Crosshair marker border width in pixels.
+ *
+ * @defaultValue `2`
+ */
+ crosshairMarkerBorderWidth: number;
+ /**
+ * Last price animation mode.
+ *
+ * @defaultValue {@link LastPriceAnimationMode.Disabled}
+ */
+ lastPriceAnimation: LastPriceAnimationMode;
+}
+/**
+ * Represents options for formatting dates, times, and prices according to a locale.
+ */
+export interface LocalizationOptions
+ extends LocalizationOptionsBase {
+ /**
+ * Override formatting of the time scale crosshair label.
+ *
+ * @defaultValue `undefined`
+ */
+ timeFormatter?: TimeFormatterFn;
+ /**
+ * Date formatting string.
+ *
+ * Can contain `yyyy`, `yy`, `MMMM`, `MMM`, `MM` and `dd` literals which will be replaced with corresponding date's value.
+ *
+ * Ignored if {@link timeFormatter} has been specified.
+ *
+ * @defaultValue `'dd MMM \'yy'`
+ */
+ dateFormat: string;
+}
+/**
+ * Represents basic localization options
+ */
+export interface LocalizationOptionsBase {
+ /**
+ * Current locale used to format dates. Uses the browser's language settings by default.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation
+ * @defaultValue `navigator.language`
+ */
+ locale: string;
+ /**
+ * Override formatting of the price scale tick marks, labels and crosshair labels. Can be used for cases that can't be covered with built-in price formats.
+ *
+ * @see {@link PriceFormatCustom}
+ * @defaultValue `undefined`
+ */
+ priceFormatter?: PriceFormatterFn;
+ /**
+ * Override formatting of the percentage scale tick marks, labels and crosshair labels. Can be used for cases that can't be covered with built-in percentage format.
+ *
+ * @defaultValue `undefined`
+ */
+ percentageFormatter?: PercentageFormatterFn;
+}
+/**
+ * Represents a mouse event.
+ */
+export interface MouseEventParams {
+ /**
+ * Time of the data at the location of the mouse event.
+ *
+ * The value will be `undefined` if the location of the event in the chart is outside the range of available data.
+ */
+ time?: HorzScaleItem;
+ /**
+ * Logical index
+ */
+ logical?: Logical;
+ /**
+ * Location of the event in the chart.
+ *
+ * The value will be `undefined` if the event is fired outside the chart, for example a mouse leave event.
+ */
+ point?: Point;
+ /**
+ * Data of all series at the location of the event in the chart.
+ *
+ * Keys of the map are {@link ISeriesApi} instances. Values are prices.
+ * Values of the map are original data items
+ */
+ seriesData: Map<
+ ISeriesApi,
+ | BarData
+ | LineData
+ | HistogramData
+ | CustomData
+ >;
+ /**
+ * The {@link ISeriesApi} for the series at the point of the mouse event.
+ */
+ hoveredSeries?: ISeriesApi;
+ /**
+ * The ID of the object at the point of the mouse event.
+ */
+ hoveredObjectId?: unknown;
+ /**
+ * The underlying source mouse or touch event data, if available
+ */
+ sourceEvent?: TouchMouseEventData;
+}
+/**
+ * Represents a bar with a {@link Time} and open, high, low, and close prices.
+ */
+export interface OhlcData
+ extends WhitespaceData {
+ /**
+ * The bar time.
+ */
+ time: HorzScaleItem;
+ /**
+ * The open price.
+ */
+ open: number;
+ /**
+ * The high price.
+ */
+ high: number;
+ /**
+ * The low price.
+ */
+ low: number;
+ /**
+ * The close price.
+ */
+ close: number;
+}
+/**
+ * Data provide to the custom series pane view which can be used within the renderer
+ * for drawing the series data.
+ */
+export interface PaneRendererCustomData<
+ HorzScaleItem,
+ TData extends CustomData
+> {
+ /**
+ * List of all the series' items and their x coordinates.
+ */
+ bars: readonly CustomBarItemData[];
+ /**
+ * Spacing between consecutive bars.
+ */
+ barSpacing: number;
+ /**
+ * The current visible range of items on the chart.
+ */
+ visibleRange: Range | null;
+}
+/**
+ * Dimensions of the Chart Pane
+ * (the main chart area which excludes the time and price scales).
+ */
+export interface PaneSize {
+ /** Height of the Chart Pane (pixels) */
+ height: number;
+ /** Width of the Chart Pane (pixels) */
+ width: number;
+}
+/**
+ * Represents a point on the chart.
+ */
+export interface Point {
+ /**
+ * The x coordinate.
+ */
+ readonly x: Coordinate;
+ /**
+ * The y coordinate.
+ */
+ readonly y: Coordinate;
+}
+/**
+ * Represents series value formatting options.
+ * The precision and minMove properties allow wide customization of formatting.
+ *
+ * @example
+ * `minMove=0.01`, `precision` is not specified - prices will change like 1.13, 1.14, 1.15 etc.
+ * @example
+ * `minMove=0.01`, `precision=3` - prices will change like 1.130, 1.140, 1.150 etc.
+ * @example
+ * `minMove=0.05`, `precision` is not specified - prices will change like 1.10, 1.15, 1.20 etc.
+ */
+export interface PriceFormatBuiltIn {
+ /**
+ * Built-in price formats:
+ * - `'price'` is the most common choice; it allows customization of precision and rounding of prices.
+ * - `'volume'` uses abbreviation for formatting prices like `1.2K` or `12.67M`.
+ * - `'percent'` uses `%` sign at the end of prices.
+ */
+ type: "price" | "volume" | "percent";
+ /**
+ * Number of digits after the decimal point.
+ * If it is not set, then its value is calculated automatically based on minMove.
+ *
+ * @defaultValue `2` if both {@link minMove} and {@link precision} are not provided, calculated automatically based on {@link minMove} otherwise.
+ */
+ precision: number;
+ /**
+ * The minimum possible step size for price value movement. This value shouldn't have more decimal digits than the precision.
+ *
+ * @defaultValue `0.01`
+ */
+ minMove: number;
+}
+/**
+ * Represents series value formatting options.
+ */
+export interface PriceFormatCustom {
+ /**
+ * The custom price format.
+ */
+ type: "custom";
+ /**
+ * Override price formatting behaviour. Can be used for cases that can't be covered with built-in price formats.
+ */
+ formatter: PriceFormatterFn;
+ /**
+ * The minimum possible step size for price value movement.
+ *
+ * @defaultValue `0.01`
+ */
+ minMove: number;
+}
+/**
+ * Represents a price line options.
+ */
+export interface PriceLineOptions {
+ /**
+ * The optional ID of this price line.
+ */
+ id?: string;
+ /**
+ * Price line's value.
+ *
+ * @defaultValue `0`
+ */
+ price: number;
+ /**
+ * Price line's color.
+ *
+ * @defaultValue `''`
+ */
+ color: string;
+ /**
+ * Price line's width in pixels.
+ *
+ * @defaultValue `1`
+ */
+ lineWidth: LineWidth;
+ /**
+ * Price line's style.
+ *
+ * @defaultValue {@link LineStyle.Solid}
+ */
+ lineStyle: LineStyle;
+ /**
+ * Display line.
+ *
+ * @defaultValue `true`
+ */
+ lineVisible: boolean;
+ /**
+ * Display the current price value in on the price scale.
+ *
+ * @defaultValue `true`
+ */
+ axisLabelVisible: boolean;
+ /**
+ * Price line's on the chart pane.
+ *
+ * @defaultValue `''`
+ */
+ title: string;
+ /**
+ * Background color for the axis label.
+ * Will default to the price line color if unspecified.
+ *
+ * @defaultValue `''`
+ */
+ axisLabelColor: string;
+ /**
+ * Text color for the axis label.
+ *
+ * @defaultValue `''`
+ */
+ axisLabelTextColor: string;
+}
+/**
+ * Represents a price range.
+ */
+export interface PriceRange {
+ /**
+ * Maximum value in the range.
+ */
+ minValue: number;
+ /**
+ * Minimum value in the range.
+ */
+ maxValue: number;
+}
+/** Defines margins of the price scale. */
+export interface PriceScaleMargins {
+ /**
+ * Top margin in percentages. Must be greater or equal to 0 and less than 1.
+ */
+ top: number;
+ /**
+ * Bottom margin in percentages. Must be greater or equal to 0 and less than 1.
+ */
+ bottom: number;
+}
+/** Structure that describes price scale options */
+export interface PriceScaleOptions {
+ /**
+ * Autoscaling is a feature that automatically adjusts a price scale to fit the visible range of data.
+ * Note that overlay price scales are always auto-scaled.
+ *
+ * @defaultValue `true`
+ */
+ autoScale: boolean;
+ /**
+ * Price scale mode.
+ *
+ * @defaultValue {@link PriceScaleMode.Normal}
+ */
+ mode: PriceScaleMode;
+ /**
+ * Invert the price scale, so that a upwards trend is shown as a downwards trend and vice versa.
+ * Affects both the price scale and the data on the chart.
+ *
+ * @defaultValue `false`
+ */
+ invertScale: boolean;
+ /**
+ * Align price scale labels to prevent them from overlapping.
+ *
+ * @defaultValue `true`
+ */
+ alignLabels: boolean;
+ /**
+ * Price scale margins.
+ *
+ * @defaultValue `{ bottom: 0.1, top: 0.2 }`
+ * @example
+ * ```js
+ * chart.priceScale('right').applyOptions({
+ * scaleMargins: {
+ * top: 0.8,
+ * bottom: 0,
+ * },
+ * });
+ * ```
+ */
+ scaleMargins: PriceScaleMargins;
+ /**
+ * Set true to draw a border between the price scale and the chart area.
+ *
+ * @defaultValue `true`
+ */
+ borderVisible: boolean;
+ /**
+ * Price scale border color.
+ *
+ * @defaultValue `'#2B2B43'`
+ */
+ borderColor: string;
+ /**
+ * Price scale text color.
+ * If not provided {@link LayoutOptions.textColor} is used.
+ *
+ * @defaultValue `undefined`
+ */
+ textColor?: string;
+ /**
+ * Show top and bottom corner labels only if entire text is visible.
+ *
+ * @defaultValue `false`
+ */
+ entireTextOnly: boolean;
+ /**
+ * Indicates if this price scale visible. Ignored by overlay price scales.
+ *
+ * @defaultValue `true` for the right price scale and `false` for the left
+ */
+ visible: boolean;
+ /**
+ * Draw small horizontal line on price axis labels.
+ *
+ * @defaultValue `false`
+ */
+ ticksVisible: boolean;
+ /**
+ * Define a minimum width for the price scale.
+ * Note: This value will be exceeded if the
+ * price scale needs more space to display it's contents.
+ *
+ * Setting a minimum width could be useful for ensuring that
+ * multiple charts positioned in a vertical stack each have
+ * an identical price scale width, or for plugins which
+ * require a bit more space within the price scale pane.
+ *
+ * @defaultValue 0
+ */
+ minimumWidth: number;
+}
+/**
+ * Data representing the currently hovered object from the Hit test.
+ */
+export interface PrimitiveHoveredItem {
+ /**
+ * CSS cursor style as defined here: [MDN: CSS Cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) or `undefined`
+ * if you want the library to use the default cursor style instead.
+ */
+ cursorStyle?: string;
+ /**
+ * Hovered objects external ID. Can be used to identify the source item within a mouse subscriber event.
+ */
+ externalId: string;
+ /**
+ * The zOrder of the hovered item.
+ */
+ zOrder: SeriesPrimitivePaneViewZOrder;
+ /**
+ * Set to true if the object is rendered using `drawBackground` instead of `draw`.
+ */
+ isBackground?: boolean;
+}
+/**
+ * Represents a generic range `from` one value `to` another.
+ */
+export interface Range {
+ /**
+ * The from value. The start of the range.
+ */
+ from: T;
+ /**
+ * The to value. The end of the range.
+ */
+ to: T;
+}
+/**
+ * Object containing references to the chart and series instances, and a requestUpdate method for triggering
+ * a refresh of the chart.
+ */
+export interface SeriesAttachedParameter<
+ HorzScaleItem = Time,
+ TSeriesType extends SeriesType = keyof SeriesOptionsMap
+> {
+ /**
+ * Chart instance.
+ */
+ chart: IChartApiBase;
+ /**
+ * Series to which the Primitive is attached.
+ */
+ series: ISeriesApi;
+ /**
+ * Request an update (redraw the chart)
+ */
+ requestUpdate: () => void;
+}
+/**
+ * Represents the type of data that a series contains.
+ *
+ * For example a bar series contains {@link BarData} or {@link WhitespaceData}.
+ */
+export interface SeriesDataItemTypeMap {
+ /**
+ * The types of bar series data.
+ */
+ Bar: BarData | WhitespaceData;
+ /**
+ * The types of candlestick series data.
+ */
+ Candlestick: CandlestickData | WhitespaceData;
+ /**
+ * The types of area series data.
+ */
+ Area: AreaData | WhitespaceData;
+ /**
+ * The types of baseline series data.
+ */
+ Baseline: BaselineData | WhitespaceData;
+ /**
+ * The types of line series data.
+ */
+ Line: LineData | WhitespaceData;
+ /**
+ * The types of histogram series data.
+ */
+ Histogram: HistogramData | WhitespaceData;
+ /**
+ * The base types of an custom series data.
+ */
+ Custom: CustomData | CustomSeriesWhitespaceData;
+}
+/**
+ * Represents a series marker.
+ */
+export interface SeriesMarker {
+ /**
+ * The time of the marker.
+ */
+ time: TimeType;
+ /**
+ * The position of the marker.
+ */
+ position: SeriesMarkerPosition;
+ /**
+ * The shape of the marker.
+ */
+ shape: SeriesMarkerShape;
+ /**
+ * The color of the marker.
+ */
+ color: string;
+ /**
+ * The ID of the marker.
+ */
+ id?: string;
+ /**
+ * The optional text of the marker.
+ */
+ text?: string;
+ /**
+ * The optional size of the marker.
+ *
+ * @defaultValue `1`
+ */
+ size?: number;
+}
+/**
+ * Represents options common for all types of series
+ */
+export interface SeriesOptionsCommon {
+ /**
+ * Visibility of the label with the latest visible price on the price scale.
+ *
+ * @defaultValue `true`
+ */
+ lastValueVisible: boolean;
+ /**
+ * You can name series when adding it to a chart. This name will be displayed on the label next to the last value label.
+ *
+ * @defaultValue `''`
+ */
+ title: string;
+ /**
+ * Target price scale to bind new series to.
+ *
+ * @defaultValue `'right'` if right scale is visible and `'left'` otherwise
+ */
+ priceScaleId?: string;
+ /**
+ * Visibility of the series.
+ * If the series is hidden, everything including price lines, baseline, price labels and markers, will also be hidden.
+ * Please note that hiding a series is not equivalent to deleting it, since hiding does not affect the timeline at all, unlike deleting where the timeline can be changed (some points can be deleted).
+ *
+ * @defaultValue `true`
+ */
+ visible: boolean;
+ /**
+ * Show the price line. Price line is a horizontal line indicating the last price of the series.
+ *
+ * @defaultValue `true`
+ */
+ priceLineVisible: boolean;
+ /**
+ * The source to use for the value of the price line.
+ *
+ * @defaultValue {@link PriceLineSource.LastBar}
+ */
+ priceLineSource: PriceLineSource;
+ /**
+ * Width of the price line.
+ *
+ * @defaultValue `1`
+ */
+ priceLineWidth: LineWidth;
+ /**
+ * Color of the price line.
+ * By default, its color is set by the last bar color (or by line color on Line and Area charts).
+ *
+ * @defaultValue `''`
+ */
+ priceLineColor: string;
+ /**
+ * Price line style.
+ *
+ * @defaultValue {@link LineStyle.Dashed}
+ */
+ priceLineStyle: LineStyle;
+ /**
+ * Price format.
+ *
+ * @defaultValue `{ type: 'price', precision: 2, minMove: 0.01 }`
+ */
+ priceFormat: PriceFormat;
+ /**
+ * Visibility of base line. Suitable for percentage and `IndexedTo100` scales.
+ *
+ * @defaultValue `true`
+ */
+ baseLineVisible: boolean;
+ /**
+ * Color of the base line in `IndexedTo100` mode.
+ *
+ * @defaultValue `'#B2B5BE'`
+ */
+ baseLineColor: string;
+ /**
+ * Base line width. Suitable for percentage and `IndexedTo10` scales.
+ *
+ * @defaultValue `1`
+ */
+ baseLineWidth: LineWidth;
+ /**
+ * Base line style. Suitable for percentage and indexedTo100 scales.
+ *
+ * @defaultValue {@link LineStyle.Solid}
+ */
+ baseLineStyle: LineStyle;
+ /**
+ * Override the default {@link AutoscaleInfo} provider.
+ * By default, the chart scales data automatically based on visible data range.
+ * However, for some reasons one could require overriding this behavior.
+ *
+ * @defaultValue `undefined`
+ * @example Use price range from 0 to 100 regardless the current visible range
+ * ```js
+ * const firstSeries = chart.addLineSeries({
+ * autoscaleInfoProvider: () => ({
+ * priceRange: {
+ * minValue: 0,
+ * maxValue: 100,
+ * },
+ * }),
+ * });
+ * ```
+ * @example Adding a small pixel margins to the price range
+ * ```js
+ * const firstSeries = chart.addLineSeries({
+ * autoscaleInfoProvider: () => ({
+ * priceRange: {
+ * minValue: 0,
+ * maxValue: 100,
+ * },
+ * margins: {
+ * above: 10,
+ * below: 10,
+ * },
+ * }),
+ * });
+ * ```
+ * @example Using the default implementation to adjust the result
+ * ```js
+ * const firstSeries = chart.addLineSeries({
+ * autoscaleInfoProvider: original => {
+ * const res = original();
+ * if (res !== null) {
+ * res.priceRange.minValue -= 10;
+ * res.priceRange.maxValue += 10;
+ * }
+ * return res;
+ * },
+ * });
+ * ```
+ */
+ autoscaleInfoProvider?: AutoscaleInfoProvider;
+}
+/**
+ * Represents the type of options for each series type.
+ *
+ * For example a bar series has options represented by {@link BarSeriesOptions}.
+ */
+export interface SeriesOptionsMap {
+ /**
+ * The type of bar series options.
+ */
+ Bar: BarSeriesOptions;
+ /**
+ * The type of candlestick series options.
+ */
+ Candlestick: CandlestickSeriesOptions;
+ /**
+ * The type of area series options.
+ */
+ Area: AreaSeriesOptions;
+ /**
+ * The type of baseline series options.
+ */
+ Baseline: BaselineSeriesOptions;
+ /**
+ * The type of line series options.
+ */
+ Line: LineSeriesOptions;
+ /**
+ * The type of histogram series options.
+ */
+ Histogram: HistogramSeriesOptions;
+ /**
+ * The type of a custom series options.
+ */
+ Custom: CustomSeriesOptions;
+}
+/**
+ * Represents the type of partial options for each series type.
+ *
+ * For example a bar series has options represented by {@link BarSeriesPartialOptions}.
+ */
+export interface SeriesPartialOptionsMap {
+ /**
+ * The type of bar series partial options.
+ */
+ Bar: BarSeriesPartialOptions;
+ /**
+ * The type of candlestick series partial options.
+ */
+ Candlestick: CandlestickSeriesPartialOptions;
+ /**
+ * The type of area series partial options.
+ */
+ Area: AreaSeriesPartialOptions;
+ /**
+ * The type of baseline series partial options.
+ */
+ Baseline: BaselineSeriesPartialOptions;
+ /**
+ * The type of line series partial options.
+ */
+ Line: LineSeriesPartialOptions;
+ /**
+ * The type of histogram series partial options.
+ */
+ Histogram: HistogramSeriesPartialOptions;
+ /**
+ * The type of a custom series partial options.
+ */
+ Custom: CustomSeriesPartialOptions;
+}
+/**
+ * A base interface for a data point of single-value series.
+ */
+export interface SingleValueData
+ extends WhitespaceData {
+ /**
+ * The time of the data.
+ */
+ time: HorzScaleItem;
+ /**
+ * Price value of the data.
+ */
+ value: number;
+}
+/**
+ * Represents a solid color.
+ */
+export interface SolidColor {
+ /**
+ * Type of color.
+ */
+ type: ColorType.Solid;
+ /**
+ * Color.
+ */
+ color: string;
+}
+/**
+ * Tick mark for the horizontal scale.
+ */
+export interface TickMark {
+ /** Index */
+ index: TimePointIndex;
+ /** Time / Coordinate */
+ time: InternalHorzScaleItem;
+ /** Weight of the tick mark */
+ weight: TickMarkWeightValue;
+ /** Original value for the `time` property */
+ originalTime: unknown;
+}
+/**
+ * Options for chart with time at the horizontal scale
+ */
+export interface TimeChartOptions extends ChartOptionsImpl {
+ /**
+ * Extended time scale options with option to override tickMarkFormatter
+ */
+ timeScale: TimeScaleOptions;
+}
+/**
+ * Represents a tick mark on the horizontal (time) scale.
+ */
+export interface TimeMark {
+ /** Does time mark need to be aligned */
+ needAlignCoordinate: boolean;
+ /** Coordinate for the time mark */
+ coord: number;
+ /** Display label for the time mark */
+ label: string;
+ /** Weight of the time mark */
+ weight: TickMarkWeightValue;
+}
+/**
+ * Extended time scale options for time-based horizontal scale
+ */
+export interface TimeScaleOptions extends HorzScaleOptions {
+ /**
+ * Tick marks formatter can be used to customize tick marks labels on the time axis.
+ *
+ * @defaultValue `undefined`
+ */
+ tickMarkFormatter?: TickMarkFormatter;
+}
+/**
+ * Represents a point on the time scale
+ */
+export interface TimeScalePoint {
+ /** Weight of the point */
+ readonly timeWeight: TickMarkWeightValue;
+ /** Time of the point */
+ readonly time: InternalHorzScaleItem;
+ /** Original time for the point */
+ readonly originalTime: unknown;
+}
+/**
+ * The TouchMouseEventData interface represents events that occur due to the user interacting with a
+ * pointing device (such as a mouse).
+ * See {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent | MouseEvent}
+ */
+export interface TouchMouseEventData {
+ /**
+ * The X coordinate of the mouse pointer in local (DOM content) coordinates.
+ */
+ readonly clientX: Coordinate;
+ /**
+ * The Y coordinate of the mouse pointer in local (DOM content) coordinates.
+ */
+ readonly clientY: Coordinate;
+ /**
+ * The X coordinate of the mouse pointer relative to the whole document.
+ */
+ readonly pageX: Coordinate;
+ /**
+ * The Y coordinate of the mouse pointer relative to the whole document.
+ */
+ readonly pageY: Coordinate;
+ /**
+ * The X coordinate of the mouse pointer in global (screen) coordinates.
+ */
+ readonly screenX: Coordinate;
+ /**
+ * The Y coordinate of the mouse pointer in global (screen) coordinates.
+ */
+ readonly screenY: Coordinate;
+ /**
+ * The X coordinate of the mouse pointer relative to the chart / price axis / time axis canvas element.
+ */
+ readonly localX: Coordinate;
+ /**
+ * The Y coordinate of the mouse pointer relative to the chart / price axis / time axis canvas element.
+ */
+ readonly localY: Coordinate;
+ /**
+ * Returns a boolean value that is true if the Ctrl key was active when the key event was generated.
+ */
+ readonly ctrlKey: boolean;
+ /**
+ * Returns a boolean value that is true if the Alt (Option or ⌥ on macOS) key was active when the
+ * key event was generated.
+ */
+ readonly altKey: boolean;
+ /**
+ * Returns a boolean value that is true if the Shift key was active when the key event was generated.
+ */
+ readonly shiftKey: boolean;
+ /**
+ * Returns a boolean value that is true if the Meta key (on Mac keyboards, the ⌘ Command key; on
+ * Windows keyboards, the Windows key (⊞)) was active when the key event was generated.
+ */
+ readonly metaKey: boolean;
+}
+/**
+ * Represent options for the tracking mode's behavior.
+ *
+ * Mobile users will not have the ability to see the values/dates like they do on desktop.
+ * To see it, they should enter the tracking mode. The tracking mode will deactivate the scrolling
+ * and make it possible to check values and dates.
+ */
+export interface TrackingModeOptions {
+ /** @inheritDoc TrackingModeExitMode
+ *
+ * @defaultValue {@link TrackingModeExitMode.OnNextTap}
+ */
+ exitMode: TrackingModeExitMode;
+}
+/**
+ * Represents a vertical gradient of two colors.
+ */
+export interface VerticalGradientColor {
+ /**
+ * Type of color.
+ */
+ type: ColorType.VerticalGradient;
+ /**
+ * Top color
+ */
+ topColor: string;
+ /**
+ * Bottom color
+ */
+ bottomColor: string;
+}
+/** Watermark options. */
+export interface WatermarkOptions {
+ /**
+ * Watermark color.
+ *
+ * @defaultValue `'rgba(0, 0, 0, 0)'`
+ */
+ color: string;
+ /**
+ * Display the watermark.
+ *
+ * @defaultValue `false`
+ */
+ visible: boolean;
+ /**
+ * Text of the watermark. Word wrapping is not supported.
+ *
+ * @defaultValue `''`
+ */
+ text: string;
+ /**
+ * Font size in pixels.
+ *
+ * @defaultValue `48`
+ */
+ fontSize: number;
+ /**
+ * Font family.
+ *
+ * @defaultValue `-apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif`
+ */
+ fontFamily: string;
+ /**
+ * Font style.
+ *
+ * @defaultValue `''`
+ */
+ fontStyle: string;
+ /**
+ * Horizontal alignment inside the chart area.
+ *
+ * @defaultValue `'center'`
+ */
+ horzAlign: HorzAlign;
+ /**
+ * Vertical alignment inside the chart area.
+ *
+ * @defaultValue `'center'`
+ */
+ vertAlign: VertAlign;
+}
+/**
+ * Represents a whitespace data item, which is a data point without a value.
+ *
+ * @example
+ * ```js
+ * const data = [
+ * { time: '2018-12-03', value: 27.02 },
+ * { time: '2018-12-04' }, // whitespace
+ * { time: '2018-12-05' }, // whitespace
+ * { time: '2018-12-06' }, // whitespace
+ * { time: '2018-12-07' }, // whitespace
+ * { time: '2018-12-08', value: 23.92 },
+ * { time: '2018-12-13', value: 30.74 },
+ * ];
+ * ```
+ */
+export interface WhitespaceData {
+ /**
+ * The time of the data.
+ */
+ time: HorzScaleItem;
+ /**
+ * Additional custom values which will be ignored by the library, but
+ * could be used by plugins.
+ */
+ customValues?: Record;
+}
+/**
+ * Represents area series options.
+ */
+export type AreaSeriesOptions = SeriesOptions;
+/**
+ * Represents area series options where all properties are optional.
+ */
+export type AreaSeriesPartialOptions = SeriesPartialOptions;
+/**
+ * A custom function used to get autoscale information.
+ *
+ * @param baseImplementation - The default implementation of autoscale algorithm, you can use it to adjust the result.
+ */
+export type AutoscaleInfoProvider = (
+ baseImplementation: () => AutoscaleInfo | null
+) => AutoscaleInfo | null;
+/**
+ * Represents the background color of the chart.
+ */
+export type Background = SolidColor | VerticalGradientColor;
+/**
+ * Represents a price as a `number`.
+ */
+export type BarPrice = Nominal;
+/**
+ * Represents bar series options.
+ */
+export type BarSeriesOptions = SeriesOptions;
+/**
+ * Represents bar series options where all properties are options.
+ */
+export type BarSeriesPartialOptions = SeriesPartialOptions;
+/**
+ * Represents a type of a base value of baseline series type.
+ */
+export type BaseValueType = BaseValuePrice;
+/**
+ * Structure describing baseline series options.
+ */
+export type BaselineSeriesOptions = SeriesOptions;
+/**
+ * Represents baseline series options where all properties are options.
+ */
+export type BaselineSeriesPartialOptions =
+ SeriesPartialOptions;
+/**
+ * Represents candlestick series options.
+ */
+export type CandlestickSeriesOptions = SeriesOptions;
+/**
+ * Represents candlestick series options where all properties are optional.
+ */
+export type CandlestickSeriesPartialOptions =
+ SeriesPartialOptions;
+/**
+ * Structure describing options of the chart with time points at the horizontal scale. Series options are to be set separately
+ */
+export type ChartOptions = TimeChartOptions;
+/**
+ * Represents a coordiate as a `number`.
+ */
+export type Coordinate = Nominal;
+/**
+ * Price line options for the {@link ISeriesApi.createPriceLine} method.
+ *
+ * `price` is required, while the rest of the options are optional.
+ */
+export type CreatePriceLineOptions = Partial &
+ Pick;
+/**
+ * Represents a custom series options.
+ */
+export type CustomSeriesOptions = SeriesOptions;
+/**
+ * Represents a custom series options where all properties are optional.
+ */
+export type CustomSeriesPartialOptions =
+ SeriesPartialOptions;
+/**
+ * Price values for the custom series. This list should include the largest, smallest, and current price values for the data point.
+ * The last value in the array will be used for the current value. You shouldn't need to
+ * have more than 3 values in this array since the library only needs a largest, smallest, and current value.
+ *
+ * Examples:
+ * - For a line series, this would contain a single number representing the current value.
+ * - For a candle series, this would contain the high, low, and close values. Where the last value would be the close value.
+ */
+export type CustomSeriesPricePlotValues = number[];
+/**
+ * A custom function use to handle data changed events.
+ */
+export type DataChangedHandler = (scope: DataChangedScope) => void;
+/**
+ * The extent of the data change.
+ */
+export type DataChangedScope = "full" | "update";
+/**
+ * Represents the type of data that a series contains.
+ */
+export type DataItem =
+ SeriesDataItemTypeMap[SeriesType];
+/**
+ * Represents a type `T` where every property is optional.
+ */
+export type DeepPartial = {
+ [P in keyof T]?: T[P] extends (infer U)[]
+ ? DeepPartial[]
+ : T[P] extends readonly (infer X)[]
+ ? readonly DeepPartial[]
+ : DeepPartial;
+};
+/**
+ * Represents histogram series options.
+ */
+export type HistogramSeriesOptions = SeriesOptions;
+/**
+ * Represents histogram series options where all properties are optional.
+ */
+export type HistogramSeriesPartialOptions =
+ SeriesPartialOptions;
+/**
+ * Represents a horizontal alignment.
+ */
+export type HorzAlign = "left" | "center" | "right";
+/**
+ * Function for converting a horizontal scale item to an internal item.
+ */
+export type HorzScaleItemConverterToInternalObj = (
+ time: HorzScaleItem
+) => InternalHorzScaleItem;
+/**
+ * Interface for series primitives. It must be implemented to add some external graphics to series.
+ */
+export type ISeriesPrimitive = ISeriesPrimitiveBase<
+ SeriesAttachedParameter
+>;
+/**
+ * Internal Horizontal Scale Item
+ */
+export type InternalHorzScaleItem = Nominal;
+/**
+ * Index key for a horizontal scale item.
+ */
+export type InternalHorzScaleItemKey = Nominal<
+ number,
+ "InternalHorzScaleItemKey"
+>;
+/**
+ * Represents line series options.
+ */
+export type LineSeriesOptions = SeriesOptions;
+/**
+ * Represents line series options where all properties are optional.
+ */
+export type LineSeriesPartialOptions = SeriesPartialOptions;
+/**
+ * Represents the width of a line.
+ */
+export type LineWidth = 1 | 2 | 3 | 4;
+/**
+ * Represents the `to` or `from` number in a logical range.
+ */
+export type Logical = Nominal;
+/**
+ * A logical range is an object with 2 properties: `from` and `to`, which are numbers and represent logical indexes on the time scale.
+ *
+ * The starting point of the time scale's logical range is the first data item among all series.
+ * Before that point all indexes are negative, starting from that point - positive.
+ *
+ * Indexes might have fractional parts, for instance 4.2, due to the time-scale being continuous rather than discrete.
+ *
+ * Integer part of the logical index means index of the fully visible bar.
+ * Thus, if we have 5.2 as the last visible logical index (`to` field), that means that the last visible bar has index 5, but we also have partially visible (for 20%) 6th bar.
+ * Half (e.g. 1.5, 3.5, 10.5) means exactly a middle of the bar.
+ */
+export type LogicalRange = Range;
+/**
+ * A custom function used to handle changes to the time scale's logical range.
+ */
+export type LogicalRangeChangeEventHandler = (
+ logicalRange: LogicalRange | null
+) => void;
+/**
+ * A custom function use to handle mouse events.
+ */
+export type MouseEventHandler = (
+ param: MouseEventParams
+) => void;
+/**
+ * Removes "readonly" from all properties
+ */
+export type Mutable = {
+ -readonly [P in keyof T]: T[P];
+};
+/**
+ * This is the generic type useful for declaring a nominal type,
+ * which does not structurally matches with the base type and
+ * the other types declared over the same base type
+ *
+ * @example
+ * ```ts
+ * type Index = Nominal;
+ * // let i: Index = 42; // this fails to compile
+ * let i: Index = 42 as Index; // OK
+ * ```
+ * @example
+ * ```ts
+ * type TagName = Nominal;
+ * ```
+ */
+export type Nominal = T & {
+ /** The 'name' or species of the nominal. */
+ [Symbol.species]: Name;
+};
+/**
+ * Represents overlay price scale options.
+ */
+export type OverlayPriceScaleOptions = Omit<
+ PriceScaleOptions,
+ "visible" | "autoScale"
+>;
+/**
+ * A function used to format a percentage value as a string.
+ */
+export type PercentageFormatterFn = (percentageValue: number) => string;
+/**
+ * Represents information used to format prices.
+ */
+export type PriceFormat = PriceFormatBuiltIn | PriceFormatCustom;
+/**
+ * A function used to format a {@link BarPrice} as a string.
+ */
+export type PriceFormatterFn = (priceValue: BarPrice) => string;
+/**
+ * Converter function for changing prices into vertical coordinate values.
+ *
+ * This is provided as a convenience function since the series original data will most likely be defined
+ * in price values, and the renderer needs to draw with coordinates. This returns the same values as
+ * directly using the series' priceToCoordinate method.
+ */
+export type PriceToCoordinateConverter = (price: number) => Coordinate | null;
+/**
+ * Represents the position of a series marker relative to a bar.
+ */
+export type SeriesMarkerPosition = "aboveBar" | "belowBar" | "inBar";
+/**
+ * Represents the shape of a series marker.
+ */
+export type SeriesMarkerShape = "circle" | "square" | "arrowUp" | "arrowDown";
+/**
+ * Represents the intersection of a series type `T`'s options and common series options.
+ *
+ * @see {@link SeriesOptionsCommon} for common options.
+ */
+export type SeriesOptions = T & SeriesOptionsCommon;
+/**
+ * Represents a {@link SeriesOptions} where every property is optional.
+ */
+export type SeriesPartialOptions = DeepPartial;
+/**
+ * Defines where in the visual layer stack the renderer should be executed.
+ *
+ * - `bottom`: Draw below everything except the background.
+ * - `normal`: Draw at the same level as the series.
+ * - `top`: Draw above everything (including the crosshair).
+ */
+export type SeriesPrimitivePaneViewZOrder = "bottom" | "normal" | "top";
+/**
+ * Represents a type of series.
+ *
+ * @see {@link SeriesOptionsMap}
+ */
+export type SeriesType = keyof SeriesOptionsMap;
+/**
+ * A custom function used to handle changes to the time scale's size.
+ */
+export type SizeChangeEventHandler = (width: number, height: number) => void;
+/**
+ * The `TickMarkFormatter` is used to customize tick mark labels on the time scale.
+ *
+ * This function should return `time` as a string formatted according to `tickMarkType` type (year, month, etc) and `locale`.
+ *
+ * Note that the returned string should be the shortest possible value and should have no more than 8 characters.
+ * Otherwise, the tick marks will overlap each other.
+ *
+ * If the formatter function returns `null` then the default tick mark formatter will be used as a fallback.
+ *
+ * @example
+ * ```js
+ * const customFormatter = (time, tickMarkType, locale) => {
+ * // your code here
+ * };
+ * ```
+ */
+export type TickMarkFormatter = (
+ time: Time,
+ tickMarkType: TickMarkType,
+ locale: string
+) => string | null;
+/**
+ * Weight of the tick mark. @see TickMarkWeight enum
+ */
+export type TickMarkWeightValue = Nominal;
+/**
+ * The Time type is used to represent the time of data items.
+ *
+ * Values can be a {@link UTCTimestamp}, a {@link BusinessDay}, or a business day string in ISO format.
+ *
+ * @example
+ * ```js
+ * const timestamp = 1529899200; // Literal timestamp representing 2018-06-25T04:00:00.000Z
+ * const businessDay = { year: 2019, month: 6, day: 1 }; // June 1, 2019
+ * const businessDayString = '2021-02-03'; // Business day string literal
+ * ```
+ */
+export type Time = UTCTimestamp | BusinessDay | string;
+/**
+ * A custom function used to override formatting of a time to a string.
+ */
+export type TimeFormatterFn = (
+ time: HorzScaleItem
+) => string;
+/**
+ * Index for a point on the horizontal (time) scale.
+ */
+export type TimePointIndex = Nominal;
+/**
+ * A custom function used to handle changes to the time scale's time range.
+ */
+export type TimeRangeChangeEventHandler = (
+ timeRange: Range | null
+) => void;
+/**
+ * Represents a time as a UNIX timestamp.
+ *
+ * If your chart displays an intraday interval you should use a UNIX Timestamp.
+ *
+ * Note that JavaScript Date APIs like `Date.now` return a number of milliseconds but UTCTimestamp expects a number of seconds.
+ *
+ * Note that to prevent errors, you should cast the numeric type of the time to `UTCTimestamp` type from the package (`value as UTCTimestamp`) in TypeScript code.
+ *
+ * @example
+ * ```ts
+ * const timestamp = 1529899200 as UTCTimestamp; // Literal timestamp representing 2018-06-25T04:00:00.000Z
+ * const timestamp2 = (Date.now() / 1000) as UTCTimestamp;
+ * ```
+ */
+export type UTCTimestamp = Nominal;
+/**
+ * Represents a vertical alignment.
+ */
+export type VertAlign = "top" | "center" | "bottom";
+/**
+ * Represents a visible price scale's options.
+ *
+ * @see {@link PriceScaleOptions}
+ */
+export type VisiblePriceScaleOptions = PriceScaleOptions;
+
+export {};
diff --git a/app-html/libraries/uFuzzy/uFuzzy.d.ts b/app-html/libraries/uFuzzy/uFuzzy.d.ts
new file mode 100644
index 000000000..9b8160af8
--- /dev/null
+++ b/app-html/libraries/uFuzzy/uFuzzy.d.ts
@@ -0,0 +1,196 @@
+declare class uFuzzy {
+ constructor(opts?: uFuzzy.Options);
+
+ /** search API composed of filter/info/sort, with a info/ranking threshold (1e3) and fast outOfOrder impl */
+ search(
+ haystack: string[],
+ needle: string,
+ /** limit how many terms will be permuted, default = 0; 5 will result in up to 5! (120) search iterations. be careful with this! */
+ outOfOrder?: number,
+ /** default = 1e3 */
+ infoThresh?: number,
+ preFiltered?: uFuzzy.HaystackIdxs | null
+ ): uFuzzy.SearchResult;
+
+ /** initial haystack filter, can accept idxs from previous prefix/typeahead match as optimization */
+ filter(
+ haystack: string[],
+ needle: string,
+ idxs?: uFuzzy.HaystackIdxs
+ ): uFuzzy.HaystackIdxs | null;
+
+ /** collects stats about pre-filtered matches, does additional filtering based on term boundary settings, finds highlight ranges */
+ info(
+ idxs: uFuzzy.HaystackIdxs,
+ haystack: string[],
+ needle: string
+ ): uFuzzy.Info;
+
+ /** performs final result sorting via Array.sort(), relying on Info */
+ sort(
+ info: uFuzzy.Info,
+ haystack: string[],
+ needle: string
+ ): uFuzzy.InfoIdxOrder;
+
+ /** utility for splitting needle into terms following defined interSplit/intraSplit opts. useful for out-of-order permutes */
+ split(needle: string): uFuzzy.Terms;
+
+ /** util for creating out-of-order permutations of a needle terms array */
+ static permute(arr: unknown[]): unknown[][];
+
+ /** util for replacing common diacritics/accents */
+ static latinize(strings: T): T;
+
+ /** util for highlighting matched substr parts of a result */
+ static highlight(
+ match: string,
+ ranges: number[],
+
+ mark?: (part: string, matched: boolean) => TMarkedPart,
+ accum?: TAccum,
+ append?: (accum: TAccum, part: TMarkedPart) => TAccum | undefined
+ ): TAccum;
+}
+
+export = uFuzzy;
+
+declare namespace uFuzzy {
+ /** needle's terms */
+ export type Terms = string[];
+
+ /** subset of idxs of a haystack array */
+ export type HaystackIdxs = number[];
+
+ /** sorted order in which info facets should be iterated */
+ export type InfoIdxOrder = number[];
+
+ export type AbortedResult = [null, null, null];
+
+ export type FilteredResult = [uFuzzy.HaystackIdxs, null, null];
+
+ export type RankedResult = [
+ uFuzzy.HaystackIdxs,
+ uFuzzy.Info,
+ uFuzzy.InfoIdxOrder
+ ];
+
+ export type SearchResult = FilteredResult | RankedResult | AbortedResult;
+
+ /** partial RegExp */
+ type PartialRegExp = string;
+
+ /** what should be considered acceptable term bounds */
+ export const enum BoundMode {
+ /** will match 'man' substr anywhere. e.g. tasmania */
+ Any = 0,
+ /** will match 'man' at whitespace, punct, case-change, and alpha-num boundaries. e.g. mantis, SuperMan, fooManBar, 0007man */
+ Loose = 1,
+ /** will match 'man' at whitespace, punct boundaries only. e.g. mega man, walk_man, man-made, foo.man.bar */
+ Strict = 2,
+ }
+
+ export const enum IntraMode {
+ /** allows any number of extra char insertions within a term, but all term chars must be present for a match */
+ MultiInsert = 0,
+ /** allows for a single-char substitution, transposition, insertion, or deletion within terms (excluding first and last chars) */
+ SingleError = 1,
+ }
+
+ export type IntraSliceIdxs = [from: number, to: number];
+
+ export interface Options {
+ // whether regexps use a /u unicode flag
+ unicode?: boolean; // false
+
+ /** @deprecated renamed to opts.alpha */
+ letters?: PartialRegExp | null; // a-z
+
+ // regexp character class [] of chars which should be treated as letters (case insensitive)
+ alpha?: PartialRegExp | null; // a-z
+
+ /** term segmentation & punct/whitespace merging */
+ interSplit?: PartialRegExp; // '[^A-Za-z\\d']+'
+ intraSplit?: PartialRegExp | null; // '[a-z][A-Z]'
+
+ /** inter bounds that will be used to increase lft2/rgt2 info counters */
+ interBound?: PartialRegExp | null; // '[^A-Za-z\\d]'
+ /** intra bounds that will be used to increase lft1/rgt1 info counters */
+ intraBound?: PartialRegExp | null; // '[A-Za-z][0-9]|[0-9][A-Za-z]|[a-z][A-Z]'
+
+ /** inter-term modes, during .info() can discard matches when bounds conditions are not met */
+ interLft?: BoundMode; // 0
+ interRgt?: BoundMode; // 0
+
+ /** allowance between terms */
+ interChars?: PartialRegExp; // '.'
+ interIns?: number; // Infinity
+
+ /** allowance between chars within terms */
+ intraChars?: PartialRegExp; // '[a-z\\d]'
+ intraIns?: number; // 0
+
+ /** contractions detection */
+ intraContr?: PartialRegExp; // "'[a-z]{1,2}\\b"
+
+ /** error tolerance mode within terms. will clamp intraIns to 1 when set to SingleError */
+ intraMode?: IntraMode; // 0
+
+ /** which part of each term should tolerate errors (when intraMode: 1) */
+ intraSlice?: IntraSliceIdxs; // [1, Infinity]
+
+ /** max substitutions (when intraMode: 1) */
+ intraSub?: 0 | 1; // 0
+ /** max transpositions (when intraMode: 1) */
+ intraTrn?: 0 | 1; // 0
+ /** max omissions/deletions (when intraMode: 1) */
+ intraDel?: 0 | 1; // 0
+
+ /** can dynamically adjust error tolerance rules per term in needle (when intraMode: 1) */
+ intraRules?: (term: string) => {
+ intraSlice?: IntraSliceIdxs;
+ intraIns: 0 | 1;
+ intraSub: 0 | 1;
+ intraTrn: 0 | 1;
+ intraDel: 0 | 1;
+ };
+
+ /** post-filters matches during .info() based on cmp of term in needle vs partial match */
+ intraFilt?: (term: string, match: string, index: number) => boolean; // should this also accept WIP info?
+
+ sort?: (info: Info, haystack: string[], needle: string) => InfoIdxOrder;
+ }
+
+ export interface Info {
+ /** matched idxs from haystack */
+ idx: HaystackIdxs;
+
+ /** match offsets */
+ start: number[];
+
+ /** number of left BoundMode.Strict term boundaries found */
+ interLft2: number[];
+ /** number of right BoundMode.Strict term boundaries found */
+ interRgt2: number[];
+ /** number of left BoundMode.Loose term boundaries found */
+ interLft1: number[];
+ /** number of right BoundMode.Loose term boundaries found */
+ interRgt1: number[];
+
+ /** total number of extra chars matched within all terms. higher = matched terms have more fuzz in them */
+ intraIns: number[];
+ /** total number of chars found in between matched terms. higher = terms are more sparse, have more fuzz in between them */
+ interIns: number[];
+
+ /** total number of matched contiguous chars (substrs but not necessarily full terms) */
+ chars: number[];
+
+ /** number of exactly-matched terms (intra = 0) where both lft and rgt landed on a BoundMode.Loose or BoundMode.Strict boundary */
+ terms: number[];
+
+ /** offset ranges within match for highlighting: [startIdx0, endIdx0, startIdx1, endIdx1,...] */
+ ranges: number[][];
+ }
+}
+
+export as namespace uFuzzy;
diff --git a/app-html/libraries/uFuzzy/uFuzzy.esm.js b/app-html/libraries/uFuzzy/uFuzzy.esm.js
new file mode 100644
index 000000000..7412c76ac
--- /dev/null
+++ b/app-html/libraries/uFuzzy/uFuzzy.esm.js
@@ -0,0 +1,1053 @@
+// @ts-nocheck
+
+/**
+ * Copyright (c) 2024, Leon Sorokin
+ * All rights reserved. (MIT Licensed)
+ *
+ * uFuzzy.js (μFuzzy)
+ * A tiny, efficient fuzzy matcher that doesn't suck
+ * https://github.com/leeoniya/uFuzzy (v1.0.14)
+ */
+
+const cmp = new Intl.Collator("en", { numeric: true, sensitivity: "base" })
+ .compare;
+
+const inf = Infinity;
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping
+const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+
+// meh, magic tmp placeholder, must be tolerant to toLocaleLowerCase(), interSplit, and intraSplit
+const EXACT_HERE = "eexxaacctt";
+
+const PUNCT_RE = /\p{P}/gu;
+
+const LATIN_UPPER = "A-Z";
+const LATIN_LOWER = "a-z";
+
+const swapAlpha = (str, upper, lower) =>
+ str.replace(LATIN_UPPER, upper).replace(LATIN_LOWER, lower);
+
+const OPTS = {
+ // whether regexps use a /u unicode flag
+ unicode: false,
+
+ alpha: null,
+
+ // term segmentation & punct/whitespace merging
+ interSplit: "[^A-Za-z\\d']+",
+ intraSplit: "[a-z][A-Z]",
+
+ // inter bounds that will be used to increase lft2/rgt2 info counters
+ interBound: "[^A-Za-z\\d]",
+ // intra bounds that will be used to increase lft1/rgt1 info counters
+ intraBound: "[A-Za-z]\\d|\\d[A-Za-z]|[a-z][A-Z]",
+
+ // inter-bounds mode
+ // 2 = strict (will only match 'man' on whitepace and punct boundaries: Mega Man, Mega_Man, mega.man)
+ // 1 = loose (plus allowance for alpha-num and case-change boundaries: MegaMan, 0007man)
+ // 0 = any (will match 'man' as any substring: megamaniac)
+ interLft: 0,
+ interRgt: 0,
+
+ // allowance between terms
+ interChars: ".",
+ interIns: inf,
+
+ // allowance between chars in terms
+ intraChars: "[a-z\\d']", // internally case-insensitive
+ intraIns: null,
+
+ intraContr: "'[a-z]{1,2}\\b",
+
+ // multi-insert or single-error mode
+ intraMode: 0,
+
+ // single-error bounds for errors within terms, default requires exact first char
+ intraSlice: [1, inf],
+
+ // single-error tolerance toggles
+ intraSub: null,
+ intraTrn: null,
+ intraDel: null,
+
+ // can post-filter matches that are too far apart in distance or length
+ // (since intraIns is between each char, it can accum to nonsense matches)
+ intraFilt: (term, match, index) => true, // should this also accept WIP info?
+
+ // final sorting fn
+ sort: (info, haystack, needle) => {
+ let {
+ idx,
+ chars,
+ terms,
+ interLft2,
+ interLft1,
+ // interRgt2,
+ // interRgt1,
+ start,
+ intraIns,
+ interIns,
+ } = info;
+
+ return idx
+ .map((v, i) => i)
+ .sort(
+ (ia, ib) =>
+ // most contig chars matched
+ chars[ib] - chars[ia] ||
+ // least char intra-fuzz (most contiguous)
+ intraIns[ia] - intraIns[ib] ||
+ // most prefix bounds, boosted by full term matches
+ terms[ib] +
+ interLft2[ib] +
+ 0.5 * interLft1[ib] -
+ (terms[ia] + interLft2[ia] + 0.5 * interLft1[ia]) ||
+ // highest density of match (least span)
+ // span[ia] - span[ib] ||
+ // highest density of match (least term inter-fuzz)
+ interIns[ia] - interIns[ib] ||
+ // earliest start of match
+ start[ia] - start[ib] ||
+ // alphabetic
+ cmp(haystack[idx[ia]], haystack[idx[ib]])
+ );
+ },
+};
+
+const lazyRepeat = (chars, limit) =>
+ limit == 0
+ ? ""
+ : limit == 1
+ ? chars + "??"
+ : limit == inf
+ ? chars + "*?"
+ : chars + `{0,${limit}}?`;
+
+const mode2Tpl = "(?:\\b|_)";
+
+function uFuzzy(opts) {
+ opts = Object.assign({}, OPTS, opts);
+
+ let {
+ unicode,
+ interLft,
+ interRgt,
+ intraMode,
+ intraSlice,
+ intraIns,
+ intraSub,
+ intraTrn,
+ intraDel,
+ intraContr,
+ intraSplit: _intraSplit,
+ interSplit: _interSplit,
+ intraBound: _intraBound,
+ interBound: _interBound,
+ intraChars,
+ } = opts;
+
+ intraIns ??= intraMode;
+ intraSub ??= intraMode;
+ intraTrn ??= intraMode;
+ intraDel ??= intraMode;
+
+ let alpha = opts.letters ?? opts.alpha;
+
+ if (alpha != null) {
+ let upper = alpha.toLocaleUpperCase();
+ let lower = alpha.toLocaleLowerCase();
+
+ _interSplit = swapAlpha(_interSplit, upper, lower);
+ _intraSplit = swapAlpha(_intraSplit, upper, lower);
+ _interBound = swapAlpha(_interBound, upper, lower);
+ _intraBound = swapAlpha(_intraBound, upper, lower);
+ intraChars = swapAlpha(intraChars, upper, lower);
+ intraContr = swapAlpha(intraContr, upper, lower);
+ }
+
+ let uFlag = unicode ? "u" : "";
+
+ const quotedAny = '".+?"';
+ const EXACTS_RE = new RegExp(quotedAny, "gi" + uFlag);
+ const NEGS_RE = new RegExp(
+ `(?:\\s+|^)-(?:${intraChars}+|${quotedAny})`,
+ "gi" + uFlag
+ );
+
+ let { intraRules } = opts;
+
+ if (intraRules == null) {
+ intraRules = (p) => {
+ // default is exact term matches only
+ let _intraSlice = OPTS.intraSlice, // requires first char
+ _intraIns = 0,
+ _intraSub = 0,
+ _intraTrn = 0,
+ _intraDel = 0;
+
+ // only-digits strings should match exactly, else special rules for short strings
+ if (/[^\d]/.test(p)) {
+ let plen = p.length;
+
+ // prevent junk matches by requiring stricter rules for short terms
+ if (plen <= 4) {
+ if (plen >= 3) {
+ // one swap in non-first char when 3-4 chars
+ _intraTrn = Math.min(intraTrn, 1);
+
+ // or one insertion when 4 chars
+ if (plen == 4) _intraIns = Math.min(intraIns, 1);
+ }
+ // else exact match when 1-2 chars
+ }
+ // use supplied opts
+ else {
+ _intraSlice = intraSlice;
+ (_intraIns = intraIns),
+ (_intraSub = intraSub),
+ (_intraTrn = intraTrn),
+ (_intraDel = intraDel);
+ }
+ }
+
+ return {
+ intraSlice: _intraSlice,
+ intraIns: _intraIns,
+ intraSub: _intraSub,
+ intraTrn: _intraTrn,
+ intraDel: _intraDel,
+ };
+ };
+ }
+
+ let withIntraSplit = !!_intraSplit;
+
+ let intraSplit = new RegExp(_intraSplit, "g" + uFlag);
+ let interSplit = new RegExp(_interSplit, "g" + uFlag);
+
+ let trimRe = new RegExp(
+ "^" + _interSplit + "|" + _interSplit + "$",
+ "g" + uFlag
+ );
+ let contrsRe = new RegExp(intraContr, "gi" + uFlag);
+
+ const split = (needle) => {
+ let exacts = [];
+
+ needle = needle.replace(EXACTS_RE, (m) => {
+ exacts.push(m);
+ return EXACT_HERE;
+ });
+
+ needle = needle.replace(trimRe, "").toLocaleLowerCase();
+
+ if (withIntraSplit)
+ needle = needle.replace(intraSplit, (m) => m[0] + " " + m[1]);
+
+ let j = 0;
+ return needle
+ .split(interSplit)
+ .filter((t) => t != "")
+ .map((v) => (v === EXACT_HERE ? exacts[j++] : v));
+ };
+
+ const NUM_OR_ALPHA_RE = /[^\d]+|\d+/g;
+
+ const prepQuery = (needle, capt = 0, interOR = false) => {
+ // split on punct, whitespace, num-alpha, and upper-lower boundaries
+ let parts = split(needle);
+
+ if (parts.length == 0) return [];
+
+ // split out any detected contractions for each term that become required suffixes
+ let contrs = Array(parts.length).fill("");
+ parts = parts.map((p, pi) =>
+ p.replace(contrsRe, (m) => {
+ contrs[pi] = m;
+ return "";
+ })
+ );
+
+ // array of regexp tpls for each term
+ let reTpl;
+
+ // allows single mutations within each term
+ if (intraMode == 1) {
+ reTpl = parts.map((p, pi) => {
+ if (p[0] === '"') return escapeRegExp(p.slice(1, -1));
+
+ let reTpl = "";
+
+ // split into numeric and alpha parts, so numbers are only matched as following punct or alpha boundaries, without swaps or insertions
+ for (let m of p.matchAll(NUM_OR_ALPHA_RE)) {
+ let p = m[0];
+
+ let { intraSlice, intraIns, intraSub, intraTrn, intraDel } =
+ intraRules(p);
+
+ if (intraIns + intraSub + intraTrn + intraDel == 0)
+ reTpl += p + contrs[pi];
+ else {
+ let [lftIdx, rgtIdx] = intraSlice;
+ let lftChar = p.slice(0, lftIdx); // prefix
+ let rgtChar = p.slice(rgtIdx); // suffix
+
+ let chars = p.slice(lftIdx, rgtIdx);
+
+ // neg lookahead to prefer matching 'Test' instead of 'tTest' in ManifestTest or fittest
+ // but skip when search term contains leading repetition (aardvark, aaa)
+ if (intraIns == 1 && lftChar.length == 1 && lftChar != chars[0])
+ lftChar += "(?!" + lftChar + ")";
+
+ let numChars = chars.length;
+
+ let variants = [p];
+
+ // variants with single char substitutions
+ if (intraSub) {
+ for (let i = 0; i < numChars; i++)
+ variants.push(
+ lftChar +
+ chars.slice(0, i) +
+ intraChars +
+ chars.slice(i + 1) +
+ rgtChar
+ );
+ }
+
+ // variants with single transpositions
+ if (intraTrn) {
+ for (let i = 0; i < numChars - 1; i++) {
+ if (chars[i] != chars[i + 1])
+ variants.push(
+ lftChar +
+ chars.slice(0, i) +
+ chars[i + 1] +
+ chars[i] +
+ chars.slice(i + 2) +
+ rgtChar
+ );
+ }
+ }
+
+ // variants with single char omissions
+ if (intraDel) {
+ for (let i = 0; i < numChars; i++)
+ variants.push(
+ lftChar +
+ chars.slice(0, i + 1) +
+ "?" +
+ chars.slice(i + 1) +
+ rgtChar
+ );
+ }
+
+ // variants with single char insertions
+ if (intraIns) {
+ let intraInsTpl = lazyRepeat(intraChars, 1);
+
+ for (let i = 0; i < numChars; i++)
+ variants.push(
+ lftChar +
+ chars.slice(0, i) +
+ intraInsTpl +
+ chars.slice(i) +
+ rgtChar
+ );
+ }
+
+ reTpl += "(?:" + variants.join("|") + ")" + contrs[pi];
+ }
+ }
+
+ // console.log(reTpl);
+
+ return reTpl;
+ });
+ } else {
+ let intraInsTpl = lazyRepeat(intraChars, intraIns);
+
+ // capture at char level
+ if (capt == 2 && intraIns > 0) {
+ // sadly, we also have to capture the inter-term junk via parenth-wrapping .*?
+ // to accum other capture groups' indices for \b boosting during scoring
+ intraInsTpl = ")(" + intraInsTpl + ")(";
+ }
+
+ reTpl = parts.map((p, pi) =>
+ p[0] === '"'
+ ? escapeRegExp(p.slice(1, -1))
+ : p
+ .split("")
+ .map((c, i, chars) => {
+ // neg lookahead to prefer matching 'Test' instead of 'tTest' in ManifestTest or fittest
+ // but skip when search term contains leading repetition (aardvark, aaa)
+ if (
+ intraIns == 1 &&
+ i == 0 &&
+ chars.length > 1 &&
+ c != chars[i + 1]
+ )
+ c += "(?!" + c + ")";
+
+ return c;
+ })
+ .join(intraInsTpl) + contrs[pi]
+ );
+ }
+
+ // console.log(reTpl);
+
+ // this only helps to reduce initial matches early when they can be detected
+ // TODO: might want a mode 3 that excludes _
+ let preTpl = interLft == 2 ? mode2Tpl : "";
+ let sufTpl = interRgt == 2 ? mode2Tpl : "";
+
+ let interCharsTpl =
+ sufTpl + lazyRepeat(opts.interChars, opts.interIns) + preTpl;
+
+ // capture at word level
+ if (capt > 0) {
+ if (interOR) {
+ // this is basically for doing .matchAll() occurence counting and highlighting without needing permuted ooo needles
+ reTpl =
+ preTpl +
+ "(" +
+ reTpl.join(")" + sufTpl + "|" + preTpl + "(") +
+ ")" +
+ sufTpl;
+ } else {
+ // sadly, we also have to capture the inter-term junk via parenth-wrapping .*?
+ // to accum other capture groups' indices for \b boosting during scoring
+ reTpl = "(" + reTpl.join(")(" + interCharsTpl + ")(") + ")";
+ reTpl = "(.??" + preTpl + ")" + reTpl + "(" + sufTpl + ".*)"; // nit: trailing capture here assumes interIns = Inf
+ }
+ } else {
+ reTpl = reTpl.join(interCharsTpl);
+ reTpl = preTpl + reTpl + sufTpl;
+ }
+
+ // console.log(reTpl);
+
+ return [new RegExp(reTpl, "i" + uFlag), parts, contrs];
+ };
+
+ const filter = (haystack, needle, idxs) => {
+ let [query] = prepQuery(needle);
+
+ if (query == null) return null;
+
+ let out = [];
+
+ if (idxs != null) {
+ for (let i = 0; i < idxs.length; i++) {
+ let idx = idxs[i];
+ query.test(haystack[idx]) && out.push(idx);
+ }
+ } else {
+ for (let i = 0; i < haystack.length; i++)
+ query.test(haystack[i]) && out.push(i);
+ }
+
+ return out;
+ };
+
+ let withIntraBound = !!_intraBound;
+
+ let interBound = new RegExp(_interBound, uFlag);
+ let intraBound = new RegExp(_intraBound, uFlag);
+
+ const info = (idxs, haystack, needle) => {
+ let [query, parts, contrs] = prepQuery(needle, 1);
+ let [queryR] = prepQuery(needle, 2);
+ let partsLen = parts.length;
+
+ let len = idxs.length;
+
+ let field = Array(len).fill(0);
+
+ let info = {
+ // idx in haystack
+ idx: Array(len),
+
+ // start of match
+ start: field.slice(),
+ // length of match
+ // span: field.slice(),
+
+ // contiguous chars matched
+ chars: field.slice(),
+
+ // contiguous (no fuzz) and bounded terms (intra=0, lft2/1, rgt2/1)
+ // excludes terms that are contiguous but have < 2 bounds (substrings)
+ terms: field.slice(),
+
+ // cumulative length of unmatched chars (fuzz) within span
+ interIns: field.slice(), // between terms
+ intraIns: field.slice(), // within terms
+
+ // interLft/interRgt counters
+ interLft2: field.slice(),
+ interRgt2: field.slice(),
+ interLft1: field.slice(),
+ interRgt1: field.slice(),
+
+ ranges: Array(len),
+ };
+
+ // might discard idxs based on bounds checks
+ let mayDiscard = interLft == 1 || interRgt == 1;
+
+ let ii = 0;
+
+ for (let i = 0; i < idxs.length; i++) {
+ let mhstr = haystack[idxs[i]];
+
+ // the matched parts are [full, junk, term, junk, term, junk]
+ let m = mhstr.match(query);
+
+ // leading junk
+ let start = m.index + m[1].length;
+
+ let idxAcc = start;
+ // let span = m[0].length;
+
+ let disc = false;
+ let lft2 = 0;
+ let lft1 = 0;
+ let rgt2 = 0;
+ let rgt1 = 0;
+ let chars = 0;
+ let terms = 0;
+ let inter = 0;
+ let intra = 0;
+
+ let refine = [];
+
+ for (let j = 0, k = 2; j < partsLen; j++, k += 2) {
+ let group = m[k].toLocaleLowerCase();
+ let part = parts[j];
+ let term = part[0] == '"' ? part.slice(1, -1) : part + contrs[j];
+ let termLen = term.length;
+ let groupLen = group.length;
+ let fullMatch = group == term;
+
+ // this won't handle the case when an exact match exists across the boundary of the current group and the next junk
+ // e.g. blob,ob when searching for 'bob' but finding the earlier `blob` (with extra insertion)
+ if (!fullMatch && m[k + 1].length >= termLen) {
+ // probe for exact match in inter junk (TODO: maybe even in this matched part?)
+ let idxOf = m[k + 1].toLocaleLowerCase().indexOf(term);
+
+ if (idxOf > -1) {
+ refine.push(idxAcc, groupLen, idxOf, termLen);
+ idxAcc += refineMatch(m, k, idxOf, termLen);
+ group = term;
+ groupLen = termLen;
+ fullMatch = true;
+
+ if (j == 0) start = idxAcc;
+ }
+ }
+
+ if (mayDiscard || fullMatch) {
+ // does group's left and/or right land on \b
+ let lftCharIdx = idxAcc - 1;
+ let rgtCharIdx = idxAcc + groupLen;
+
+ let isPre = false;
+ let isSuf = false;
+
+ // prefix info
+ if (lftCharIdx == -1 || interBound.test(mhstr[lftCharIdx])) {
+ fullMatch && lft2++;
+ isPre = true;
+ } else {
+ if (interLft == 2) {
+ disc = true;
+ break;
+ }
+
+ if (
+ withIntraBound &&
+ intraBound.test(mhstr[lftCharIdx] + mhstr[lftCharIdx + 1])
+ ) {
+ fullMatch && lft1++;
+ isPre = true;
+ } else {
+ if (interLft == 1) {
+ // regexps are eager, so try to improve the match by probing forward inter junk for exact match at a boundary
+ let junk = m[k + 1];
+ let junkIdx = idxAcc + groupLen;
+
+ if (junk.length >= termLen) {
+ let idxOf = 0;
+ let found = false;
+ let re = new RegExp(term, "ig" + uFlag);
+
+ let m2;
+ while ((m2 = re.exec(junk))) {
+ idxOf = m2.index;
+
+ let charIdx = junkIdx + idxOf;
+ let lftCharIdx = charIdx - 1;
+
+ if (
+ lftCharIdx == -1 ||
+ interBound.test(mhstr[lftCharIdx])
+ ) {
+ lft2++;
+ found = true;
+ break;
+ } else if (
+ intraBound.test(mhstr[lftCharIdx] + mhstr[charIdx])
+ ) {
+ lft1++;
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ isPre = true;
+
+ // identical to exact term refinement pass above
+ refine.push(idxAcc, groupLen, idxOf, termLen);
+ idxAcc += refineMatch(m, k, idxOf, termLen);
+ group = term;
+ groupLen = termLen;
+ fullMatch = true;
+
+ if (j == 0) start = idxAcc;
+ }
+ }
+
+ if (!isPre) {
+ disc = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // suffix info
+ if (
+ rgtCharIdx == mhstr.length ||
+ interBound.test(mhstr[rgtCharIdx])
+ ) {
+ fullMatch && rgt2++;
+ isSuf = true;
+ } else {
+ if (interRgt == 2) {
+ disc = true;
+ break;
+ }
+
+ if (
+ withIntraBound &&
+ intraBound.test(mhstr[rgtCharIdx - 1] + mhstr[rgtCharIdx])
+ ) {
+ fullMatch && rgt1++;
+ isSuf = true;
+ } else {
+ if (interRgt == 1) {
+ disc = true;
+ break;
+ }
+ }
+ }
+
+ if (fullMatch) {
+ chars += termLen;
+
+ if (isPre && isSuf) terms++;
+ }
+ }
+
+ if (groupLen > termLen) intra += groupLen - termLen; // intraFuzz
+
+ if (j > 0) inter += m[k - 1].length; // interFuzz
+
+ // TODO: group here is lowercased, which is okay for length cmp, but not more case-sensitive filts
+ if (!opts.intraFilt(term, group, idxAcc)) {
+ disc = true;
+ break;
+ }
+
+ if (j < partsLen - 1) idxAcc += groupLen + m[k + 1].length;
+ }
+
+ if (!disc) {
+ info.idx[ii] = idxs[i];
+ info.interLft2[ii] = lft2;
+ info.interLft1[ii] = lft1;
+ info.interRgt2[ii] = rgt2;
+ info.interRgt1[ii] = rgt1;
+ info.chars[ii] = chars;
+ info.terms[ii] = terms;
+ info.interIns[ii] = inter;
+ info.intraIns[ii] = intra;
+
+ info.start[ii] = start;
+ // info.span[ii] = span;
+
+ // ranges
+ let m = mhstr.match(queryR);
+
+ let idxAcc = m.index + m[1].length;
+
+ let refLen = refine.length;
+ let ri = refLen > 0 ? 0 : Infinity;
+ let lastRi = refLen - 4;
+
+ for (let i = 2; i < m.length; ) {
+ let len = m[i].length;
+
+ if (ri <= lastRi && refine[ri] == idxAcc) {
+ let groupLen = refine[ri + 1];
+ let idxOf = refine[ri + 2];
+ let termLen = refine[ri + 3];
+
+ // advance to end of original (full) group match that includes intra-junk
+ let j = i;
+ let v = "";
+ for (let _len = 0; _len < groupLen; j++) {
+ v += m[j];
+ _len += m[j].length;
+ }
+
+ m.splice(i, j - i, v);
+
+ idxAcc += refineMatch(m, i, idxOf, termLen);
+
+ ri += 4;
+ } else {
+ idxAcc += len;
+ i++;
+ }
+ }
+
+ idxAcc = m.index + m[1].length;
+
+ let ranges = (info.ranges[ii] = []);
+ let from = idxAcc;
+ let to = idxAcc;
+
+ for (let i = 2; i < m.length; i++) {
+ let len = m[i].length;
+
+ idxAcc += len;
+
+ if (i % 2 == 0) to = idxAcc;
+ else if (len > 0) {
+ ranges.push(from, to);
+ from = to = idxAcc;
+ }
+ }
+
+ if (to > from) ranges.push(from, to);
+
+ ii++;
+ }
+ }
+
+ // trim arrays
+ if (ii < idxs.length) {
+ for (let k in info) info[k] = info[k].slice(0, ii);
+ }
+
+ return info;
+ };
+
+ const refineMatch = (m, k, idxInNext, termLen) => {
+ // shift the current group into the prior junk
+ let prepend = m[k] + m[k + 1].slice(0, idxInNext);
+ m[k - 1] += prepend;
+ m[k] = m[k + 1].slice(idxInNext, idxInNext + termLen);
+ m[k + 1] = m[k + 1].slice(idxInNext + termLen);
+ return prepend.length;
+ };
+
+ const OOO_TERMS_LIMIT = 5;
+
+ // returns [idxs, info, order]
+ const _search = (
+ haystack,
+ needle,
+ outOfOrder,
+ infoThresh = 1e3,
+ preFiltered
+ ) => {
+ outOfOrder = !outOfOrder
+ ? 0
+ : outOfOrder === true
+ ? OOO_TERMS_LIMIT
+ : outOfOrder;
+
+ let needles = null;
+ let matches = null;
+
+ let negs = [];
+
+ needle = needle.replace(NEGS_RE, (m) => {
+ let neg = m.trim().slice(1);
+
+ neg =
+ neg[0] === '"'
+ ? escapeRegExp(neg.slice(1, -1))
+ : neg.replace(PUNCT_RE, "");
+
+ if (neg != "") negs.push(neg);
+
+ return "";
+ });
+
+ let terms = split(needle);
+
+ let negsRe;
+
+ if (negs.length > 0) {
+ negsRe = new RegExp(negs.join("|"), "i" + uFlag);
+
+ if (terms.length == 0) {
+ let idxs = [];
+
+ for (let i = 0; i < haystack.length; i++) {
+ if (!negsRe.test(haystack[i])) idxs.push(i);
+ }
+
+ return [idxs, null, null];
+ }
+ } else {
+ // abort search (needle is empty after pre-processing, e.g. no alpha-numeric chars)
+ if (terms.length == 0) return [null, null, null];
+ }
+
+ // console.log(negs);
+ // console.log(needle);
+
+ if (outOfOrder > 0) {
+ // since uFuzzy is an AND-based search, we can iteratively pre-reduce the haystack by searching
+ // for each term in isolation before running permutations on what's left.
+ // this is a major perf win. e.g. searching "test man ger pp a" goes from 570ms -> 14ms
+ let terms = split(needle);
+
+ if (terms.length > 1) {
+ // longest -> shortest
+ let terms2 = terms.slice().sort((a, b) => b.length - a.length);
+
+ for (let ti = 0; ti < terms2.length; ti++) {
+ // no haystack item contained all terms
+ if (preFiltered?.length == 0) return [[], null, null];
+
+ preFiltered = filter(haystack, terms2[ti], preFiltered);
+ }
+
+ // avoid combinatorial explosion by limiting outOfOrder to 5 terms (120 max searches)
+ // fall back to just filter() otherwise
+ if (terms.length > outOfOrder) return [preFiltered, null, null];
+
+ needles = permute(terms).map((perm) => perm.join(" "));
+
+ // filtered matches for each needle excluding same matches for prior needles
+ matches = [];
+
+ // keeps track of already-matched idxs to skip in follow-up permutations
+ let matchedIdxs = new Set();
+
+ for (let ni = 0; ni < needles.length; ni++) {
+ if (matchedIdxs.size < preFiltered.length) {
+ // filter further for this needle, exclude already-matched
+ let preFiltered2 = preFiltered.filter(
+ (idx) => !matchedIdxs.has(idx)
+ );
+
+ let matched = filter(haystack, needles[ni], preFiltered2);
+
+ for (let j = 0; j < matched.length; j++)
+ matchedIdxs.add(matched[j]);
+
+ matches.push(matched);
+ } else matches.push([]);
+ }
+ }
+ }
+
+ // interOR
+ // console.log(prepQuery(needle, 1, null, true));
+
+ // non-ooo or ooo w/single term
+ if (needles == null) {
+ needles = [needle];
+ matches = [
+ preFiltered?.length > 0 ? preFiltered : filter(haystack, needle),
+ ];
+ }
+
+ let retInfo = null;
+ let retOrder = null;
+
+ if (negs.length > 0)
+ matches = matches.map((idxs) =>
+ idxs.filter((idx) => !negsRe.test(haystack[idx]))
+ );
+
+ let matchCount = matches.reduce((acc, idxs) => acc + idxs.length, 0);
+
+ // rank, sort, concat
+ if (matchCount <= infoThresh) {
+ retInfo = {};
+ retOrder = [];
+
+ for (let ni = 0; ni < matches.length; ni++) {
+ let idxs = matches[ni];
+
+ if (idxs == null || idxs.length == 0) continue;
+
+ let needle = needles[ni];
+ let _info = info(idxs, haystack, needle);
+ let order = opts.sort(_info, haystack, needle);
+
+ // offset idxs for concat'ing infos
+ if (ni > 0) {
+ for (let i = 0; i < order.length; i++) order[i] += retOrder.length;
+ }
+
+ for (let k in _info) retInfo[k] = (retInfo[k] ?? []).concat(_info[k]);
+
+ retOrder = retOrder.concat(order);
+ }
+ }
+
+ return [[].concat(...matches), retInfo, retOrder];
+ };
+
+ return {
+ search: (...args) => {
+ let out = _search(...args);
+ return out;
+ },
+ split,
+ filter,
+ info,
+ sort: opts.sort,
+ };
+}
+
+const latinize = (() => {
+ let accents = {
+ A: "ÁÀÃÂÄĄ",
+ a: "áàãâäą",
+ E: "ÉÈÊËĖ",
+ e: "éèêëę",
+ I: "ÍÌÎÏĮ",
+ i: "íìîïį",
+ O: "ÓÒÔÕÖ",
+ o: "óòôõö",
+ U: "ÚÙÛÜŪŲ",
+ u: "úùûüūų",
+ C: "ÇČĆ",
+ c: "çčć",
+ L: "Ł",
+ l: "ł",
+ N: "ÑŃ",
+ n: "ñń",
+ S: "ŠŚ",
+ s: "šś",
+ Z: "ŻŹ",
+ z: "żź",
+ };
+
+ let accentsMap = new Map();
+ let accentsTpl = "";
+
+ for (let r in accents) {
+ accents[r].split("").forEach((a) => {
+ accentsTpl += a;
+ accentsMap.set(a, r);
+ });
+ }
+
+ let accentsRe = new RegExp(`[${accentsTpl}]`, "g");
+ let replacer = (m) => accentsMap.get(m);
+
+ return (strings) => {
+ if (typeof strings == "string") return strings.replace(accentsRe, replacer);
+
+ let out = Array(strings.length);
+ for (let i = 0; i < strings.length; i++)
+ out[i] = strings[i].replace(accentsRe, replacer);
+ return out;
+ };
+})();
+
+// https://stackoverflow.com/questions/9960908/permutations-in-javascript/37580979#37580979
+function permute(arr) {
+ arr = arr.slice();
+
+ let length = arr.length,
+ result = [arr.slice()],
+ c = new Array(length).fill(0),
+ i = 1,
+ k,
+ p;
+
+ while (i < length) {
+ if (c[i] < i) {
+ k = i % 2 && c[i];
+ p = arr[i];
+ arr[i] = arr[k];
+ arr[k] = p;
+ ++c[i];
+ i = 1;
+ result.push(arr.slice());
+ } else {
+ c[i] = 0;
+ ++i;
+ }
+ }
+
+ return result;
+}
+
+const _mark = (part, matched) => (matched ? `${part} ` : part);
+const _append = (acc, part) => acc + part;
+
+function highlight(str, ranges, mark = _mark, accum = "", append = _append) {
+ accum = append(accum, mark(str.substring(0, ranges[0]), false)) ?? accum;
+
+ for (let i = 0; i < ranges.length; i += 2) {
+ let fr = ranges[i];
+ let to = ranges[i + 1];
+
+ accum = append(accum, mark(str.substring(fr, to), true)) ?? accum;
+
+ if (i < ranges.length - 3)
+ accum =
+ append(
+ accum,
+ mark(str.substring(ranges[i + 1], ranges[i + 2]), false)
+ ) ?? accum;
+ }
+
+ accum =
+ append(accum, mark(str.substring(ranges[ranges.length - 1]), false)) ??
+ accum;
+
+ return accum;
+}
+
+uFuzzy.latinize = latinize;
+uFuzzy.permute = (arr) => {
+ let idxs = permute([...Array(arr.length).keys()]).sort((a, b) => {
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) return a[i] - b[i];
+ }
+ return 0;
+ });
+
+ return idxs.map((pi) => pi.map((i) => arr[i]));
+};
+uFuzzy.highlight = highlight;
+
+export { uFuzzy as default };
diff --git a/app-html/manifest.webmanifest b/app-html/manifest.webmanifest
new file mode 100644
index 000000000..ef4536323
--- /dev/null
+++ b/app-html/manifest.webmanifest
@@ -0,0 +1,37 @@
+{
+ "name": "Satonomics",
+ "short_name": "Satonomics",
+ "description": "A better, FOSS, Bitcoin-only, self-hostable Glassnode",
+ "start_url": "/",
+ "display": "standalone",
+ "theme_color": "#0c0a09",
+ "background_color": "#0c0a09",
+ "lang": "en",
+ "scope": "/",
+ "icons": [
+ {
+ "src": "/assets/manifest-icon-192.maskable.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/assets/manifest-icon-192.maskable.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/assets/manifest-icon-512.maskable.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/assets/manifest-icon-512.maskable.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ]
+}
diff --git a/app-html/robots.txt b/app-html/robots.txt
new file mode 100644
index 000000000..14267e903
--- /dev/null
+++ b/app-html/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Allow: /
\ No newline at end of file
diff --git a/app-html/script.js b/app-html/script.js
new file mode 100644
index 000000000..adfdd7f39
--- /dev/null
+++ b/app-html/script.js
@@ -0,0 +1,1826 @@
+// @ts-check
+
+// Lightweight Charts download link: https://unpkg.com/browse/lightweight-charts@4.2.0/dist/
+
+/**
+ * @import { FilePath, PartialPreset, PartialPresetFolder, PartialPresetTree, Preset, PresetFolder, PresetTree, ResourceDataset, Scale, SerializedPresetsHistory, TimeRange } from "./types/self"
+ * @import * as _ from "./libraries/uFuzzy/uFuzzy.d.ts"
+ * @import { DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior } from "./libraries/lightweight-charts/types.d.ts"
+ */
+
+/*
+ * Reactivity
+ * https://gist.github.com/1Marc/09e739caa6a82cc176ab4c2abd691814
+ * Credit Ryan Carniato https://frontendmasters.com/courses/reactivity-solidjs/
+ */
+
+/**
+ * @typedef Effect
+ * @type {object}
+ * @property {VoidFunction} execute
+ * @property {Set>} dependencies
+ */
+
+/**
+ * @template T
+ * @typedef {{(): T}} Accessor
+ */
+
+/**
+ * @template T
+ * @typedef {{ (): T; set: (newValue: T | ((old: T) => T)) => void }} Signal
+ */
+
+/** @type {Effect[]} */
+let context = [];
+
+/** @param {VoidFunction} fn */
+function untrack(fn) {
+ const prevContext = context;
+ context = [];
+ const res = fn();
+ context = prevContext;
+ return res;
+}
+
+/** @param {Effect} observer */
+function cleanup(observer) {
+ for (const dep of observer.dependencies) {
+ dep.delete(observer);
+ }
+ observer.dependencies.clear();
+}
+
+/**
+ * @param {Effect} observer
+ * @param {Set} subscriptions
+ */
+function subscribe(observer, subscriptions) {
+ subscriptions.add(observer);
+ observer.dependencies.add(subscriptions);
+}
+
+/**
+ * @template T
+ * @param {T} value
+ * @param {{ equals?: boolean}} [options]
+ */
+function createSignal(value, options) {
+ const subscriptions = new Set();
+
+ function read() {
+ const observer = context[context.length - 1];
+ if (observer) subscribe(observer, subscriptions);
+ return value;
+ }
+
+ /** @param {T | ((old: T) => T)} newValue */
+ function write(newValue) {
+ if (options?.equals !== false && value === newValue) {
+ return;
+ }
+
+ if (typeof newValue === "function") {
+ // @ts-ignore
+ value = newValue(value);
+ } else {
+ value = newValue;
+ }
+ for (const observer of [...subscriptions]) {
+ observer.execute();
+ }
+ }
+
+ read.set = write;
+
+ return read;
+}
+
+/** @param {VoidFunction} fn */
+function createEffect(fn) {
+ /** @type {Effect} */
+ const effect = {
+ execute() {
+ cleanup(effect);
+ context.push(effect);
+ fn();
+ context.pop();
+ },
+ dependencies: new Set(),
+ };
+
+ effect.execute();
+
+ return effect;
+}
+
+/**
+ * @template T
+ * @param {() => T} fn
+ */
+function createMemo(fn) {
+ /** @type {Signal} */
+ const signal = /** @type {any} */ (createSignal(undefined));
+ createEffect(() => signal.set(fn()));
+ return signal;
+}
+
+function createScope() {
+ /** @type {Effect[]} */
+ const observers = [];
+
+ return {
+ /** @param {VoidFunction} callback */
+ observe(callback) {
+ this.add(createEffect(callback));
+ },
+ /** @param {Effect} effect */
+ add(effect) {
+ observers.push(effect);
+ },
+ reset() {
+ for (let i = 0; i < observers.length; i++) {
+ cleanup(observers[i]);
+ }
+ observers.length = 0;
+ },
+ };
+}
+
+/**
+ * @param {string} id
+ * @returns {HTMLElement}
+ */
+function getElementById(id) {
+ const element = window.document.getElementById(id);
+ if (!element) throw `Element with id = "${id}" should exist`;
+ return element;
+}
+
+/**
+ * @param {string} s
+ * @returns {string}
+ */
+function stringToId(s) {
+ return s.replace(/\W/g, " ").trim().replace(/ +/g, "-").toLowerCase();
+}
+
+/** @param {VoidFunction} callback */
+function runWhenIdle(callback) {
+ if ("requestIdleCallback" in window) {
+ requestIdleCallback(callback);
+ } else {
+ setTimeout(callback, 1);
+ }
+}
+
+// TODO: Wrap all on dom object
+const mainFrames = getElementById("frames");
+const chartFrameSelectorLabelId = `selected-frame-selector-label`;
+const chartLabel = getElementById(chartFrameSelectorLabelId);
+const foldersLabel = getElementById(`folders-frame-selector-label`);
+const searchLabel = getElementById(`search-frame-selector-label`);
+const foldersFrame = getElementById("folders-frame");
+const searchFrame = getElementById("search-frame");
+const historyFrame = getElementById("history-frame");
+const historyList = getElementById("history-list");
+const searchInput = /** @type {HTMLInputElement} */ (
+ getElementById("search-input")
+);
+const searchSmall = getElementById("search-small");
+const searchResults = getElementById("search-results");
+const presetTitle = getElementById("preset-title");
+const presetDescription = getElementById("preset-description");
+const foldersFilterAllCount = getElementById("folders-filter-all-count");
+const foldersFilterFavoritesCount = getElementById(
+ "folders-filter-favorites-count"
+);
+const foldersFilterNewCount = getElementById("folders-filter-new-count");
+
+(function initFrames() {
+ const localStorageKey = "checked-frame-selector-label";
+ let selectedFrameLabel = localStorage.getItem(localStorageKey);
+
+ const fieldset = window.document.getElementById("frame-selectors");
+ if (!fieldset) throw "Fieldset should exist";
+
+ const children = Array.from(fieldset.children);
+
+ /** @type {HTMLElement | undefined} */
+ let focusedSection = undefined;
+
+ for (let i = 0; i < children.length; i++) {
+ const element = children[i];
+
+ switch (element.tagName) {
+ case "LABEL": {
+ element.addEventListener("click", (event) => {
+ const id = element.id;
+
+ event.stopPropagation();
+ event.preventDefault();
+
+ const forId = element.getAttribute("for") || "";
+ const input = /** @type {HTMLInputElement | undefined} */ (
+ window.document.getElementById(forId)
+ );
+
+ if (!input) throw "Shouldn't be possible";
+ selectedFrameLabel = id;
+ localStorage.setItem(localStorageKey, id);
+ input.checked = true;
+
+ const sectionId = element.id.split("-").splice(0, 2).join("-");
+
+ const section = window.document.getElementById(sectionId);
+
+ if (!section) {
+ console.log(sectionId, section);
+ throw "Section should exist";
+ }
+
+ if (section === focusedSection) {
+ return;
+ }
+
+ section.hidden = false;
+ if (focusedSection?.parentElement === mainFrames) {
+ focusedSection.hidden = true;
+ }
+ focusedSection = section;
+ });
+ break;
+ }
+ }
+ }
+
+ if (selectedFrameLabel) {
+ const frameLabel = window.document.getElementById(selectedFrameLabel);
+ if (!frameLabel) throw "Frame should exist";
+ frameLabel.click();
+ } else {
+ chartLabel.click();
+ }
+
+ // When going from mobile view to desktop view, if selected frame was open, go to the folders frame
+ new IntersectionObserver((entries) => {
+ for (let i = 0; i < entries.length; i++) {
+ if (
+ !entries[i].isIntersecting &&
+ entries[i].target === chartLabel &&
+ selectedFrameLabel === chartFrameSelectorLabelId
+ ) {
+ foldersLabel.click();
+ }
+ }
+ }).observe(chartLabel);
+
+ document.addEventListener("keydown", (event) => {
+ switch (event.key) {
+ case "Escape": {
+ event.stopPropagation();
+ event.preventDefault();
+ foldersLabel.click();
+ break;
+ }
+ case "/": {
+ if (window.document.activeElement === searchInput) {
+ return;
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ searchLabel.click();
+ searchInput.focus();
+ break;
+ }
+ }
+ });
+})();
+
+const dark = createSignal(true);
+
+(function initEverythingRelatedToPresets() {
+ /** @type {Signal} */
+ const selected = createSignal(/** @type {any} */ (undefined));
+ const selectedLocalStorageKey = `selected-id`;
+ const savedSelectedId = localStorage.getItem(selectedLocalStorageKey);
+ const firstTime = !savedSelectedId;
+
+ /**
+ * @param {Scale} scale
+ * @returns {PartialPresetFolder}
+ */
+ function createMarketPresets(scale) {
+ return {
+ name: "Market",
+ tree: [
+ {
+ scale,
+ icon: "💵",
+ name: "Price",
+ title: "Market Price",
+ description: "",
+ unit: "US Dollars",
+ },
+ {
+ scale,
+ icon: "♾️",
+ name: "Capitalization",
+ title: "Market Capitalization",
+ description: "",
+ unit: "US Dollars",
+ bottom: [
+ {
+ title: "Market Cap.",
+ datasetPath: `${scale}-to-market-cap`,
+ color: "#f97315",
+ },
+ ],
+ },
+ ],
+ };
+ }
+
+ /** @type {PartialPresetTree} */
+ const partialTree = [
+ {
+ name: "Dashboards",
+ tree: [],
+ },
+ {
+ name: "Charts",
+ tree: [
+ {
+ name: "By Block Date",
+ tree: [createMarketPresets("date")],
+ },
+ {
+ name: "By Block Height - Desktop/Tablet Only",
+ tree: [createMarketPresets("height")],
+ },
+ ],
+ },
+ ];
+
+ /** @type {string[]} */
+ const presetsIds = [];
+
+ /** @type {Preset[]} */
+ const presetsList = [];
+
+ /** @type {HTMLDetailsElement[]} */
+ const detailsList = [];
+
+ /** @typedef {'all' | 'favorites' | 'new'} FoldersFilter */
+
+ const foldersFilterLocalStorageKey = "folders-filter";
+ const filter = createSignal(
+ /** @type {FoldersFilter} */ (
+ localStorage.getItem(foldersFilterLocalStorageKey) || "all"
+ )
+ );
+
+ const favoritesCount = createSignal(0);
+ const newCount = createSignal(0);
+ /** @param {Preset} preset */
+ function updateCounters(preset) {
+ let firstFavoritesRun = true;
+ createEffect(() => {
+ if (preset.isFavorite()) {
+ favoritesCount.set((c) => c + 1);
+ } else if (!firstFavoritesRun) {
+ favoritesCount.set((c) => c - 1);
+ }
+ firstFavoritesRun = false;
+ });
+
+ let firstNewRun = true;
+ createEffect(() => {
+ if (!preset.visited()) {
+ newCount.set((c) => c + 1);
+ } else if (!firstNewRun) {
+ newCount.set((c) => c - 1);
+ }
+ firstNewRun = false;
+ });
+ }
+
+ /** @param {string} id */
+ function createVisitedPresetLocalStorageKey(id) {
+ return `${id}-visited`;
+ }
+
+ /** @param {{preset: Preset, frame: string, name?: string, top?: string, id?: string}} args */
+ function createPresetLabel({ preset, frame, name, top, id }) {
+ const label = window.document.createElement("label");
+ const input = window.document.createElement("input");
+ input.type = "radio";
+ id = id ? `-${id}` : "";
+ input.name = `preset-${frame}${id}`;
+ input.id = `${preset.id}-${frame}${id}-selector`;
+ input.value = preset.id;
+ label.append(input);
+ label.id = `${input.id}-label`;
+ // @ts-ignore
+ label.for = input.id;
+ label.title = preset.title;
+
+ if (top) {
+ const small = window.document.createElement("small");
+ small.innerHTML = top;
+ label.append(small);
+ }
+
+ const spanMain = window.document.createElement("span");
+ spanMain.classList.add("main");
+ label.append(spanMain);
+
+ const spanEmoji = window.document.createElement("span");
+ spanEmoji.classList.add("emoji");
+ spanEmoji.innerHTML = preset.icon;
+ spanMain.append(spanEmoji);
+
+ const spanName = window.document.createElement("span");
+ spanName.classList.add("name");
+ spanName.innerHTML = name || preset.name;
+ spanMain.append(spanName);
+
+ /** @type {HTMLSpanElement | undefined} */
+ let spanNew;
+
+ if (!preset.visited()) {
+ spanNew = window.document.createElement("span");
+ spanNew.classList.add("new");
+ spanMain.append(spanNew);
+ }
+
+ /** @type {HTMLSpanElement | undefined} */
+ let spanFavorite;
+
+ if (preset.isFavorite()) {
+ spanFavorite = window.document.createElement("span");
+ spanFavorite.classList.add("favorite");
+ spanMain.append(spanFavorite);
+ }
+
+ if (!selected() && (firstTime || savedSelectedId === preset.id)) {
+ selected.set(preset);
+ }
+ label.addEventListener("click", (event) => {
+ event.stopPropagation();
+ event.preventDefault();
+ selected.set(preset);
+ });
+
+ const effect = createEffect(() => {
+ if (selected()?.id === preset.id) {
+ input.checked = true;
+ spanNew?.remove();
+ preset.visited.set(true);
+ localStorage.setItem(
+ createVisitedPresetLocalStorageKey(preset.id),
+ "1"
+ );
+ localStorage.setItem(selectedLocalStorageKey, preset.id);
+ } else {
+ input.checked = false;
+ }
+ });
+
+ return { label, effect };
+ }
+
+ /**
+ * @param {PartialPresetTree} partialTree
+ * @param {HTMLElement} parent
+ * @param {FilePath | undefined} path
+ * @returns {Signal}
+ */
+ function processPartialTree(partialTree, parent, path = undefined) {
+ const ul = window.document.createElement("ul");
+ parent.appendChild(ul);
+
+ /** @type {Accessor[]} */
+ const listForSum = [];
+
+ partialTree.forEach((anyPartial) => {
+ const li = window.document.createElement("li");
+ ul.appendChild(li);
+
+ if ("tree" in anyPartial) {
+ const folderId = stringToId(
+ `${(path || [])?.map(({ name }) => name).join(" ")} ${
+ anyPartial.name
+ } folder`
+ );
+
+ /** @type {Omit} */
+ const restFolder = {
+ id: folderId,
+ };
+
+ Object.assign(anyPartial, restFolder);
+
+ presetsIds.push(restFolder.id);
+
+ const details = window.document.createElement("details");
+ const folderOpenLocalStorageKey = `${folderId}-open`;
+ details.open = !!localStorage.getItem(folderOpenLocalStorageKey);
+ detailsList.push(details);
+ li.appendChild(details);
+
+ const summary = window.document.createElement("summary");
+ summary.id = folderId;
+
+ const spanMarker = window.document.createElement("span");
+ spanMarker.classList.add("marker");
+ spanMarker.innerHTML = "●";
+ summary.append(spanMarker);
+
+ const spanName = window.document.createElement("span");
+ spanName.classList.add("name");
+ spanName.innerHTML = anyPartial.name;
+ summary.append(spanName);
+
+ const smallCount = window.document.createElement("small");
+ smallCount.hidden = details.open;
+ summary.append(smallCount);
+
+ details.appendChild(summary);
+
+ details.addEventListener("toggle", () => {
+ const open = details.open;
+
+ smallCount.hidden = open;
+
+ if (open) {
+ spanMarker.innerHTML = "○";
+ localStorage.setItem(folderOpenLocalStorageKey, "1");
+ } else {
+ spanMarker.innerHTML = "●";
+ localStorage.removeItem(folderOpenLocalStorageKey);
+ }
+ });
+
+ const childPresetsCount = processPartialTree(anyPartial.tree, details, [
+ ...(path || []),
+ {
+ name: anyPartial.name,
+ id: restFolder.id,
+ },
+ ]);
+
+ listForSum.push(childPresetsCount);
+
+ createEffect(() => {
+ const count = childPresetsCount();
+ smallCount.innerHTML = count.toString();
+
+ if (!count) {
+ li.hidden = true;
+ } else {
+ li.hidden = false;
+ }
+ });
+ } else {
+ const id = `${anyPartial.scale}-to-${stringToId(anyPartial.title)}`;
+
+ const favoriteLocalStorageKey = `${id}-favorite`;
+
+ /** @type {Omit} */
+ const restPreset = {
+ id,
+ path: path || [],
+ serializedPath: `/ ${[
+ ...(path || []).map(({ name }) => name),
+ anyPartial.name,
+ ].join(" / ")}`,
+ isFavorite: createSignal(false),
+ visited: createSignal(
+ !!localStorage.getItem(createVisitedPresetLocalStorageKey(id))
+ ),
+ };
+
+ Object.assign(anyPartial, restPreset);
+
+ const preset = /** @type {Preset} */ (anyPartial);
+
+ updateCounters(preset);
+
+ const { label } = createPresetLabel({
+ preset,
+ frame: "folders",
+ });
+ const inDom = createSignal(true);
+ li.append(label);
+
+ // DOM effect
+ createEffect(() => {
+ switch (filter()) {
+ case "all": {
+ if (!inDom()) {
+ ul.append(li);
+ inDom.set(true);
+ }
+ break;
+ }
+ case "favorites": {
+ if (preset.isFavorite()) {
+ if (!inDom()) {
+ ul.append(li);
+ inDom.set(true);
+ }
+ } else if (inDom()) {
+ inDom.set(false);
+ ul.removeChild(li);
+ }
+ break;
+ }
+ case "new": {
+ if (!preset.visited()) {
+ if (!inDom()) {
+ ul.append(li);
+ inDom.set(true);
+ }
+ } else if (inDom()) {
+ inDom.set(false);
+ ul.removeChild(li);
+ }
+ break;
+ }
+ }
+ });
+
+ const memo = createMemo(() => (inDom() ? 1 : 0));
+ listForSum.push(memo);
+
+ presetsList.push(preset);
+ presetsIds.push(id);
+ }
+ });
+
+ return createMemo(() => listForSum.reduce((acc, s) => acc + s(), 0));
+ }
+
+ const tree = window.document.createElement("div");
+ tree.classList.add("tree");
+ foldersFrame.append(tree);
+ const allCount = processPartialTree(partialTree, tree);
+
+ (function checkUniqueIds() {
+ if (presetsIds.length !== new Set(presetsIds).size) {
+ /** @type {Map} */
+ const m = new Map();
+
+ presetsIds.forEach((id) => {
+ m.set(id, (m.get(id) || 0) + 1);
+ });
+
+ console.log(
+ [...m.entries()]
+ .filter(([_, value]) => value > 1)
+ .map(([key, _]) => key)
+ );
+
+ throw Error("ID duplicate");
+ }
+ })();
+
+ (function createCountersDomUpdateEffect() {
+ foldersFilterAllCount.innerHTML = allCount().toLocaleString();
+ createEffect(() => {
+ foldersFilterFavoritesCount.innerHTML = favoritesCount().toLocaleString();
+ });
+ createEffect(() => {
+ foldersFilterNewCount.innerHTML = newCount().toLocaleString();
+ });
+ })();
+
+ (function initFilterElements() {
+ const filterAllInput = /** @type {HTMLInputElement} */ (
+ getElementById("folders-filter-all")
+ );
+ const filterFavoritesInput = /** @type {HTMLInputElement} */ (
+ getElementById("folders-filter-favorites")
+ );
+ const filterNewInput = /** @type {HTMLInputElement} */ (
+ getElementById("folders-filter-new")
+ );
+
+ filterAllInput.addEventListener("change", () => {
+ filter.set("all");
+ });
+ filterFavoritesInput.addEventListener("change", () => {
+ filter.set("favorites");
+ });
+ filterNewInput.addEventListener("change", () => {
+ filter.set("new");
+ });
+
+ createEffect(() => {
+ const f = filter();
+ localStorage.setItem(foldersFilterLocalStorageKey, f);
+ switch (f) {
+ case "all": {
+ filterAllInput.checked = true;
+ break;
+ }
+ case "favorites": {
+ filterFavoritesInput.checked = true;
+ break;
+ }
+ case "new": {
+ filterNewInput.checked = true;
+ break;
+ }
+ }
+ });
+ })();
+
+ (function initCloseAllButton() {
+ getElementById("button-close-all-folders").addEventListener("click", () => {
+ detailsList.forEach((details) => (details.open = false));
+ });
+ })();
+
+ (function initGoToSelectedButton() {
+ function goToSelected() {
+ filter.set("all");
+
+ if (!selected()) throw "Selected should be set by now";
+ const selectedId = selected().id;
+
+ selected().path.forEach(({ id }) => {
+ const summary = getElementById(id);
+ const details = /** @type {HTMLDetailsElement | undefined} */ (
+ summary.parentElement
+ );
+ if (!details) throw "Parent details should exist";
+ if (!details.open) {
+ summary.click();
+ }
+ });
+
+ setTimeout(() => {
+ getElementById(`${selectedId}-folders-selector`).scrollIntoView({
+ behavior: "instant",
+ block: "center",
+ });
+ }, 0);
+ }
+
+ getElementById("button-go-to-selected").addEventListener(
+ "click",
+ goToSelected
+ );
+
+ if (firstTime) {
+ goToSelected();
+ }
+ })();
+
+ createEffect(() => {
+ const preset = selected();
+ presetTitle.innerHTML = preset.title;
+ presetDescription.innerHTML = preset.serializedPath;
+ });
+
+ const LOCAL_STORAGE_RANGE_KEY = "chart-range";
+ const URL_PARAMS_RANGE_FROM_KEY = "from";
+ const URL_PARAMS_RANGE_TO_KEY = "to";
+ const HEIGHT_CHUNK_SIZE = 10_000;
+
+ /**
+ * @param {Scale} scale
+ * @returns {string}
+ */
+ function getVisibleRangeLocalStorageKey(scale) {
+ return `${LOCAL_STORAGE_RANGE_KEY}-${scale}`;
+ }
+
+ /**
+ * @param {Scale} scale
+ * @returns {TimeRange}
+ */
+ function getInitialVisibleRange(scale) {
+ const urlParams = new URLSearchParams(window.location.search);
+
+ const urlFrom = urlParams.get(URL_PARAMS_RANGE_FROM_KEY);
+ const urlTo = urlParams.get(URL_PARAMS_RANGE_TO_KEY);
+
+ if (urlFrom && urlTo) {
+ if (scale === "date" && urlFrom.includes("-") && urlTo.includes("-")) {
+ return {
+ from: new Date(urlFrom).toJSON().split("T")[0],
+ to: new Date(urlTo).toJSON().split("T")[0],
+ };
+ } else if (
+ scale === "height" &&
+ !urlFrom.includes("-") &&
+ !urlTo.includes("-")
+ ) {
+ return {
+ from: Number(urlFrom),
+ to: Number(urlTo),
+ };
+ }
+ }
+
+ /** @type {TimeRange | null} */
+ const savedTimeRange = /** @type {any} */ (
+ JSON.parse(
+ localStorage.getItem(getVisibleRangeLocalStorageKey(scale)) || "null"
+ )
+ );
+
+ if (savedTimeRange) {
+ return savedTimeRange;
+ }
+
+ switch (scale) {
+ case "date": {
+ const defaultTo = new Date();
+ const defaultFrom = new Date();
+ defaultFrom.setDate(defaultFrom.getUTCDate() - 6 * 30);
+
+ return {
+ from: defaultFrom.toJSON().split("T")[0],
+ to: defaultTo.toJSON().split("T")[0],
+ };
+ }
+ case "height": {
+ return {
+ from: 800_000,
+ to: 850_000,
+ };
+ }
+ }
+ }
+
+ runWhenIdle(() =>
+ import("./libraries/lightweight-charts/standalone.mjs").then(
+ ({ createChart: createClassicChart }) => {
+ const scale = createMemo(() => selected().scale);
+ const activeDatasets = createSignal(
+ /** @type {ResourceDataset[]} */ ([]),
+ {
+ equals: false,
+ }
+ );
+ const visibleRange = createSignal(getInitialVisibleRange(scale()));
+ const visibleDatasetIds = createSignal(/** @type {number[]} */ ([]), {
+ equals: false,
+ });
+
+ function setActiveIds() {
+ /** @type {number[]} */
+ let ids = [];
+
+ const today = new Date();
+ const { from: rawFrom, to: rawTo } = visibleRange();
+
+ if (typeof rawFrom === "string" && typeof rawTo === "string") {
+ const from = new Date(rawFrom).getUTCFullYear();
+ const to = new Date(rawTo).getUTCFullYear();
+
+ ids = Array.from(
+ { length: to - from + 1 },
+ (_, i) => i + from
+ ).filter((year) => year >= 2009 && year <= today.getUTCFullYear());
+ } else {
+ const from = Math.floor(Number(rawFrom) / HEIGHT_CHUNK_SIZE);
+ const to = Math.floor(Number(rawTo) / HEIGHT_CHUNK_SIZE);
+
+ const length = to - from + 1;
+
+ ids = Array.from(
+ { length },
+ (_, i) => (from + i) * HEIGHT_CHUNK_SIZE
+ );
+ }
+
+ const old = visibleDatasetIds();
+
+ if (
+ old.length !== ids.length ||
+ old.at(0) !== ids.at(0) ||
+ old.at(-1) !== ids.at(-1)
+ ) {
+ console.log("range:", ids);
+
+ visibleDatasetIds.set(ids);
+ }
+ }
+ setActiveIds();
+
+ (function createFetchChunksOfVisibleDatasetsEffect() {
+ // Fetch visible dataset
+ createEffect(() => {
+ const ids = visibleDatasetIds();
+ const datasets = activeDatasets();
+ for (let i = 0; i < ids.length; i++) {
+ const id = ids[i];
+ for (let j = 0; j < datasets.length; j++) {
+ datasets[j].fetch(id);
+ }
+ }
+ });
+ })();
+
+ /** @param {number} value */
+ function numberToShortUSLocale(value) {
+ const absoluteValue = Math.abs(value);
+
+ // value = absoluteValue;
+
+ if (isNaN(value)) {
+ return "";
+ // } else if (value === 0) {
+ // return "0";
+ } else if (absoluteValue < 10) {
+ return numberToUSLocale(value, 3);
+ } else if (absoluteValue < 100) {
+ return numberToUSLocale(value, 2);
+ } else if (absoluteValue < 1_000) {
+ return numberToUSLocale(value, 1);
+ } else if (absoluteValue < 100_000) {
+ return numberToUSLocale(value, 0);
+ } else if (absoluteValue < 1_000_000) {
+ return `${numberToUSLocale(value / 1_000, 1)}K`;
+ } else if (absoluteValue >= 1_000_000_000_000_000_000) {
+ return "Inf.";
+ }
+
+ const log = Math.floor(Math.log10(absoluteValue) - 6);
+
+ const suffices = ["M", "B", "T", "Q"];
+ const letterIndex = Math.floor(log / 3);
+ const letter = suffices[letterIndex];
+
+ const modulused = log % 3;
+
+ if (modulused === 0) {
+ return `${numberToUSLocale(
+ value / (1_000_000 * 1_000 ** letterIndex),
+ 3
+ )}${letter}`;
+ } else if (modulused === 1) {
+ return `${numberToUSLocale(
+ value / (1_000_000 * 1_000 ** letterIndex),
+ 2
+ )}${letter}`;
+ } else {
+ return `${numberToUSLocale(
+ value / (1_000_000 * 1_000 ** letterIndex),
+ 1
+ )}${letter}`;
+ }
+ }
+
+ /**
+ * @param {number} value
+ * @param {number} [digits]
+ * @param {Intl.NumberFormatOptions} [options]
+ */
+ function numberToUSLocale(value, digits, options) {
+ return value.toLocaleString("en-us", {
+ ...options,
+ minimumFractionDigits: digits,
+ maximumFractionDigits: digits,
+ });
+ }
+
+ /**
+ * @class
+ * @implements {IHorzScaleBehavior}
+ */
+ class HorzScaleBehaviorHeight {
+ options() {
+ return /** @type {any} */ (undefined);
+ }
+ setOptions() {}
+ preprocessData() {}
+ updateFormatter() {}
+
+ createConverterToInternalObj() {
+ /** @type {(p: any) => any} */
+ return (price) => price;
+ }
+
+ /** @param {any} item */
+ key(item) {
+ return item;
+ }
+
+ /** @param {any} item */
+ cacheKey(item) {
+ return item;
+ }
+
+ /** @param {any} item */
+ convertHorzItemToInternal(item) {
+ return item;
+ }
+
+ /** @param {any} item */
+ formatHorzItem(item) {
+ return item;
+ }
+
+ /** @param {any} tickMark */
+ formatTickmark(tickMark) {
+ return tickMark.time.toLocaleString("en-us");
+ }
+
+ /** @param {any} tickMarks */
+ maxTickMarkWeight(tickMarks) {
+ return tickMarks.reduce(this.getMarkWithGreaterWeight, tickMarks[0])
+ .weight;
+ }
+
+ /**
+ * @param {any} sortedTimePoints
+ * @param {number} startIndex
+ */
+ fillWeightsForPoints(sortedTimePoints, startIndex) {
+ for (
+ let index = startIndex;
+ index < sortedTimePoints.length;
+ ++index
+ ) {
+ sortedTimePoints[index].timeWeight = this.computeHeightWeight(
+ sortedTimePoints[index].time
+ );
+ }
+ }
+
+ /**
+ * @param {any} a
+ * @param {any} b
+ */
+ getMarkWithGreaterWeight(a, b) {
+ return a.weight > b.weight ? a : b;
+ }
+
+ /** @param {number} value */
+ computeHeightWeight(value) {
+ // if (value === Math.ceil(value / 1000000) * 1000000) {
+ // return 12;
+ // }
+ if (value === Math.ceil(value / 100000) * 100000) {
+ return 11;
+ }
+ if (value === Math.ceil(value / 10000) * 10000) {
+ return 10;
+ }
+ if (value === Math.ceil(value / 1000) * 1000) {
+ return 9;
+ }
+ if (value === Math.ceil(value / 100) * 100) {
+ return 8;
+ }
+ if (value === Math.ceil(value / 50) * 50) {
+ return 7;
+ }
+ if (value === Math.ceil(value / 25) * 25) {
+ return 6;
+ }
+ if (value === Math.ceil(value / 10) * 10) {
+ return 5;
+ }
+ if (value === Math.ceil(value / 5) * 5) {
+ return 4;
+ }
+ if (value === Math.ceil(value)) {
+ return 3;
+ }
+ if (value * 2 === Math.ceil(value * 2)) {
+ return 1;
+ }
+
+ return 0;
+ }
+ }
+
+ const colors = (function createColors() {
+ /** @param {Accessor} dark */
+ function lightRed(dark) {
+ const tailwindRed300 = "#fca5a5";
+ const tailwindRed800 = "#991b1b";
+ return dark() ? tailwindRed300 : tailwindRed800;
+ }
+ /** @param {Accessor} dark */
+ function red(dark) {
+ return "#e63636"; // 550
+ }
+ /** @param {Accessor} dark */
+ function darkRed(dark) {
+ const tailwindRed900 = "#7f1d1d";
+ const tailwindRed100 = "#fee2e2";
+ return dark() ? tailwindRed900 : tailwindRed100;
+ }
+ /** @param {Accessor} dark */
+ function orange(dark) {
+ return "#fa5c00"; // 550
+ }
+ /** @param {Accessor} dark */
+ function darkOrange(dark) {
+ const tailwindOrange900 = "#7c2d12";
+ const tailwindOrange100 = "#ffedd5";
+ return dark() ? tailwindOrange900 : tailwindOrange100;
+ }
+ /** @param {Accessor} dark */
+ function amber(dark) {
+ return "#df9408"; // 550
+ }
+ /** @param {Accessor} dark */
+ function yellow(dark) {
+ return "#db9e03"; // 550
+ }
+ /** @param {Accessor} dark */
+ function lime(dark) {
+ return "#74b713"; // 550
+ }
+ /** @param {Accessor} dark */
+ function green(dark) {
+ return "#1cb454";
+ }
+ /** @param {Accessor} dark */
+ function darkGreen(dark) {
+ const tailwindGreen900 = "#14532d";
+ const tailwindGreen100 = "#dcfce7";
+ return dark() ? tailwindGreen900 : tailwindGreen100;
+ }
+ /** @param {Accessor} dark */
+ function emerald(dark) {
+ return "#0ba775";
+ }
+ /** @param {Accessor} dark */
+ function darkEmerald(dark) {
+ const tailwindEmerald900 = "#064e3b";
+ const tailwindEmerald100 = "#d1fae5";
+ return dark() ? tailwindEmerald900 : tailwindEmerald100;
+ }
+ /** @param {Accessor} dark */
+ function teal(dark) {
+ return "#10a697"; // 550
+ }
+ /** @param {Accessor} dark */
+ function cyan(dark) {
+ return "#06a3c3"; // 550
+ }
+ /** @param {Accessor} dark */
+ function sky(dark) {
+ return "#0794d8"; // 550
+ }
+ /** @param {Accessor} dark */
+ function blue(dark) {
+ return "#2f73f1"; // 550
+ }
+ /** @param {Accessor} dark */
+ function indigo(dark) {
+ return "#5957eb";
+ }
+ /** @param {Accessor} dark */
+ function violet(dark) {
+ return "#834cf2";
+ }
+ /** @param {Accessor} dark */
+ function purple(dark) {
+ return "#9d45f0";
+ }
+ /** @param {Accessor} dark */
+ function fuchsia(dark) {
+ return "#cc37e1";
+ }
+ /** @param {Accessor