@stacksjs/charts 0.70.87 → 0.70.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/charts",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.87",
5
+ "version": "0.70.88",
6
6
  "description": "Chart rendering for Stacks. Built on ts-charts (D3 in TypeScript).",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
package/dist/chart.d.ts DELETED
@@ -1,22 +0,0 @@
1
- import type { ChartConfig, ChartData, ChartOptions, ChartType } from './types';
2
- /**
3
- * Chart.js-compatible adapter rendering to HTML5 Canvas.
4
- *
5
- * Supports the dashboard subset: line / bar / doughnut / pie, with
6
- * responsive sizing, scales (beginAtZero / stacked / grid / ticks /
7
- * y1 dual-axis), legends, and tooltip callbacks. Advanced features
8
- * (radar, animations, plugins) are no-ops rather than crashes.
9
- */
10
- export declare class Chart {
11
- static instances: unknown;
12
- static register(..._items: unknown[]): void;
13
- type: ChartType;
14
- data: ChartData;
15
- options: ChartOptions;
16
- canvas: HTMLCanvasElement;
17
- ctx: CanvasRenderingContext2D;
18
- constructor(target: HTMLCanvasElement | CanvasRenderingContext2D, config: ChartConfig);
19
- update(): void;
20
- resize(): void;
21
- destroy(): void;
22
- }
package/dist/colors.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare function paletteColor(index: number): string;
2
- export declare function withAlpha(color: string, alpha: number): string;
3
- /** @defaultValue `[ '#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#14b8a6', '#f97316', '#6366f1', '#84cc16', ]` */
4
- export declare const DEFAULT_PALETTE: string[];
package/dist/index.d.ts DELETED
@@ -1,24 +0,0 @@
1
- import { Chart } from './chart';
2
- export type {
3
- ChartConfig,
4
- ChartData,
5
- ChartDataset,
6
- ChartOptions,
7
- ChartType,
8
- LegendConfig,
9
- ScaleConfig,
10
- TooltipCallbackContext,
11
- TooltipConfig,
12
- } from './types';
13
- /**
14
- * Chart.js compatibility shim — `chart.js/auto` exposes a `registerables`
15
- * array used to opt-in to all chart types and plugins. We auto-register
16
- * everything by default, so the shim is intentionally empty; export it
17
- * so existing call sites that destructure `{ Chart, registerables }` and
18
- * call `Chart.register(...registerables)` keep working unchanged.
19
- */
20
- export declare const registerables: unknown[];
21
- export { Chart };
22
- export { DEFAULT_PALETTE, paletteColor, withAlpha } from './colors';
23
- export { formatTick, niceTicks } from './ticks';
24
- export default Chart;
package/dist/index.js DELETED
@@ -1,5 +0,0 @@
1
- // @bun
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
- `):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 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/dist/ticks.d.ts DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * Compute "nice" tick values for a numeric range.
3
- *
4
- * Delegates to `@ts-charts/scale`'s `scaleLinear().nice().ticks()` so we
5
- * inherit the same 1/2/5×10ⁿ progression D3 has battle-tested for a decade.
6
- */
7
- export declare function niceTicks(min: number, max: number, count?: number): number[];
8
- /**
9
- * Format a tick value compactly. Uses ts-charts SI notation (`1.5k`, `2.5M`)
10
- * which is what the dashboards expect, falling back to integer/2dp for
11
- * values under 1000.
12
- */
13
- export declare function formatTick(value: number): string;
package/dist/types.d.ts DELETED
@@ -1,87 +0,0 @@
1
- export declare interface ChartDataset {
2
- label?: string
3
- data: number[]
4
- backgroundColor?: string | string[] | CanvasGradient
5
- borderColor?: string | string[] | CanvasGradient
6
- borderWidth?: number
7
- fill?: boolean
8
- tension?: number
9
- pointRadius?: number
10
- pointBackgroundColor?: string
11
- pointBorderColor?: string
12
- stack?: string
13
- yAxisID?: string
14
- type?: ChartType
15
- }
16
- export declare interface ChartData {
17
- labels?: string[]
18
- datasets: ChartDataset[]
19
- }
20
- export declare interface ScaleConfig {
21
- beginAtZero?: boolean
22
- display?: boolean
23
- stacked?: boolean
24
- grid?: { display?: boolean, color?: string, drawBorder?: boolean }
25
- ticks?: {
26
- color?: string
27
- font?: { size?: number, family?: string }
28
- callback?: (value: number, index: number, ticks: any[]) => string
29
- stepSize?: number
30
- maxTicksLimit?: number
31
- }
32
- min?: number
33
- max?: number
34
- position?: 'left' | 'right' | 'top' | 'bottom'
35
- title?: { display?: boolean, text?: string, color?: string }
36
- }
37
- export declare interface LegendConfig {
38
- display?: boolean
39
- position?: 'top' | 'right' | 'bottom' | 'left'
40
- align?: 'start' | 'center' | 'end'
41
- labels?: { color?: string, font?: { size?: number }, boxWidth?: number, padding?: number }
42
- }
43
- export declare interface TooltipCallbackContext {
44
- dataset: ChartDataset
45
- datasetIndex: number
46
- dataIndex: number
47
- parsed: { x?: number, y: number }
48
- raw: number
49
- label: string
50
- formattedValue: string
51
- }
52
- export declare interface TooltipConfig {
53
- enabled?: boolean
54
- mode?: 'index' | 'point' | 'nearest' | 'dataset'
55
- intersect?: boolean
56
- callbacks?: {
57
- label?: (ctx: TooltipCallbackContext) => string | string[]
58
- title?: (ctx: TooltipCallbackContext[]) => string | string[]
59
- }
60
- backgroundColor?: string
61
- titleColor?: string
62
- bodyColor?: string
63
- borderColor?: string
64
- borderWidth?: number
65
- padding?: number
66
- }
67
- export declare interface ChartOptions {
68
- responsive?: boolean
69
- maintainAspectRatio?: boolean
70
- cutout?: string | number
71
- interaction?: { mode?: 'index' | 'point' | 'nearest' | 'dataset', intersect?: boolean }
72
- scales?: Record<string, ScaleConfig>
73
- plugins?: {
74
- legend?: LegendConfig
75
- tooltip?: TooltipConfig
76
- title?: { display?: boolean, text?: string, color?: string, font?: { size?: number } }
77
- }
78
- animation?: false | { duration?: number }
79
- layout?: { padding?: number | { top?: number, right?: number, bottom?: number, left?: number } }
80
- }
81
- export declare interface ChartConfig {
82
- type: ChartType
83
- data: ChartData
84
- options?: ChartOptions
85
- }
86
- export type ChartType = 'line' | 'bar' | 'doughnut' | 'pie' | 'radar';
87
- export type CanvasContext = HTMLCanvasElement | CanvasRenderingContext2D;