@stacksjs/charts 0.70.73 → 0.70.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +3 -3
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{scaleBand as g,scaleLinear as f}from"@ts-charts/scale";import{arc as h,area as r,curveLinear as x,curveMonotoneX as n,line as c,pie as p}from"@ts-charts/shape";var C=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#14b8a6","#f97316","#6366f1","#84cc16"];function F(q){return C[q%C.length]??C[0]}function T(q,J){if(q.startsWith("#")){let N=q.slice(1),z=Number.parseInt(N.slice(0,2),16),Z=Number.parseInt(N.slice(2,4),16),K=Number.parseInt(N.slice(4,6),16);return`rgba(${z}, ${Z}, ${K}, ${J})`}if(q.startsWith("rgb("))return q.replace("rgb(","rgba(").replace(")",`, ${J})`);return q}import{format as u}from"@ts-charts/format";import{scaleLinear as m}from"@ts-charts/scale";function A(q,J,N=8){if(!Number.isFinite(q)||!Number.isFinite(J)||J<=q)return[Number.isFinite(q)?q:0];let Z=m().domain([q,J]).nice(N).ticks(N);if(Z.length===0)return[q,J];return Z}var b=u("~s");function R(q){if(!Number.isFinite(q))return"";if(Math.abs(q)>=1000)return b(q).replace("G","B").toUpperCase();if(Number.isInteger(q))return q.toString();return q.toFixed(2)}var o="rgba(148, 163, 184, 0.18)",I="#64748b",d="rgba(15, 23, 42, 0.92)";class w{static instances=new WeakMap;static register(...q){}type;data;options;canvas;ctx;resizeObserver=null;hitItems=[];tooltipEl=null;boundMove=(q)=>this.handleMouseMove(q);boundLeave=()=>this.hideTooltip();constructor(q,J){this.canvas=q instanceof HTMLCanvasElement?q:q.canvas;let N=this.canvas.getContext("2d");if(!N)throw Error("Chart: 2D canvas context unavailable");this.ctx=N,this.type=J.type,this.data=J.data,this.options=J.options??{},w.instances.set(this.canvas,this),this.attachInteractions(),this.observeResize(),this.render()}update(){this.render()}resize(){this.render()}destroy(){if(this.resizeObserver)this.resizeObserver.disconnect(),this.resizeObserver=null;if(this.canvas.removeEventListener("mousemove",this.boundMove),this.canvas.removeEventListener("mouseleave",this.boundLeave),this.tooltipEl?.parentNode)this.tooltipEl.parentNode.removeChild(this.tooltipEl);this.tooltipEl=null,this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),w.instances.delete(this.canvas)}observeResize(){if(this.options.responsive===!1||typeof ResizeObserver>"u")return;this.resizeObserver=new ResizeObserver(()=>this.render()),this.resizeObserver.observe(this.canvas.parentElement??this.canvas)}attachInteractions(){if(this.options.plugins?.tooltip?.enabled===!1)return;this.canvas.addEventListener("mousemove",this.boundMove),this.canvas.addEventListener("mouseleave",this.boundLeave)}syncCanvasSize(){let q=typeof window<"u"?window.devicePixelRatio||1:1,J=this.canvas.getBoundingClientRect(),N=J.width||this.canvas.clientWidth||this.canvas.width,z=J.height||this.canvas.clientHeight||this.canvas.height,Z=Math.max(1,Math.floor(N*q)),K=Math.max(1,Math.floor(z*q));if(this.canvas.width!==Z)this.canvas.width=Z;if(this.canvas.height!==K)this.canvas.height=K;return this.ctx.setTransform(q,0,0,q,0,0),{width:N,height:z}}render(){let{width:q,height:J}=this.syncCanvasSize();if(this.ctx.clearRect(0,0,q,J),this.hitItems=[],this.type==="doughnut"||this.type==="pie"){this.renderRadial(q,J);return}if(this.type==="radar"){this.renderCartesian(q,J,"line");return}this.renderCartesian(q,J,this.type)}renderCartesian(q,J,N){let z=this.data.labels??[],Z=this.data.datasets,K=this.layoutLegend(q,J),$=8+(this.options.plugins?.title?.display?24:0)+(K.position==="top"?K.h:0),Q=28+(K.position==="bottom"?K.h:0),j=48+(K.position==="left"?K.w:0),V=16+(K.position==="right"?K.w:0)+(this.hasRightAxis()?40:0),H={x:j,y:$,w:Math.max(1,q-j-V),h:Math.max(1,J-$-Q)};if(this.options.plugins?.title?.display&&this.options.plugins.title.text){let Y=this.options.plugins.title;this.ctx.fillStyle=Y.color??I,this.ctx.font=`${Y.font?.size??14}px system-ui, sans-serif`,this.ctx.textAlign="center",this.ctx.textBaseline="top",this.ctx.fillText(Y.text??"",q/2,8)}this.drawLegend(K,Z);let S=this.computeAxis(Z.filter((Y)=>(Y.yAxisID??"y")==="y"),"y"),B=this.hasRightAxis()?this.computeAxis(Z.filter((Y)=>Y.yAxisID==="y1"),"y1"):null;if(this.drawGridAndYAxis(H,S,"left"),B)this.drawYAxis(H,B,"right");if(this.drawXAxis(H,z),N==="bar")this.drawBars(H,z,Z,S,B);else this.drawLines(H,z,Z,S,B)}hasRightAxis(){return this.data.datasets.some((q)=>q.yAxisID==="y1")}computeAxis(q,J){let N=this.options.scales?.[J]??{},z=Number.POSITIVE_INFINITY,Z=Number.NEGATIVE_INFINITY;if(N.stacked){let M=this.data.labels??[];for(let $=0;$<M.length;$++){let Q=0,j=0;for(let V of q){let H=V.data[$]??0;if(H>=0)Q+=H;else j+=H}if(Q>Z)Z=Q;if(j<z)z=j}}else for(let M of q)for(let $ of M.data){if($<z)z=$;if($>Z)Z=$}if(!Number.isFinite(z))z=0;if(!Number.isFinite(Z))Z=1;if(N.beginAtZero!==!1&&z>0)z=0;if(N.min!==void 0)z=N.min;if(N.max!==void 0)Z=N.max;if(z===Z)Z=z+1;let K=A(z,Z,N.ticks?.maxTicksLimit??6);return{ticks:K,min:K[0]??z,max:K[K.length-1]??Z}}drawGridAndYAxis(q,J,N){let z=this.options.scales?.y??{},Z=z.grid?.display!==!1,K=z.ticks?.color??I,M=z.grid?.color??o;this.ctx.save(),this.ctx.font=`${z.ticks?.font?.size??11}px system-ui, sans-serif`,this.ctx.textBaseline="middle";for(let $ of J.ticks){let Q=this.scaleY(q,J,$);if(Z)this.ctx.strokeStyle=M,this.ctx.lineWidth=1,this.ctx.beginPath(),this.ctx.moveTo(q.x,Q),this.ctx.lineTo(q.x+q.w,Q),this.ctx.stroke();let j=z.ticks?.callback?z.ticks.callback($,J.ticks.indexOf($),J.ticks):R($);this.ctx.fillStyle=K,this.ctx.textAlign=N==="left"?"right":"left";let V=N==="left"?q.x-8:q.x+q.w+8;this.ctx.fillText(String(j),V,Q)}this.ctx.restore()}drawYAxis(q,J,N){let z=this.options.scales?.y1??{},Z=z.ticks?.color??I;this.ctx.save(),this.ctx.font=`${z.ticks?.font?.size??11}px system-ui, sans-serif`,this.ctx.textBaseline="middle";for(let K of J.ticks){let M=this.scaleY(q,J,K),$=z.ticks?.callback?z.ticks.callback(K,J.ticks.indexOf(K),J.ticks):R(K);this.ctx.fillStyle=Z,this.ctx.textAlign=N==="left"?"right":"left";let Q=N==="left"?q.x-8:q.x+q.w+8;this.ctx.fillText(String($),Q,M)}this.ctx.restore()}drawXAxis(q,J){let N=this.options.scales?.x??{},z=N.ticks?.color??I;if(N.display===!1||J.length===0)return;this.ctx.save(),this.ctx.font=`${N.ticks?.font?.size??11}px system-ui, sans-serif`,this.ctx.textBaseline="top",this.ctx.textAlign="center",this.ctx.fillStyle=z;let Z=Math.min(J.length,Math.max(2,Math.floor(q.w/60))),K=Math.max(1,Math.floor(J.length/Z));for(let M=0;M<J.length;M+=K){let $=this.scaleX(q,J.length,M);this.ctx.fillText(J[M]??"",$,q.y+q.h+8)}this.ctx.restore()}scaleX(q,J,N){if(J<=1)return q.x+q.w/2;return f().domain([0,J-1]).range([q.x,q.x+q.w])(N)}scaleY(q,J,N){if(J.max===J.min)return q.y+q.h/2;return f().domain([J.min,J.max]).range([q.y+q.h,q.y])(N)}drawLines(q,J,N,z,Z){N.forEach((K,M)=>{let $=K.yAxisID==="y1"&&Z?Z:z;if(K.type==="bar"){this.drawBarSeries(q,J,[K],z,Z);return}let Q=(typeof K.borderColor==="string"?K.borderColor:null)??F(M),j=K.backgroundColor&&typeof K.backgroundColor==="string"?K.backgroundColor:K.fill?T(Q,0.15):null,V=K.data.map((Y,P)=>({x:this.scaleX(q,J.length||K.data.length,P),y:this.scaleY(q,$,Y),value:Y}));if(V.length===0)return;let H=(K.tension??0)>0?n:x;if(j){let Y=q.y+q.h,P=r().x((G)=>G.x).y0(()=>Y).y1((G)=>G.y).curve(H).context(this.ctx);this.ctx.beginPath(),P(V),this.ctx.fillStyle=j,this.ctx.fill(),P.context(null)}let S=c().x((Y)=>Y.x).y((Y)=>Y.y).curve(H).context(this.ctx);this.ctx.beginPath(),S(V),this.ctx.lineWidth=K.borderWidth??2,this.ctx.strokeStyle=Q,this.ctx.lineJoin="round",this.ctx.lineCap="round",this.ctx.stroke(),S.context(null);let B=K.pointRadius??0;if(B>0){this.ctx.fillStyle=K.pointBackgroundColor??Q;for(let Y of V)this.ctx.beginPath(),this.ctx.arc(Y.x,Y.y,B,0,Math.PI*2),this.ctx.fill()}V.forEach((Y,P)=>{this.hitItems.push({datasetIndex:M,dataIndex:P,x:Y.x,y:Y.y,label:J[P]??String(P),value:Y.value})})})}drawBars(q,J,N,z,Z){this.drawBarSeries(q,J,N,z,Z)}drawBarSeries(q,J,N,z,Z){let K=J.length||(N[0]?.data.length??0);if(K===0)return;let $=!!this.options.scales?.y?.stacked,Q=Array.from({length:K},(S,B)=>B),j=g().domain(Q).range([q.x,q.x+q.w]).paddingInner(0.3),V=j.bandwidth(),H=$?V:V/Math.max(1,N.length);for(let S=0;S<K;S++){let B=j(S),Y=0,P=0;N.forEach((G,D)=>{let W=G.yAxisID==="y1"&&Z?Z:z,X=G.data[S]??0,U=$?X>=0?Y:P:0,O=U+X,L=this.scaleY(q,W,U),E=this.scaleY(q,W,O),_=$?B:B+D*H,k=Math.min(L,E),v=Math.abs(E-L),y=Array.isArray(G.backgroundColor)?G.backgroundColor[S]??F(D):typeof G.backgroundColor==="string"?G.backgroundColor:F(D);if(this.ctx.fillStyle=y,this.ctx.fillRect(_,k,Math.max(1,H-2),v),G.borderWidth&&G.borderColor&&typeof G.borderColor==="string")this.ctx.lineWidth=G.borderWidth,this.ctx.strokeStyle=G.borderColor,this.ctx.strokeRect(_,k,Math.max(1,H-2),v);if($)if(X>=0)Y=O;else P=O;this.hitItems.push({datasetIndex:D,dataIndex:S,x:_+H/2,y:k,label:J[S]??String(S),value:X})})}}renderRadial(q,J){let N=this.data.datasets;if(N.length===0)return;let z=N[0];if(!z)return;let Z=this.data.labels??[],K=this.layoutLegend(q,J),M=q,$=J,Q=0,j=0;if(K.position==="right")M=q-K.w;else if(K.position==="left")M=q-K.w,Q=K.w;else if(K.position==="top")$=J-K.h,j=K.h;else if(K.position==="bottom")$=J-K.h;this.drawLegend(K,N.map((X,U)=>({...X,label:Z[U]??X.label})),Z);let V=Q+M/2,H=j+$/2,S=Math.min(M,$)/2-8,B=this.options.cutout,Y=typeof B==="string"&&B.endsWith("%")?Number.parseFloat(B)/100:this.type==="doughnut"?0.6:0,P=S*Y,D=p().value((X)=>Math.max(0,X||0)).startAngle(-Math.PI/2).endAngle(-Math.PI/2+Math.PI*2).sort(null)(z.data),W=h().innerRadius(P).outerRadius(S);this.ctx.save(),this.ctx.translate(V,H);for(let X of D){let U=X.index,O=z.data[U]??0,L=Array.isArray(z.backgroundColor)?z.backgroundColor[U]??F(U):typeof z.backgroundColor==="string"?z.backgroundColor:F(U);this.ctx.beginPath(),W.context(this.ctx)(X),this.ctx.fillStyle=L,this.ctx.fill();let E=(X.startAngle+X.endAngle)/2-Math.PI/2,_=(S+P)/2;this.hitItems.push({datasetIndex:0,dataIndex:U,x:V+Math.cos(E)*_,y:H+Math.sin(E)*_,label:Z[U]??String(U),value:O})}this.ctx.restore(),W.context(null)}layoutLegend(q,J){let N=this.options.plugins?.legend;if(N?.display===!1||!this.data.datasets.some((Z)=>Z.label))return{w:0,h:0,position:"none"};let z=N?.position??"top";if(z==="left"||z==="right")return{w:100,h:0,position:z};return{w:0,h:Math.max(24,Math.ceil(this.data.datasets.length/4)*18+8),position:z}}drawLegend(q,J,N){if(q.position==="none")return;let z=this.options.plugins?.legend,Z=N&&(this.type==="pie"||this.type==="doughnut")?N.map(($,Q)=>{let j=J[0],V=Array.isArray(j?.backgroundColor)?j.backgroundColor[Q]??F(Q):typeof j?.backgroundColor==="string"?j.backgroundColor:F(Q);return{label:$,color:V}}):J.map(($,Q)=>({label:$.label??`Dataset ${Q+1}`,color:typeof $.borderColor==="string"?$.borderColor:Array.isArray($.backgroundColor)?$.backgroundColor[0]??F(Q):typeof $.backgroundColor==="string"?$.backgroundColor:F(Q)}));if(Z.length===0)return;this.ctx.save(),this.ctx.font=`${z?.labels?.font?.size??12}px system-ui, sans-serif`,this.ctx.fillStyle=z?.labels?.color??I,this.ctx.textBaseline="middle";let K=z?.labels?.boxWidth??12,M=z?.labels?.padding??8;if(q.position==="top"||q.position==="bottom"){let $=q.position==="top"?12:(this.canvas.clientHeight||0)-12,Q=M;this.ctx.textAlign="left";for(let j of Z)this.ctx.fillStyle=j.color,this.ctx.fillRect(Q,$-K/2,K,K),Q+=K+4,this.ctx.fillStyle=z?.labels?.color??I,this.ctx.fillText(j.label,Q,$),Q+=this.ctx.measureText(j.label).width+M*2}else{let $=q.position==="right"?(this.canvas.clientWidth||0)-110:8,Q=M+6;for(let j of Z)this.ctx.fillStyle=j.color,this.ctx.fillRect($,Q-K/2,K,K),this.ctx.fillStyle=z?.labels?.color??I,this.ctx.textAlign="left",this.ctx.fillText(j.label,$+K+4,Q),Q+=18}this.ctx.restore()}handleMouseMove(q){if(this.hitItems.length===0)return;let J=this.canvas.getBoundingClientRect(),N=q.clientX-J.left,z=q.clientY-J.top;if((this.options.interaction?.mode??this.options.plugins?.tooltip?.mode??"nearest")==="index"){let $=this.findClosestByIndex(N);if($)this.showTooltip(q.clientX,q.clientY,$);else this.hideTooltip();return}let K=null,M=Number.POSITIVE_INFINITY;for(let $ of this.hitItems){let Q=$.x-N,j=$.y-z,V=Q*Q+j*j;if(V<M)M=V,K=$}if(K&&M<3600)this.showTooltip(q.clientX,q.clientY,[K]);else this.hideTooltip()}findClosestByIndex(q){let J=-1,N=Number.POSITIVE_INFINITY;for(let z of this.hitItems){let Z=Math.abs(z.x-q);if(Z<N)N=Z,J=z.dataIndex}if(J<0)return null;return this.hitItems.filter((z)=>z.dataIndex===J)}showTooltip(q,J,N){if(!this.tooltipEl)this.tooltipEl=document.createElement("div"),Object.assign(this.tooltipEl.style,{position:"fixed",pointerEvents:"none",background:this.options.plugins?.tooltip?.backgroundColor??d,color:this.options.plugins?.tooltip?.bodyColor??"#fff",padding:"6px 10px",borderRadius:"6px",font:"12px system-ui, sans-serif",zIndex:"9999",whiteSpace:"pre-line",transform:"translate(8px, 8px)"}),document.body.appendChild(this.tooltipEl);let z=this.options.plugins?.tooltip?.callbacks,Z=[];N.forEach((Q)=>{let j=this.data.datasets[Q.datasetIndex];if(!j)return;let V={dataset:j,datasetIndex:Q.datasetIndex,dataIndex:Q.dataIndex,parsed:{y:Q.value},raw:Q.value,label:Q.label,formattedValue:R(Q.value)},H=z?.label?z.label(V):`${j.label??""}: ${R(Q.value)}`,S=Array.isArray(H)?H.join(`
3
- `):H;Z.push(S)});let K=z?.title?z.title(N.flatMap((Q)=>{let j=this.data.datasets[Q.datasetIndex];if(!j)return[];return[{dataset:j,datasetIndex:Q.datasetIndex,dataIndex:Q.dataIndex,parsed:{y:Q.value},raw:Q.value,label:Q.label,formattedValue:R(Q.value)}]})):N[0]?.label,M=Array.isArray(K)?K.join(`
2
+ import{scaleBand as h,scaleLinear as r}from"@ts-charts/scale";import{arc as x,area as n,curveLinear as p,curveMonotoneX as c,line as o,pie as d}from"@ts-charts/shape";var L=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#14b8a6","#f97316","#6366f1","#84cc16"];function F(q){return L[q%L.length]??L[0]}function T(q,J){if(q.startsWith("#")){let N=q.slice(1),z=Number.parseInt(N.slice(0,2),16),Z=Number.parseInt(N.slice(2,4),16),K=Number.parseInt(N.slice(4,6),16);return`rgba(${z}, ${Z}, ${K}, ${J})`}if(q.startsWith("rgb("))return q.replace("rgb(","rgba(").replace(")",`, ${J})`);return q}import{format as u}from"@ts-charts/format";import{scaleLinear as m}from"@ts-charts/scale";var b=m;function A(q,J,N=8){if(!Number.isFinite(q)||!Number.isFinite(J)||J<=q)return[Number.isFinite(q)?q:0];let Z=b().domain([q,J]).nice(N).ticks(N);if(Z.length===0)return[q,J];return Z}var g=u("~s");function R(q){if(!Number.isFinite(q))return"";if(Math.abs(q)>=1000)return g(q).replace("G","B").toUpperCase();if(Number.isInteger(q))return q.toString();return q.toFixed(2)}var f=r,a=h,l="rgba(148, 163, 184, 0.18)",I="#64748b",i="rgba(15, 23, 42, 0.92)";class w{static instances=new WeakMap;static register(...q){}type;data;options;canvas;ctx;resizeObserver=null;hitItems=[];tooltipEl=null;boundMove=(q)=>this.handleMouseMove(q);boundLeave=()=>this.hideTooltip();constructor(q,J){this.canvas=q instanceof HTMLCanvasElement?q:q.canvas;let N=this.canvas.getContext("2d");if(!N)throw Error("Chart: 2D canvas context unavailable");this.ctx=N,this.type=J.type,this.data=J.data,this.options=J.options??{},w.instances.set(this.canvas,this),this.attachInteractions(),this.observeResize(),this.render()}update(){this.render()}resize(){this.render()}destroy(){if(this.resizeObserver)this.resizeObserver.disconnect(),this.resizeObserver=null;if(this.canvas.removeEventListener("mousemove",this.boundMove),this.canvas.removeEventListener("mouseleave",this.boundLeave),this.tooltipEl?.parentNode)this.tooltipEl.parentNode.removeChild(this.tooltipEl);this.tooltipEl=null,this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),w.instances.delete(this.canvas)}observeResize(){if(this.options.responsive===!1||typeof ResizeObserver>"u")return;this.resizeObserver=new ResizeObserver(()=>this.render()),this.resizeObserver.observe(this.canvas.parentElement??this.canvas)}attachInteractions(){if(this.options.plugins?.tooltip?.enabled===!1)return;this.canvas.addEventListener("mousemove",this.boundMove),this.canvas.addEventListener("mouseleave",this.boundLeave)}syncCanvasSize(){let q=typeof window<"u"?window.devicePixelRatio||1:1,J=this.canvas.getBoundingClientRect(),N=J.width||this.canvas.clientWidth||this.canvas.width,z=J.height||this.canvas.clientHeight||this.canvas.height,Z=Math.max(1,Math.floor(N*q)),K=Math.max(1,Math.floor(z*q));if(this.canvas.width!==Z)this.canvas.width=Z;if(this.canvas.height!==K)this.canvas.height=K;return this.ctx.setTransform(q,0,0,q,0,0),{width:N,height:z}}render(){let{width:q,height:J}=this.syncCanvasSize();if(this.ctx.clearRect(0,0,q,J),this.hitItems=[],this.type==="doughnut"||this.type==="pie"){this.renderRadial(q,J);return}if(this.type==="radar"){this.renderCartesian(q,J,"line");return}this.renderCartesian(q,J,this.type)}renderCartesian(q,J,N){let z=this.data.labels??[],Z=this.data.datasets,K=this.layoutLegend(q,J),$=8+(this.options.plugins?.title?.display?24:0)+(K.position==="top"?K.h:0),Q=28+(K.position==="bottom"?K.h:0),j=48+(K.position==="left"?K.w:0),V=16+(K.position==="right"?K.w:0)+(this.hasRightAxis()?40:0),H={x:j,y:$,w:Math.max(1,q-j-V),h:Math.max(1,J-$-Q)};if(this.options.plugins?.title?.display&&this.options.plugins.title.text){let Y=this.options.plugins.title;this.ctx.fillStyle=Y.color??I,this.ctx.font=`${Y.font?.size??14}px system-ui, sans-serif`,this.ctx.textAlign="center",this.ctx.textBaseline="top",this.ctx.fillText(Y.text??"",q/2,8)}this.drawLegend(K,Z);let G=this.computeAxis(Z.filter((Y)=>(Y.yAxisID??"y")==="y"),"y"),P=this.hasRightAxis()?this.computeAxis(Z.filter((Y)=>Y.yAxisID==="y1"),"y1"):null;if(this.drawGridAndYAxis(H,G,"left"),P)this.drawYAxis(H,P,"right");if(this.drawXAxis(H,z),N==="bar")this.drawBars(H,z,Z,G,P);else this.drawLines(H,z,Z,G,P)}hasRightAxis(){return this.data.datasets.some((q)=>q.yAxisID==="y1")}computeAxis(q,J){let N=this.options.scales?.[J]??{},z=Number.POSITIVE_INFINITY,Z=Number.NEGATIVE_INFINITY;if(N.stacked){let M=this.data.labels??[];for(let $=0;$<M.length;$++){let Q=0,j=0;for(let V of q){let H=V.data[$]??0;if(H>=0)Q+=H;else j+=H}if(Q>Z)Z=Q;if(j<z)z=j}}else for(let M of q)for(let $ of M.data){if($<z)z=$;if($>Z)Z=$}if(!Number.isFinite(z))z=0;if(!Number.isFinite(Z))Z=1;if(N.beginAtZero!==!1&&z>0)z=0;if(N.min!==void 0)z=N.min;if(N.max!==void 0)Z=N.max;if(z===Z)Z=z+1;let K=A(z,Z,N.ticks?.maxTicksLimit??6);return{ticks:K,min:K[0]??z,max:K[K.length-1]??Z}}drawGridAndYAxis(q,J,N){let z=this.options.scales?.y??{},Z=z.grid?.display!==!1,K=z.ticks?.color??I,M=z.grid?.color??l;this.ctx.save(),this.ctx.font=`${z.ticks?.font?.size??11}px system-ui, sans-serif`,this.ctx.textBaseline="middle";for(let $ of J.ticks){let Q=this.scaleY(q,J,$);if(Z)this.ctx.strokeStyle=M,this.ctx.lineWidth=1,this.ctx.beginPath(),this.ctx.moveTo(q.x,Q),this.ctx.lineTo(q.x+q.w,Q),this.ctx.stroke();let j=z.ticks?.callback?z.ticks.callback($,J.ticks.indexOf($),J.ticks):R($);this.ctx.fillStyle=K,this.ctx.textAlign=N==="left"?"right":"left";let V=N==="left"?q.x-8:q.x+q.w+8;this.ctx.fillText(String(j),V,Q)}this.ctx.restore()}drawYAxis(q,J,N){let z=this.options.scales?.y1??{},Z=z.ticks?.color??I;this.ctx.save(),this.ctx.font=`${z.ticks?.font?.size??11}px system-ui, sans-serif`,this.ctx.textBaseline="middle";for(let K of J.ticks){let M=this.scaleY(q,J,K),$=z.ticks?.callback?z.ticks.callback(K,J.ticks.indexOf(K),J.ticks):R(K);this.ctx.fillStyle=Z,this.ctx.textAlign=N==="left"?"right":"left";let Q=N==="left"?q.x-8:q.x+q.w+8;this.ctx.fillText(String($),Q,M)}this.ctx.restore()}drawXAxis(q,J){let N=this.options.scales?.x??{},z=N.ticks?.color??I;if(N.display===!1||J.length===0)return;this.ctx.save(),this.ctx.font=`${N.ticks?.font?.size??11}px system-ui, sans-serif`,this.ctx.textBaseline="top",this.ctx.textAlign="center",this.ctx.fillStyle=z;let Z=Math.min(J.length,Math.max(2,Math.floor(q.w/60))),K=Math.max(1,Math.floor(J.length/Z));for(let M=0;M<J.length;M+=K){let $=this.scaleX(q,J.length,M);this.ctx.fillText(J[M]??"",$,q.y+q.h+8)}this.ctx.restore()}scaleX(q,J,N){if(J<=1)return q.x+q.w/2;return f().domain([0,J-1]).range([q.x,q.x+q.w])(N)}scaleY(q,J,N){if(J.max===J.min)return q.y+q.h/2;return f().domain([J.min,J.max]).range([q.y+q.h,q.y])(N)}drawLines(q,J,N,z,Z){N.forEach((K,M)=>{let $=K.yAxisID==="y1"&&Z?Z:z;if(K.type==="bar"){this.drawBarSeries(q,J,[K],z,Z);return}let Q=(typeof K.borderColor==="string"?K.borderColor:null)??F(M),j=K.backgroundColor&&typeof K.backgroundColor==="string"?K.backgroundColor:K.fill?T(Q,0.15):null,V=K.data.map((Y,S)=>({x:this.scaleX(q,J.length||K.data.length,S),y:this.scaleY(q,$,Y),value:Y}));if(V.length===0)return;let H=(K.tension??0)>0?c:p;if(j){let Y=q.y+q.h,S=n().x((B)=>B.x).y0(()=>Y).y1((B)=>B.y).curve(H).context(this.ctx);this.ctx.beginPath(),S(V),this.ctx.fillStyle=j,this.ctx.fill(),S.context(null)}let G=o().x((Y)=>Y.x).y((Y)=>Y.y).curve(H).context(this.ctx);this.ctx.beginPath(),G(V),this.ctx.lineWidth=K.borderWidth??2,this.ctx.strokeStyle=Q,this.ctx.lineJoin="round",this.ctx.lineCap="round",this.ctx.stroke(),G.context(null);let P=K.pointRadius??0;if(P>0){this.ctx.fillStyle=K.pointBackgroundColor??Q;for(let Y of V)this.ctx.beginPath(),this.ctx.arc(Y.x,Y.y,P,0,Math.PI*2),this.ctx.fill()}V.forEach((Y,S)=>{this.hitItems.push({datasetIndex:M,dataIndex:S,x:Y.x,y:Y.y,label:J[S]??String(S),value:Y.value})})})}drawBars(q,J,N,z,Z){this.drawBarSeries(q,J,N,z,Z)}drawBarSeries(q,J,N,z,Z){let K=J.length||(N[0]?.data.length??0);if(K===0)return;let $=!!this.options.scales?.y?.stacked,Q=Array.from({length:K},(G,P)=>P),j=a().domain(Q).range([q.x,q.x+q.w]).paddingInner(0.3),V=j.bandwidth(),H=$?V:V/Math.max(1,N.length);for(let G=0;G<K;G++){let P=j(G),Y=0,S=0;N.forEach((B,D)=>{let W=B.yAxisID==="y1"&&Z?Z:z,X=B.data[G]??0,U=$?X>=0?Y:S:0,O=U+X,C=this.scaleY(q,W,U),E=this.scaleY(q,W,O),_=$?P:P+D*H,k=Math.min(C,E),v=Math.abs(E-C),y=Array.isArray(B.backgroundColor)?B.backgroundColor[G]??F(D):typeof B.backgroundColor==="string"?B.backgroundColor:F(D);if(this.ctx.fillStyle=y,this.ctx.fillRect(_,k,Math.max(1,H-2),v),B.borderWidth&&B.borderColor&&typeof B.borderColor==="string")this.ctx.lineWidth=B.borderWidth,this.ctx.strokeStyle=B.borderColor,this.ctx.strokeRect(_,k,Math.max(1,H-2),v);if($)if(X>=0)Y=O;else S=O;this.hitItems.push({datasetIndex:D,dataIndex:G,x:_+H/2,y:k,label:J[G]??String(G),value:X})})}}renderRadial(q,J){let N=this.data.datasets;if(N.length===0)return;let z=N[0];if(!z)return;let Z=this.data.labels??[],K=this.layoutLegend(q,J),M=q,$=J,Q=0,j=0;if(K.position==="right")M=q-K.w;else if(K.position==="left")M=q-K.w,Q=K.w;else if(K.position==="top")$=J-K.h,j=K.h;else if(K.position==="bottom")$=J-K.h;this.drawLegend(K,N.map((X,U)=>({...X,label:Z[U]??X.label})),Z);let V=Q+M/2,H=j+$/2,G=Math.min(M,$)/2-8,P=this.options.cutout,Y=typeof P==="string"&&P.endsWith("%")?Number.parseFloat(P)/100:this.type==="doughnut"?0.6:0,S=G*Y,D=d().value((X)=>Math.max(0,X||0)).startAngle(-Math.PI/2).endAngle(-Math.PI/2+Math.PI*2).sort(null)(z.data),W=x().innerRadius(S).outerRadius(G);this.ctx.save(),this.ctx.translate(V,H);for(let X of D){let U=X.index,O=z.data[U]??0,C=Array.isArray(z.backgroundColor)?z.backgroundColor[U]??F(U):typeof z.backgroundColor==="string"?z.backgroundColor:F(U);this.ctx.beginPath(),W.context(this.ctx)(X),this.ctx.fillStyle=C,this.ctx.fill();let E=(X.startAngle+X.endAngle)/2-Math.PI/2,_=(G+S)/2;this.hitItems.push({datasetIndex:0,dataIndex:U,x:V+Math.cos(E)*_,y:H+Math.sin(E)*_,label:Z[U]??String(U),value:O})}this.ctx.restore(),W.context(null)}layoutLegend(q,J){let N=this.options.plugins?.legend;if(N?.display===!1||!this.data.datasets.some((Z)=>Z.label))return{w:0,h:0,position:"none"};let z=N?.position??"top";if(z==="left"||z==="right")return{w:100,h:0,position:z};return{w:0,h:Math.max(24,Math.ceil(this.data.datasets.length/4)*18+8),position:z}}drawLegend(q,J,N){if(q.position==="none")return;let z=this.options.plugins?.legend,Z=N&&(this.type==="pie"||this.type==="doughnut")?N.map(($,Q)=>{let j=J[0],V=Array.isArray(j?.backgroundColor)?j.backgroundColor[Q]??F(Q):typeof j?.backgroundColor==="string"?j.backgroundColor:F(Q);return{label:$,color:V}}):J.map(($,Q)=>({label:$.label??`Dataset ${Q+1}`,color:typeof $.borderColor==="string"?$.borderColor:Array.isArray($.backgroundColor)?$.backgroundColor[0]??F(Q):typeof $.backgroundColor==="string"?$.backgroundColor:F(Q)}));if(Z.length===0)return;this.ctx.save(),this.ctx.font=`${z?.labels?.font?.size??12}px system-ui, sans-serif`,this.ctx.fillStyle=z?.labels?.color??I,this.ctx.textBaseline="middle";let K=z?.labels?.boxWidth??12,M=z?.labels?.padding??8;if(q.position==="top"||q.position==="bottom"){let $=q.position==="top"?12:(this.canvas.clientHeight||0)-12,Q=M;this.ctx.textAlign="left";for(let j of Z)this.ctx.fillStyle=j.color,this.ctx.fillRect(Q,$-K/2,K,K),Q+=K+4,this.ctx.fillStyle=z?.labels?.color??I,this.ctx.fillText(j.label,Q,$),Q+=this.ctx.measureText(j.label).width+M*2}else{let $=q.position==="right"?(this.canvas.clientWidth||0)-110:8,Q=M+6;for(let j of Z)this.ctx.fillStyle=j.color,this.ctx.fillRect($,Q-K/2,K,K),this.ctx.fillStyle=z?.labels?.color??I,this.ctx.textAlign="left",this.ctx.fillText(j.label,$+K+4,Q),Q+=18}this.ctx.restore()}handleMouseMove(q){if(this.hitItems.length===0)return;let J=this.canvas.getBoundingClientRect(),N=q.clientX-J.left,z=q.clientY-J.top;if((this.options.interaction?.mode??this.options.plugins?.tooltip?.mode??"nearest")==="index"){let $=this.findClosestByIndex(N);if($)this.showTooltip(q.clientX,q.clientY,$);else this.hideTooltip();return}let K=null,M=Number.POSITIVE_INFINITY;for(let $ of this.hitItems){let Q=$.x-N,j=$.y-z,V=Q*Q+j*j;if(V<M)M=V,K=$}if(K&&M<3600)this.showTooltip(q.clientX,q.clientY,[K]);else this.hideTooltip()}findClosestByIndex(q){let J=-1,N=Number.POSITIVE_INFINITY;for(let z of this.hitItems){let Z=Math.abs(z.x-q);if(Z<N)N=Z,J=z.dataIndex}if(J<0)return null;return this.hitItems.filter((z)=>z.dataIndex===J)}showTooltip(q,J,N){if(!this.tooltipEl)this.tooltipEl=document.createElement("div"),Object.assign(this.tooltipEl.style,{position:"fixed",pointerEvents:"none",background:this.options.plugins?.tooltip?.backgroundColor??i,color:this.options.plugins?.tooltip?.bodyColor??"#fff",padding:"6px 10px",borderRadius:"6px",font:"12px system-ui, sans-serif",zIndex:"9999",whiteSpace:"pre-line",transform:"translate(8px, 8px)"}),document.body.appendChild(this.tooltipEl);let z=this.options.plugins?.tooltip?.callbacks,Z=[];N.forEach((Q)=>{let j=this.data.datasets[Q.datasetIndex];if(!j)return;let V={dataset:j,datasetIndex:Q.datasetIndex,dataIndex:Q.dataIndex,parsed:{y:Q.value},raw:Q.value,label:Q.label,formattedValue:R(Q.value)},H=z?.label?z.label(V):`${j.label??""}: ${R(Q.value)}`,G=Array.isArray(H)?H.join(`
3
+ `):H;Z.push(G)});let K=z?.title?z.title(N.flatMap((Q)=>{let j=this.data.datasets[Q.datasetIndex];if(!j)return[];return[{dataset:j,datasetIndex:Q.datasetIndex,dataIndex:Q.dataIndex,parsed:{y:Q.value},raw:Q.value,label:Q.label,formattedValue:R(Q.value)}]})):N[0]?.label,M=Array.isArray(K)?K.join(`
4
4
  `):K;if(this.tooltipEl.textContent="",M){let Q=document.createElement("strong");Q.textContent=M,this.tooltipEl.appendChild(Q),this.tooltipEl.appendChild(document.createElement("br"))}let $=document.createTextNode(Z.join(`
5
- `));this.tooltipEl.appendChild($),this.tooltipEl.style.left=`${q}px`,this.tooltipEl.style.top=`${J}px`,this.tooltipEl.style.display="block"}hideTooltip(){if(this.tooltipEl)this.tooltipEl.style.display="none"}}var Zq=w,Nq=[];export{T as withAlpha,Nq as registerables,F as paletteColor,A as niceTicks,R as formatTick,Zq as default,C as DEFAULT_PALETTE,w as Chart};
5
+ `));this.tooltipEl.appendChild($),this.tooltipEl.style.left=`${q}px`,this.tooltipEl.style.top=`${J}px`,this.tooltipEl.style.display="block"}hideTooltip(){if(this.tooltipEl)this.tooltipEl.style.display="none"}}var Mq=w,$q=[];export{T as withAlpha,$q as registerables,F as paletteColor,A as niceTicks,R as formatTick,Mq as default,L as DEFAULT_PALETTE,w as Chart};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/charts",
3
3
  "type": "module",
4
- "version": "0.70.73",
4
+ "version": "0.70.74",
5
5
  "description": "Chart rendering for Stacks. Built on ts-charts (D3 in TypeScript).",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [
@@ -58,6 +58,6 @@
58
58
  "@ts-charts/shape": "^0.2.0"
59
59
  },
60
60
  "devDependencies": {
61
- "better-dx": "^0.2.12"
61
+ "better-dx": "^0.2.16"
62
62
  }
63
63
  }