@graphysdk/node-renderer 2.0.0-beta.1786389736654 → 2.0.0-beta.1787130761469
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -55
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +460 -415
- package/licenses/PolyForm-Free-Trial-1.0.0.md +93 -0
- package/licenses/PolyForm-NonCommercial-1.0.0.md +131 -0
- package/licenses/PolyForm-Small-Business-1.0.0.md +121 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,88 +1,63 @@
|
|
|
1
1
|
# @graphysdk/node-renderer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Render a Graphy chart to a PNG in Node.js.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
- [Provider and renderer](https://docs.graphy.dev/sdk-next/rendering/provider-and-renderer)
|
|
8
|
-
- [Quickstart](https://docs.graphy.dev/sdk-next/quickstart)
|
|
9
|
-
|
|
10
|
-
## Serverless (Lambda, Vercel, etc.)
|
|
11
|
-
|
|
12
|
-
This package is designed for ephemeral Node runtimes:
|
|
5
|
+
## Install
|
|
13
6
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- **No temp files:** Rendering is in-memory (`Buffer` in, PNG `Buffer` out).
|
|
17
|
-
- **Inter via npm:** Default fonts load from `@fontsource/inter` at runtime using `require.resolve` (WOFF files in `node_modules`). No writable disk or checked-in TTFs required.
|
|
18
|
-
|
|
19
|
-
Host apps using Nitro, esbuild, or similar should treat `@graphysdk/node-renderer`, `@napi-rs/canvas`, and `@fontsource/inter` as **external** runtime dependencies (same as other native addons). For Nitro on Vercel, include `@fontsource/inter` in `traceDeps` so font files are copied into the function bundle:
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
traceDeps: ['@graphysdk/node-renderer', '@napi-rs/canvas', '@fontsource/inter'],
|
|
7
|
+
```bash
|
|
8
|
+
npm install @graphysdk/node-renderer @graphysdk/viz-engine
|
|
23
9
|
```
|
|
24
10
|
|
|
25
|
-
## Fonts
|
|
26
|
-
|
|
27
|
-
Text measurement and drawing use the same `@napi-rs/canvas` context with family **`Inter`** (aligned with the browser renderer).
|
|
28
|
-
|
|
29
|
-
1. **Default (automatic):** `ensureDefaultFonts()` registers Latin Inter 400 and 600 from `@fontsource/inter` on first render. Works on Vercel as long as `@fontsource/inter` is installed (declared as a dependency of this package).
|
|
30
|
-
|
|
31
|
-
2. **Optional `assets/` override:** place TTF files at `assets/Inter-Regular.ttf` and `assets/Inter-SemiBold.ttf` beside the installed package if you need custom binaries instead of Fontsource.
|
|
32
|
-
|
|
33
|
-
3. **In-memory:** pass `fonts` in `RenderOptions` or call `registerFont({ family, data: Buffer })`. Optional `weight` / `style` on `FontRegistration` are dedup-cache keys only — Skia reads metrics from the font bytes.
|
|
34
|
-
|
|
35
|
-
Without registered fonts, Skia uses built-in fallbacks; layout may differ from the browser renderer.
|
|
36
|
-
|
|
37
11
|
## Usage
|
|
38
12
|
|
|
39
|
-
### Low-level spec API
|
|
40
|
-
|
|
41
13
|
```ts
|
|
42
14
|
import { renderGraphToPng } from '@graphysdk/node-renderer';
|
|
43
15
|
import { createSpec, geom, pipe, scale } from '@graphysdk/viz-engine';
|
|
44
16
|
|
|
45
17
|
const input = pipe(createSpec({ x: 'category', y: 'value' }), geom.bar(), scale.x(), scale.y());
|
|
46
18
|
|
|
47
|
-
const png = await renderGraphToPng({ input, data }, { width: 1200, height: 800,
|
|
19
|
+
const png = await renderGraphToPng({ input, data }, { width: 1200, height: 800, colorScheme: 'light' });
|
|
48
20
|
```
|
|
49
21
|
|
|
50
|
-
|
|
22
|
+
## Docs
|
|
23
|
+
|
|
24
|
+
- [Quickstart](https://docs.graphy.dev/sdk-next/quickstart) — React apps start with [`@graphysdk/react`](https://www.npmjs.com/package/@graphysdk/react)
|
|
51
25
|
|
|
52
|
-
|
|
26
|
+
## GraphConfig
|
|
27
|
+
|
|
28
|
+
If you already have a stored chart config (`{ type, data, … }`), render it with `renderChartConfigToPng`. Check `canRenderConfigWithCanvas` first — some chart types are not supported.
|
|
53
29
|
|
|
54
30
|
```ts
|
|
55
31
|
import { canRenderConfigWithCanvas, renderChartConfigToPng } from '@graphysdk/node-renderer';
|
|
56
32
|
|
|
57
33
|
const capability = canRenderConfigWithCanvas(storedConfig);
|
|
58
34
|
if (!capability.ok) {
|
|
59
|
-
//
|
|
35
|
+
// use another export path
|
|
60
36
|
}
|
|
61
37
|
|
|
62
|
-
const png = await renderChartConfigToPng(storedConfig, { width: 1200, height: 800,
|
|
38
|
+
const png = await renderChartConfigToPng(storedConfig, { width: 1200, height: 800, colorScheme: 'light' });
|
|
63
39
|
```
|
|
64
40
|
|
|
65
|
-
|
|
41
|
+
Supported types: `column`, `columnStacked`, `columnStackedFill`, `bar`, `barStacked`, `barStackedFill`, `line`, `areaStacked`, `pie`, `donut`, `scatter`, `bubble`, `combo`.
|
|
66
42
|
|
|
67
|
-
|
|
43
|
+
Not supported: `funnel`, `heatmap`, `waterfall`, `mekko`, `table`.
|
|
68
44
|
|
|
69
|
-
|
|
70
|
-
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
71
|
-
| **Supported `type`** | `column`, `columnStacked`, `columnStackedFill`, `bar`, `barStacked`, `barStackedFill`, `line`, `areaStacked`, `pie`, `donut`, `scatter`, `bubble`, `combo` |
|
|
72
|
-
| **Unsupported `type`** | `funnel`, `heatmap`, `waterfall`, `mekko`, `table` (viz-engine throws) |
|
|
73
|
-
| **Canvas geoms** | Cartesian: bar, line, area, point, rule — Polar: bar (pie/donut) |
|
|
74
|
-
| **Rejected up front** | `_unstable_mapping`; `referenceLines.trendline` / `referenceLines.averageLine` |
|
|
75
|
-
| **Supported referenceLines** | `goalLine` (compiled to `geom.rule`) |
|
|
76
|
-
| **Legend display** | `pill` (color, stacked swatches, bubble/size); `direct` (series labels on panel edge) |
|
|
77
|
-
| **Lossy at compile** | Annotations, `themeOverrides`, series styles, headline numbers (see viz-engine `graph-config.converter`) |
|
|
78
|
-
| **Visual deltas vs browser** | Font metrics, anti-aliasing |
|
|
45
|
+
Annotations, theme overrides, series styles, and headline numbers may be dropped or simplified in the PNG.
|
|
79
46
|
|
|
80
|
-
`CANVAS_SUPPORTED_GRAPH_TYPES
|
|
47
|
+
The package also exports `CANVAS_SUPPORTED_GRAPH_TYPES` and `canRenderConfigWithCanvas` for checks in your own code.
|
|
81
48
|
|
|
82
|
-
##
|
|
49
|
+
## Fonts
|
|
83
50
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
51
|
+
Latin Inter 400 and 600 load automatically.
|
|
52
|
+
|
|
53
|
+
To use your own fonts, pass `fonts` when rendering or call `registerFont({ family, data })`.
|
|
54
|
+
|
|
55
|
+
## Serverless
|
|
56
|
+
|
|
57
|
+
This package uses a native canvas module. Install it as a normal dependency — do not bundle it into your function.
|
|
87
58
|
|
|
88
|
-
|
|
59
|
+
On Vercel with Nitro, include these in `traceDeps` so binaries and fonts are copied into the function:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
traceDeps: ['@graphysdk/node-renderer', '@napi-rs/canvas', '@fontsource/inter'];
|
|
63
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var it=Object.create;var ue=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames;var lt=Object.getPrototypeOf,dt=Object.prototype.hasOwnProperty;var ct=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of at(t))!dt.call(e,i)&&i!==n&&ue(e,i,{get:()=>t[i],enumerable:!(o=st(t,i))||o.enumerable});return e};var ut=(e,t,n)=>(n=e!=null?it(lt(e)):{},ct(t||!e||!e.__esModule?ue(n,"default",{value:e,enumerable:!0}):n,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const fe=require("node:fs"),Le=require("node:module"),D=require("node:path"),ft=require("node:url"),gt=require("@graphysdk/viz-engine/graph-config"),N=require("d3-shape"),c=require("@graphysdk/viz-engine"),ht=require("node:buffer");var w=typeof document<"u"?document.currentScript:null;let U,J;const _e=()=>U?Promise.resolve(U):(J??=import("@napi-rs/canvas").then(e=>(U=e,e)).catch(e=>{throw J=void 0,e}),J),W=()=>{if(!U)throw new Error("Canvas runtime is not loaded. Call loadCanvasRuntime() before rendering.");return U},y="Inter",x=new Set;let ge=!1,q=!1;const we=e=>`${e.family}|${e.weight??400}|${e.style??"normal"}`,re=e=>{const t=we(e);x.has(t)||(W().GlobalFonts.register(e.data,e.family),x.add(t))},mt=[{file:"Inter-Regular.ttf",family:y,weight:400},{file:"Inter-SemiBold.ttf",family:y,weight:600}],bt=[{file:"inter-latin-400-normal.woff",family:y,weight:400},{file:"inter-latin-600-normal.woff",family:y,weight:600}],At="@fontsource/inter",pt=()=>{try{const e=Le.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:w&&w.tagName.toUpperCase()==="SCRIPT"&&w.src||new URL("index.cjs",document.baseURI).href),t=D.dirname(e.resolve("@graphysdk/node-renderer/package.json"));return D.join(t,"assets")}catch{return D.resolve(D.dirname(ft.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:w&&w.tagName.toUpperCase()==="SCRIPT"&&w.src||new URL("index.cjs",document.baseURI).href)),"../assets")}},Ce=(e,t,n)=>{try{return fe.existsSync(e)?(re({family:t,data:fe.readFileSync(e),weight:n}),!0):!1}catch{return!1}},Tt=()=>{const e=pt();for(const{file:t,family:n,weight:o}of mt)Ce(D.join(e,t),n,o)&&(q=!0)},St=()=>{const e=Le.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:w&&w.tagName.toUpperCase()==="SCRIPT"&&w.src||new URL("index.cjs",document.baseURI).href);for(const{file:t,family:n,weight:o}of bt)if(!x.has(we({family:n,data:Buffer.alloc(0),weight:o})))try{const i=e.resolve(`${At}/files/${t}`);Ce(i,n,o)&&(q=!0)}catch{}},Ie=()=>(ge||(ge=!0,Tt(),St()),q),C=(e,t)=>e.x+t*e.width,_=(e,t)=>e.y+(1-t)*e.height,ee=e=>e==="catmull-rom"?N.curveCatmullRom:N.curveLinear,Be=e=>{switch(e){case"dashed":return[8,4];case"dotted":return[2,2];case"solid":return[]}},k=e=>e,yt=(e,t)=>t!=="connect"?e:e.filter(n=>c.getX(n)!==null&&c.getY(n)!==null),Rt=(e,t,n)=>{const o=ee(t.interpolate),i=N.area().curve(o),r=N.line().curve(o);if(e.mainAxis==="y"){const s=l=>_(n,c.getY(l)??0),a=l=>C(n,c.getXMin(l)??0),d=l=>C(n,c.getXMax(l)??c.getX(l)??0);i.y(s).x0(a).x1(d),r.y(s).x(d)}else{const s=l=>C(n,c.getX(l)??0),a=l=>_(n,c.getYMin(l)??0),d=l=>_(n,c.getYMax(l)??c.getY(l)??0);i.x(s).y0(a).y1(d),r.x(s).y(d)}if(t.missingValues==="gap"){const s=a=>c.getX(a)!==null&&c.getY(a)!==null;i.defined(s),r.defined(s)}return{areaGenerator:i,lineGenerator:r}},Et=k({geom:"area",coord:"cartesian",draw:(e,{layer:t,coordSystem:n,panel:o,colorScheme:i})=>{const r=c.createStyleResolver({colorScheme:i}).geomReaders(t),{areaGenerator:s,lineGenerator:a}=Rt(n,t.params,o),d=e;t.data.groupBy(c.GROUP_VARIABLES.group).forEach(l=>{const u=yt([...l],t.params.missingValues),f=u[0];if(!f)return;const g=r.get("color",f),h=r.get("alpha",f),m=r.get("strokeWidth",f),A=Be(r.get("lineType",f));e.save(),e.globalAlpha=h,e.fillStyle=g,e.beginPath(),s.context(d)(u),e.fill(),e.restore(),e.save(),e.globalAlpha=r.get("strokeAlpha",f),e.strokeStyle=g,e.lineWidth=m,e.setLineDash(A),e.lineJoin="round",e.lineCap="round",e.beginPath(),a.context(d)(u),e.stroke(),e.restore()})}}),he=(e,t,n,o,i,r)=>{const s=Math.max(0,Math.min(r.rx??r.ry??0,o/2)),a=Math.max(0,Math.min(r.ry??r.rx??0,i/2)),d=Math.PI/2;e.moveTo(t+s,n),e.lineTo(t+o-s,n),e.ellipse(t+o-s,n+a,s,a,0,-d,0),e.lineTo(t+o,n+i-a),e.ellipse(t+o-s,n+i-a,s,a,0,0,d),e.lineTo(t+s,n+i),e.ellipse(t+s,n+i-a,s,a,0,d,Math.PI),e.lineTo(t,n+a),e.ellipse(t+s,n+a,s,a,0,Math.PI,Math.PI*1.5),e.closePath()},Lt=k({geom:"bar",coord:"cartesian",draw:(e,{layer:t,coordSystem:n,panel:o,colorScheme:i})=>{const{Path2D:r}=W(),s=c.createStyleResolver({colorScheme:i}).geomReaders(t),a=n.mainAxis,d=new Map;for(const l of t.data){const u=c.getBarRectBounds(a,l);if(!u)continue;const f=C(o,u.x),g=o.y+u.y*o.height,h={x:f,y:g,width:u.width*o.width,height:u.height*o.height,fill:s.get("color",l),opacity:s.get("alpha",l)},m=c.buildColumnKey(a,u),A=d.get(m);A?A.bars.push(h):d.set(m,{bars:[h],style:{borderColor:s.get("borderColor",l),borderWidth:s.get("borderWidth",l),borderRadius:s.get("borderRadius",l),borderAlpha:s.get("alpha",l)}})}for(const{bars:l,style:u}of d.values()){const{borderColor:f,borderRadius:g,borderWidth:h,borderAlpha:m}=u,A=c.resolveBarBorderTreatment(h),p=g==="full"?void 0:c.resolveBarCornerRadiiPx({borderRadius:g,mainAxis:a});if(!(l.length>1)){const[b]=l;if(!b)continue;const v=p??c.resolveBarCornerRadiiPx({borderRadius:g,mainAxis:a,bounds:{width:b.width,height:b.height}}),E=new r;he(E,b.x,b.y,b.width,b.height,v),e.save(),e.globalAlpha=b.opacity,e.fillStyle=b.fill,e.fill(E),f!==void 0&&(e.clip(E),e.strokeStyle=f,e.lineWidth=A.outlineWidth,e.stroke(E)),e.restore();continue}const T=c.getBoundingRect(l),L=p??c.resolveBarCornerRadiiPx({borderRadius:g,mainAxis:a,bounds:{width:T.width,height:T.height}}),S=new r;he(S,T.x,T.y,T.width,T.height,L),e.save(),e.clip(S);for(const b of l)e.globalAlpha=b.opacity,e.fillStyle=b.fill,e.fillRect(b.x,b.y,b.width,b.height),f!==void 0&&(e.strokeStyle=f,e.lineWidth=A.separatorWidth,e.strokeRect(b.x,b.y,b.width,b.height));f!==void 0&&(e.globalAlpha=m,e.strokeStyle=f,e.lineWidth=A.outlineWidth,e.stroke(S)),e.restore()}}}),me=(e,t)=>{const n=/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(e.trim());if(n?.[1]!==void 0){const i=n[1],r=i.length===3?[...i].map(l=>l+l).join(""):i.slice(0,6),s=Number.parseInt(r.slice(0,2),16),a=Number.parseInt(r.slice(2,4),16),d=Number.parseInt(r.slice(4,6),16);return`rgba(${s}, ${a}, ${d}, ${t})`}const o=/^rgba?\(([^)]+)\)$/i.exec(e.trim());if(o?.[1]!==void 0){const i=o[1].split(",").map(d=>d.trim()),[r,s,a]=i;if(r!==void 0&&s!==void 0&&a!==void 0)return`rgba(${r}, ${s}, ${a}, ${t})`}return t===0?"rgba(0, 0, 0, 0)":e},_t=(e,t)=>t!=="connect"?e:e.filter(n=>c.getX(n)!==null&&c.getY(n)!==null),wt=(e,t)=>{const{seriesObservations:n,fillGenerator:o,panel:i,color:r,fillAlpha:s}=t,a=n.map(l=>c.getY(l)).filter(l=>l!==null).map(l=>_(i,l));if(a.length===0)return;const d=e.createLinearGradient(0,Math.min(...a),0,i.y+i.height);d.addColorStop(0,r),d.addColorStop(.7,me(r,0)),d.addColorStop(1,me(r,0)),e.save(),e.globalAlpha=s,e.fillStyle=d,e.beginPath(),o.context(e)(n),e.fill(),e.restore()},Ct=k({geom:"line",coord:"cartesian",draw:(e,{layer:t,panel:n,colorScheme:o})=>{const i=c.createStyleResolver({colorScheme:o}).geomReaders(t),r=N.line().x(a=>C(n,c.getX(a)??0)).y(a=>_(n,c.getY(a)??0)).curve(ee(t.params.interpolate)),s=N.area().x(a=>C(n,c.getX(a)??0)).y0(n.y+n.height).y1(a=>_(n,c.getY(a)??0)).curve(ee(t.params.interpolate));if(t.params.missingValues==="gap"){const a=d=>c.getX(d)!==null&&c.getY(d)!==null;r.defined(a),s.defined(a)}t.data.groupBy(c.GROUP_VARIABLES.group).forEach(a=>{const d=_t([...a],t.params.missingValues),l=d[0];if(!l)return;const u=i.get("strokeWidth",l),f=Be(i.get("lineType",l)),g=i.get("color",l),h=i.get("fillAlpha",l);h!==void 0&&wt(e,{seriesObservations:d,fillGenerator:s,panel:n,color:g,fillAlpha:h}),e.save(),e.globalAlpha=i.get("alpha",l),e.strokeStyle=g,e.lineWidth=u,e.setLineDash(f),e.lineJoin="round",e.lineCap="round",e.beginPath(),r.context(e)(d),e.stroke(),e.restore()})}}),It=k({geom:"point",coord:"cartesian",draw:(e,{layer:t,panel:n,colorScheme:o})=>{const i=c.createStyleResolver({colorScheme:o}).geomReaders(t);for(const r of t.data){const s=c.getX(r),a=c.getY(r);if(s===null||a===null)continue;const d=C(n,s),l=_(n,a),u=i.get("size",r)/2,f=i.get("borderWidth",r);e.save(),e.globalAlpha=i.get("alpha",r),e.fillStyle=i.get("color",r),e.strokeStyle=i.get("borderColor",r),e.lineWidth=f,e.beginPath(),e.arc(d,l,u,0,Math.PI*2),e.fill(),f>0&&e.stroke(),e.restore()}}}),ie=11,Bt="sans-serif",Nt=500,P=5,Ne=5,te=13,ve=6,V=12,be=21.6,vt=(e,t)=>{const n=e.mapping.y!==void 0,o=t.mainAxis==="y";return n!==o},Pt=(e,t,n)=>{const o=c.getRuleDashPattern(t,n);e.setLineDash(o),o.length>0&&(e.lineCap="round")},Ft=(e,t)=>X(e)&&X(t)?`${e}: ${t}`:X(e)?e:X(t)?t:null,X=e=>e!=null&&e.trim()!=="",kt=e=>{e.beginPath(),e.moveTo(2.48935,16.9323),e.lineTo(9.07098,9.82964),e.bezierCurveTo(9.51595,9.34944,9.51504,8.60728,9.0689,8.12818),e.lineTo(2.48866,1.06172),e.bezierCurveTo(1.85811,.384586,.974477,0,.049217,0),e.lineTo(0,0),e.lineTo(0,18),e.lineTo(.0443689,18),e.bezierCurveTo(.972463,18,1.85854,17.6131,2.48935,16.9323),e.closePath()},Pe=(e,t,n,o,i,r)=>{const s=Math.min(r,o/2,i/2);e.beginPath(),e.moveTo(t+s,n),e.lineTo(t+o-s,n),e.arcTo(t+o,n,t+o,n+s,s),e.lineTo(t+o,n+i-s),e.arcTo(t+o,n+i,t+o-s,n+i,s),e.lineTo(t+s,n+i),e.arcTo(t,n+i,t,n+i-s,s),e.lineTo(t,n+s),e.arcTo(t,n,t+s,n,s),e.closePath(),e.fill()},Dt=(e,t,n,o,i,r,s,a)=>{const d=n+P*2,l=ie+Ne*2,u=o==="start",f=u?r.x:r.x+r.width,g=_(r,i),h=u?-te:-(d-te),m=u?h+d-P:h+P-V;e.save(),e.translate(f,g),e.translate(0,-l/2),e.fillStyle=s,Pe(e,h,0,d,l,ve),e.save(),u||(e.translate(m+V/2,l/2),e.rotate(Math.PI),e.translate(-(m+V/2),-l/2)),e.translate(m,(l-be)/2),e.scale(V/10,be/18),e.fillStyle=s,kt(e),e.fill(),e.restore(),e.fillStyle=a,e.textAlign="left",e.textBaseline="middle",e.fillText(t,h+P,l/2),e.restore()},Ot=(e,t,n,o,i,r,s,a)=>{const d=n+P*2,l=ie+Ne*2,u=o==="start",f=C(r,i),g=u?r.y+r.height:r.y,h=u?-te:-8;e.save(),e.translate(f,g),e.translate(-d/2,0),e.fillStyle=s,Pe(e,0,h,d,l,ve),e.fillStyle=a,e.textAlign="left",e.textBaseline="middle",e.fillText(t,P,h+l/2),e.restore()},Ut=k({geom:"rule",coord:"cartesian",draw:(e,{layer:t,coordSystem:n,panel:o,compiled:i,textMeasurer:r,formattingLocale:s,colorScheme:a})=>{const d=t.data.getFirst();if(!d)return;const l=vt(t,n),u=l?c.getY(d):c.getX(d);if(u===null)return;const f=c.createStyleResolver({colorScheme:a}).geomReaders(t),g=f.get("color",d),h=c.getRuleLabelTextColor(g),m=f.get("strokeWidth",d);if(e.save(),e.strokeStyle=g,e.lineWidth=m,Pt(e,f.get("lineType",d),m),e.beginPath(),l){const S=_(o,u);e.moveTo(o.x,S),e.lineTo(o.x+o.width,S)}else{const S=C(o,u);e.moveTo(S,o.y),e.lineTo(S,o.y+o.height)}e.stroke(),e.restore();const A=Ft(t.params.label,c.formatRuleValue({guides:i.guides,numberFormat:i.config.numberFormat,layer:t,locale:s??i.config.parsingLocale}));if(A===null)return;const p=i.config.appearance.textScale,R={family:Bt,size:ie*p,weight:Nt};e.font=c.buildFontString(R);const T=r.measureText(A,R).width;(l?Dt:Ot)(e,A,T,t.params.labelPosition,u,o,g,h)}}),O=N.arc();O.digits(8);const Ht=k({geom:"bar",coord:"polar",draw:(e,{layer:t,coordSystem:n,panel:o,colorScheme:i})=>{const r=o.x+o.width/2,s=o.y+o.height/2,a=Math.min(o.width,o.height)/2,{Path2D:d}=W(),l=c.createStyleResolver({colorScheme:i}).geomReaders(t);e.save(),e.translate(r,s),e.scale(a,a);const u=e,f=new Map;for(const g of t.data){const{startAngle:h,endAngle:m}=c.getAngleExtent(g),{innerRadius:A,outerRadius:p}=c.getRadiusExtent(g);if(h===null||m===null||A===null||p===null)continue;const R={startAngle:h,endAngle:m,innerRadius:A,outerRadius:p,fill:l.get("color",g),opacity:l.get("alpha",g)},T=c.buildSliceGroupKey(n.bandAxis,R),L=f.get(T);L?L.items.push(R):f.set(T,{items:[R],style:{borderColor:l.get("borderColor",g),borderWidth:l.get("borderWidth",g),borderRadius:l.get("borderRadius",g),borderAlpha:l.get("alpha",g)}})}for(const{items:g,style:h}of f.values()){const{borderColor:m,borderRadius:A,borderWidth:p,borderAlpha:R}=h,T=c.resolveBarBorderTreatment(p),L=m!==void 0&&a>0,S=c.getUnionExtent(g),b=c.resolvePolarBarCornerRadiusUnit(A,S.outerRadius-S.innerRadius),v=a>0&&(L||b>0);e.save();let E;v&&(E=new d,O.cornerRadius(b),O.context(E)(S),e.clip(E)),O.cornerRadius(0);for(const Q of g)e.globalAlpha=Q.opacity,e.fillStyle=Q.fill,e.beginPath(),O.context(u)(Q),e.fill(),L&&(e.strokeStyle=m,e.lineWidth=T.separatorWidth/a,e.stroke());L&&E&&(e.globalAlpha=R,e.strokeStyle=m,e.lineWidth=T.outlineWidth/a,e.stroke(E)),e.restore()}e.restore()}}),Mt={bar:{cartesian:Lt,polar:Ht},line:{cartesian:Ct},area:{cartesian:Et},point:{cartesian:It},rule:{cartesian:Ut}},Fe=(e,t)=>Mt[e.geom]?.[t.type]??null,Gt=(e,t,n)=>{e.draw(t,n)};let Ae;const ke=()=>(Ae??=c.createCompiler(),Ae),se=["line","areaStacked","bar","barStacked","barStackedFill","column","columnStacked","columnStackedFill","combo","pie","donut","scatter","bubble"],De=["funnel","heatmap","waterfall","mekko","table"],Wt=new Set(se),Vt={supportedGraphTypes:[...se],unsupportedGraphTypes:[...De],supportedGeoms:{cartesian:["bar","line","area","point","rule"],polar:["bar"]}},B=e=>({ok:!1,reason:e}),j=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Xt=e=>{if(!j(e))return!1;const{columns:t,rows:n}=e;return!Array.isArray(t)||!Array.isArray(n)?!1:t.every(o=>j(o)&&typeof o.key=="string")},Kt=e=>{if("_unstable_mapping"in e&&e._unstable_mapping!==void 0)return!0;const t=e.referenceLines;return j(t)?t.trendline!==void 0||t.averageLine!==void 0:!1},Oe=e=>{if(!j(e))return B("Chart config must be a plain object.");if(!Xt(e.data))return B("Chart config is missing a valid `data` object (columns + rows).");const{data:t,...n}=e;return{ok:!0,input:n,data:t}},Ue=e=>{const t=Oe(e);if(!t.ok)return t;if(Kt(e))return B("Canvas renderer does not support `_unstable_mapping`, `referenceLines.trendline`, or `referenceLines.averageLine`.");const n=t.input.type??"column";if(!Wt.has(n))return B(`Unsupported chart type for canvas rendering: ${n}.`);try{const o=ke(),i=gt.convertGraphConfig(t.input,t.data),r=o.compile({input:i,data:t.data});if(!r.ok)return B(`Chart config failed to compile: ${r.errors.map(s=>s.message).join("; ")}`);for(const s of r.compiled.layers)if(Fe(s,r.compiled.coordSystem)===null)return B(`No canvas geom renderer for ${s.geom} (${r.compiled.coordSystem.type} coord).`);return{ok:!0,compiled:r.compiled}}catch(o){const i=o instanceof Error?o.message:String(o);return B(`Chart config failed to compile: ${i}`)}},K=6,z=10,Yt=20,ae=y,le=12,He=y,H=12,de=1.3,M=10,G=12,F=6,Me=16,zt=24,Ge=6,We=3,ne=4,qt=8,jt="#9ca3af",Ve=16,Zt=1.3,Xe=13,Qt=1.4,Ke=12,Jt=1.4,Z=8,ce=12,$t=1.3,xt=200,en=120,tn=80,Ye=22,nn=9,on=11,rn=10,Y=9,pe=12,sn='-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif',an=11.5,ln=550,dn={light:.55,mid:.75,dark:.08},cn={light:.62,mid:.8,dark:.85},un=.22,fn=.65,gn=y,hn=12,mn={family:ae,size:le},bn={family:gn,size:hn},An={family:He,size:H},pn=8,Te=1,Tn=[2,3],Sn=[1,3],yn=(e,t,n,o,i)=>{if(!t.isVisible||t.ticks.length===0)return;const r=t.position==="bottom"||t.position==="top",s=t.ticksVisible?1:0;e.save(),e.font=c.buildFontString(mn),e.fillStyle=i.textSecondary,e.strokeStyle=i.gridLine,e.lineWidth=1,e.setLineDash([]);for(const a of t.ticks){const d=r?a.position:1-a.position;t.ticksVisible&&En(e,t.position,d,n,o),_n(e,t.position,d,n,o,a.formattedLabel,t.labelRotation,s)}e.restore()},Rn=(e,t,n,o)=>{if(e==="bottom"||e==="top"){const a=o.x+t*o.width,d=e==="top"?n.y+n.height:n.y,l=e==="top"?-K:K;return{x1:a,y1:d,x2:a,y2:d+l}}const i=o.y+t*o.height,r=e==="right"?n.x:n.x+n.width,s=e==="right"?K:-K;return{x1:r,y1:i,x2:r+s,y2:i}},En=(e,t,n,o,i)=>{const{x1:r,y1:s,x2:a,y2:d}=Rn(t,n,o,i);e.beginPath(),e.moveTo(r,s),e.lineTo(a,d),e.stroke()},Ln=(e,t,n,o,i)=>{if(e==="bottom"||e==="top"){const s=o.x+t*o.width;return e==="bottom"?{x:s,y:n.y+i,textAlign:"center",textBaseline:"top"}:{x:s,y:n.y+n.height-i,textAlign:"center",textBaseline:"alphabetic"}}const r=o.y+t*o.height;return e==="left"?{x:n.x+n.width-i,y:r,textAlign:"right",textBaseline:"middle"}:{x:n.x+i,y:r,textAlign:"left",textBaseline:"middle"}},_n=(e,t,n,o,i,r,s,a)=>{const d=z*a;if(s!==0&&(t==="top"||t==="bottom")){const u=i.x+n*i.width,f=t==="top";e.save(),e.translate(u,f?o.y+o.height-d:o.y+d),e.rotate(s*Math.PI/180),e.textAlign=f?"left":"right",e.textBaseline="middle",e.fillText(r,0,0),e.restore();return}const l=Ln(t,n,o,i,d);e.textAlign=l.textAlign,e.textBaseline=l.textBaseline,e.fillText(r,l.x,l.y)},wn=(e,t,n,o)=>{if(!t.isVisible||!t.label)return;e.save(),e.font=c.buildFontString(bn),e.fillStyle=o.textPrimary,e.textBaseline="middle";const{x:i,y:r,alignment:s}=Cn(t.position,n);e.textAlign=s,e.fillText(t.label,i,r),e.restore()},Cn=(e,t)=>{const n=t.y+t.height/2;return e==="left"?{x:t.x,y:n,alignment:"start"}:e==="right"?{x:t.x+t.width,y:n,alignment:"end"}:{x:t.x+t.width/2,y:n,alignment:"center"}},In="data:image/png;base64,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",I=Ye;let $;const Bn=()=>{if($)return $;const{Image:e}=W(),t=new e,n=In.replace(/^data:image\/png;base64,/,"");return t.src=ht.Buffer.from(n,"base64"),$=t,t},ze=(e,t,n="full")=>!e||t.width<en||t.height<tn?"hidden":t.width<xt||n==="mini"?"mini":"full",Nn=e=>{const t=vn(e);if(t===null)return"light";const n=Pn(t);return n<=un?"dark":n<=fn?"mid":"light"},oe=(e,t,n)=>e.placement!==n||ze(e.enabled,t,e.variant)==="hidden"?0:Ye,qe=(e,t,n,o,i,r)=>{if(t.placement!==r)return;const s=ze(t.enabled,i,t.variant);if(s==="hidden")return;const a=Nn(o.background),d=a==="dark",l={family:sn,size:an,weight:400},u={...l,weight:ln};let f=0;s==="full"&&(e.font=c.buildFontString(l),f=e.measureText("Made with ").width,e.font=c.buildFontString(u),f+=e.measureText("Graphy").width);const g=s==="mini"?0:nn,h=s==="mini"?0:on,m=s==="mini"?0:rn,A=s==="mini"?I:g+Y+m+f+h,p=n.x+n.width-A,R=n.y+Math.max(0,(n.height||I)/2-I/2);e.save(),e.globalAlpha=cn[a],e.textBaseline="middle",e.textAlign="left",d||(e.shadowColor="rgba(0, 0, 0, 0.09)",e.shadowBlur=4,e.shadowOffsetY=1),e.beginPath(),e.roundRect(p,R,A,I,I/2),e.fillStyle=`rgba(255, 255, 255, ${dn[a]})`,e.fill(),e.shadowColor="transparent",e.shadowBlur=0,e.shadowOffsetY=0;const T=d?"#FFFFFF":"#2A2A28",L=s==="mini"?p+(A-Y)/2:p+g,S=R+(I-pe)/2;if(e.save(),d&&(e.filter="invert(1)"),e.drawImage(Bn(),L,S,Y,pe),e.restore(),s==="full"){const b=p+g+Y+m,v=R+I/2;e.fillStyle=T,e.font=c.buildFontString(l),e.fillText("Made with ",b,v);const E=e.measureText("Made with ").width;e.font=c.buildFontString(u),e.fillText("Graphy",b+E,v)}e.restore()},vn=e=>{const t=e.trim();if(!t.startsWith("#"))return null;const n=t.slice(1);if(n.length===3){const o=n[0],i=n[1],r=n[2];return o===void 0||i===void 0||r===void 0?null:{red:Number.parseInt(o+o,16),green:Number.parseInt(i+i,16),blue:Number.parseInt(r+r,16)}}return n.length>=6?{red:Number.parseInt(n.slice(0,2),16),green:Number.parseInt(n.slice(2,4),16),blue:Number.parseInt(n.slice(4,6),16)}:null},Pn=({red:e,green:t,blue:n})=>{const o=i=>{const r=i/255;return r<=.03928?r/12.92:((r+.055)/1.055)**2.4};return .2126*o(e)+.7152*o(t)+.0722*o(n)},Fn={family:y,size:Ve,weight:600},kn={family:y,size:Xe},Dn={family:y,size:Ke},On={family:y,size:ce,weight:500},Un={family:y,size:ce},je=Ve*Zt,Hn=Xe*Qt,Ze=Ke*Jt,Qe=ce*$t,Je=e=>{if(e===null)return null;if(e.label!==void 0&&e.label!=="")return e.label;if(e.url!==void 0&&e.url!==""&&c.isSafeUrl(e.url))try{return new URL(e.url).hostname}catch{return e.url}return null},Mn=(e,t)=>{let n=0;const o=e.isTitleVisible&&e.title!==null,i=e.isSubtitleVisible&&e.subtitle!==null;o&&(n+=je),i&&(n>0&&(n+=Z),n+=Hn);const r=oe(e.brandMark,t,"header");!o&&!i&&r>0&&(n=r);const s=e.isCaptionVisible&&e.caption!==null,a=e.isSourceVisible&&Je(e.source)!==null,d=oe(e.brandMark,t,"footer");let l=0;return s&&(l+=Ze),(a||d>0)&&(l>0&&(l+=Z),l+=Math.max(Qe,d)),{headerHeight:n,footerHeight:l}},Gn=(e,t,n,o,i)=>{if(n.height===0)return;e.save(),e.textBaseline="top",e.textAlign="left";let r=n.y;t.isTitleVisible&&t.title!==null&&(e.font=c.buildFontString(Fn),e.fillStyle=o.textPrimary,e.fillText(c.extractPlainText(t.title),n.x,r),r+=je+Z),t.isSubtitleVisible&&t.subtitle!==null&&(e.font=c.buildFontString(kn),e.fillStyle=o.textSecondary,e.fillText(c.extractPlainText(t.subtitle),n.x,r)),e.restore(),qe(e,t.brandMark,n,o,i,"header")},Wn=(e,t,n,o,i)=>{if(n.height===0)return;const r=t.isCaptionVisible?t.caption:null,s=t.isSourceVisible?Je(t.source):null,a=oe(t.brandMark,i,"footer");if(r===null&&s===null&&a===0)return;e.save(),e.textBaseline="top",e.textAlign="left";let d=n.y;if(r!==null&&(e.font=c.buildFontString(Dn),e.fillStyle=o.textSecondary,e.fillText(c.extractPlainText(r),n.x,d),d+=Ze+Z),s!==null){let l=n.x;l=Se(e,"Source: ",On,o.textSecondary,l,d),Se(e,s,Un,o.textSecondary,l,d)}e.restore(),qe(e,t.brandMark,{x:n.x,y:d,width:n.width,height:Math.max(Qe,a)},o,i,"footer")},Se=(e,t,n,o,i,r)=>(e.font=c.buildFontString(n),e.fillStyle=o,e.fillText(t,i,r),i+e.measureText(t).width),Vn=(e,t,n,o,i)=>{e.save(),e.lineCap="round",e.strokeStyle=i.gridLine;for(const r of c.computePanelBorderPaths(n.border,o,pn))e.lineWidth=r.lineWidth??Te,e.setLineDash(ye(r.lineStyle)),Xn(e,r.segments),e.stroke();for(const r of t){if(!r.gridVisible)continue;const s=r.position==="top"||r.position==="bottom";e.lineWidth=r.gridLineWidth??Te,e.setLineDash(ye(r.gridLineStyle));for(const a of r.ticks){if(a.position<=0||a.position>=1)continue;const d=s?a.position:1-a.position;if(e.beginPath(),s){const l=o.x+d*o.width;e.moveTo(l,o.y),e.lineTo(l,o.y+o.height)}else{const l=o.y+d*o.height;e.moveTo(o.x,l),e.lineTo(o.x+o.width,l)}e.stroke()}}e.restore()},ye=e=>{switch(e){case"dashed":return Tn;case"dotted":return Sn;case"solid":return[]}},Xn=(e,t)=>{e.beginPath();for(const n of t)switch(n.type){case"move":e.moveTo(n.x,n.y);break;case"line":e.lineTo(n.x,n.y);break;case"arc":e.arc(n.cx,n.cy,n.radius,n.startAngle,n.endAngle);break;case"close":e.closePath();break}},Kn=(e,t,n,o)=>{e.save(),e.font=c.buildFontString(An),e.textBaseline="middle";for(const r of t)r.display==="direct"&&Yn(e,r,n,o);const i=new Map;for(const r of t){if(r.display!=="pill"||r.items.length===0)continue;const s=i.get(r.position);s?s.push(r):i.set(r.position,[r])}for(const[r,s]of i){const a=n[r];a&&(r==="top"||r==="bottom"?zn(e,s,a,o):qn(e,s,a,o))}e.restore()},Yn=(e,t,n,o)=>{const i=n[t.position];if(i){e.textAlign="left";for(const r of t.items)r.normalizedY!==null&&(e.fillStyle=typeof r.visual.color=="string"?r.visual.color:o.textPrimary,e.fillText(r.formattedLabel,i.x+qt,_(i,r.normalizedY)))}},zn=(e,t,n,o)=>{const i=$e(t),r=i.reduce((l,u,f)=>l+Zn(u)+e.measureText(u.label).width+(f===0?0:Re(u)),0),s=H*de;let a=n.x+Math.max(0,(n.width-r)/2);const d=n.y+Ge+Math.max(s,G)/2;for(let l=0;l<i.length;l++){const u=i[l];u&&(l>0&&(a+=Re(u)),a=xe(e,u,a,d,o))}},qn=(e,t,n,o)=>{const i=$e(t),r=Math.max(H*de,G),s=4,a=i.length*r+Math.max(0,i.length-1)*s;let d=n.y+Math.max(0,(n.height-a)/2)+r/2;for(const l of i)xe(e,l,n.x,d,o),d+=r+s},$e=e=>{const t=[];for(const n of e){const o=n.aesthetics.includes("size");n.items.forEach((i,r)=>{const s=i.visual.size,a=o&&typeof s=="number"&&Number.isFinite(s)&&s>0?s:void 0;t.push({label:i.formattedLabel,colors:jn(i.visual.color),bubbleSize:a,isFirstInGroup:r===0})})}return t},jn=e=>typeof e=="string"?[e]:Array.isArray(e)?e.filter(t=>typeof t=="string"):[],Re=e=>e.isFirstInGroup?zt:Me,Zn=e=>{if(e.bubbleSize!==void 0)return e.bubbleSize+F;const t=e.colors.length;if(t===0)return 0;if(t===1)return M+F;const n=Math.min(t,We);return M+(n-1)*ne+F},xe=(e,t,n,o,i)=>{let r=n;if(t.bubbleSize!==void 0){const s=t.bubbleSize/2;e.fillStyle=t.colors[0]??jt,e.beginPath(),e.arc(r+s,o,s,0,Math.PI*2),e.fill(),r+=t.bubbleSize+F}else if(t.colors.length>0){const s=t.colors.slice(0,We);for(let a=0;a<s.length;a++){const d=s[a];d&&(e.fillStyle=d,e.fillRect(r+a*ne,o-G/2,M,G))}r+=M+(s.length-1)*ne+F}return e.fillStyle=i.textPrimary,e.textAlign="left",e.fillText(t.label,r,o),r+e.measureText(t.label).width},Ee=(e,t)=>Math.min(Math.max(...e),t),Qn=e=>t=>{if(!t.isVisible||t.ticks.length===0)return 0;const n=t.position==="top"||t.position==="bottom",o=t.ticks.map(s=>e.measureText(s.formattedLabel,{family:ae,size:le})),i=t.labelMaxWidthPx??Number.POSITIVE_INFINITY;if(n){if(t.labelRotation!==0){const s=o.map(a=>a.width);return Ee(s,i)+2*z}return Math.max(...o.map(s=>s.height))+z}const r=o.map(s=>s.width);return Ee(r,i)+z},Jn=e=>t=>{if(t.items.length===0)return 0;const n={family:He,size:H};if(t.position==="top"||t.position==="bottom"){const r=H*de;return Math.max(r,G)+Ge*2}const i=t.items.map(r=>{const s=e.measureText(r.formattedLabel,n).width;return M+F+s});return Math.max(...i)+Me},$n=e=>(t,n)=>{const{labelLineHeight:o,labelFontWeight:i}=c.getDifferenceArrowDimensions(n,1);return e.measureText(t,{family:y,size:o,weight:i})},xn=e=>(t,n)=>{const{fontSize:o,fontWeight:i}=c.getDataLabelDimensions(t,1);return e.measureText(n,{family:y,size:o,weight:i})},eo=e=>({measureAxis:Qn(e),measureAxisLabel:()=>Yt,measureLegend:Jn(e),measureTickLabel:t=>e.measureText(t,{family:ae,size:le}),measureDifferenceArrowLabel:$n(e),measureDataLabel:xn(e),measureHeadline:()=>({width:0,height:0}),measureHeadlineItemWidths:()=>[]});class et{constructor(){this.currentFont="";const t=W().createCanvas(1,1);this.ctx=t.getContext("2d")}measureText(t,n){const o=c.buildFontString(n);this.currentFont!==o&&(this.ctx.font=o,this.currentFont=o);const i=this.ctx.measureText(t);return{width:i.width,height:i.fontBoundingBoxAscent+i.fontBoundingBoxDescent,ascent:i.fontBoundingBoxAscent,descent:i.fontBoundingBoxDescent}}}const tt={background:"#ffffff",textPrimary:"#111827",textSecondary:"#6b7280",gridLine:"#e5e7eb",panelBorder:"#d1d5db",legendPillBackground:"rgba(0, 0, 0, 0.04)",legendPillBorder:"rgba(0, 0, 0, 0.08)"},nt={background:"#0b0f17",textPrimary:"#e5e7eb",textSecondary:"#9ca3af",gridLine:"#1f2937",panelBorder:"#374151",legendPillBackground:"rgba(255, 255, 255, 0.06)",legendPillBorder:"rgba(255, 255, 255, 0.12)"},to=async({input:e,data:t},n)=>{const i=ke().compile({input:e,data:t});if(!i.ok)throw new Error(`Failed to compile graph spec: ${i.errors.map(r=>r.message).join("; ")}`);return ot(i.compiled,n)},ot=async(e,t)=>{const{Canvas:n}=await _e();if(Ie(),t.fonts)for(const p of t.fonts)re(p);const o=c.formatLegends({legends:e.guides.legends.drawn,numberFormat:e.config.numberFormat,parsingLocale:e.config.parsingLocale,formattingLocale:t.formattingLocale}),i={width:t.width,height:t.height},{headerHeight:r,footerHeight:s}=Mn(e.config.content,i),a={headerSize:{width:t.width,height:r},footerSize:{width:t.width,height:s}},d=new et,{layout:l,formattedAxes:u}=new c.LayoutCompiler(eo(d)).compile({axes:e.guides.axes,numberFormat:e.config.numberFormat,parsingLocale:e.config.parsingLocale,formattedLegends:o,containerSize:{width:t.width,height:t.height},externalMeasurements:a,formattingLocale:t.formattingLocale,layout:e.config.layout}),f=t.pixelRatio??2,g=new n(t.width*f,t.height*f),h=g.getContext("2d");h.scale(f,f);const m=t.colorScheme??"light";return no(h,m==="dark"?nt:tt,m,t.width,t.height,e,u,o,l,d,t.formattingLocale),g.encode("png")},no=(e,t,n,o,i,r,s,a,d,l,u)=>{e.fillStyle=t.background,e.fillRect(0,0,o,i),Vn(e,s,r.guides.panel,d.panel,t),e.save(),e.beginPath(),e.rect(d.panel.x,d.panel.y,d.panel.width,d.panel.height),e.clip();const f={coordSystem:r.coordSystem,panel:d.panel,compiled:r,theme:t,colorScheme:n,textMeasurer:l,formattingLocale:u};for(const g of r.layers){const h=Fe(g,r.coordSystem);h&&Gt(h,e,{...f,layer:g})}e.restore();for(const g of s){const h=d.axes[g.position];h&&yn(e,g,h,d.panel,t)}for(const g of r.guides.axes){const h=d.axisLabels[g.position];h&&wn(e,g,h,t)}Kn(e,a,d.legends,t),Gn(e,r.config.content,d.header,t,{width:o,height:i}),Wn(e,r.config.content,d.footer,t,{width:o,height:i})};class rt extends Error{constructor(t){super(t),this.name="ChartConfigRenderError"}}const oo=async(e,t)=>{const n=Ue(e);if(!n.ok)throw new rt(n.reason);return ot(n.compiled,t)};exports.CANVAS_CAPABILITY_MATRIX=Vt;exports.CANVAS_SUPPORTED_GRAPH_TYPES=se;exports.CANVAS_UNSUPPORTED_GRAPH_TYPES=De;exports.ChartConfigRenderError=rt;exports.NodeCanvasTextMeasurer=et;exports.canRenderConfigWithCanvas=Ue;exports.darkTheme=nt;exports.ensureDefaultFonts=Ie;exports.lightTheme=tt;exports.loadCanvasRuntime=_e;exports.parseChartConfig=Oe;exports.registerFont=re;exports.renderChartConfigToPng=oo;exports.renderGraphToPng=to;
|
|
1
|
+
"use strict";var et=Object.create;var le=Object.defineProperty;var tt=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var nt=Object.getPrototypeOf,rt=Object.prototype.hasOwnProperty;var st=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ot(t))!rt.call(e,r)&&r!==o&&le(e,r,{get:()=>t[r],enumerable:!(n=tt(t,r))||n.enumerable});return e};var it=(e,t,o)=>(o=e!=null?et(nt(e)):{},st(t||!e||!e.__esModule?le(o,"default",{value:e,enumerable:!0}):o,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ce=require("node:fs"),ye=require("node:module"),O=require("node:path"),at=require("node:url"),lt=require("@graphysdk/viz-engine/graph-config"),I=require("d3-shape"),d=require("@graphysdk/viz-engine"),ct=require("node:buffer");var _=typeof document<"u"?document.currentScript:null;let H,Q;const Se=()=>H?Promise.resolve(H):(Q??=import("@napi-rs/canvas").then(e=>(H=e,e)).catch(e=>{throw Q=void 0,e}),Q),V=()=>{if(!H)throw new Error("Canvas runtime is not loaded. Call loadCanvasRuntime() before rendering.");return H},E="Inter",J=new Set;let de=!1,z=!1;const Te=e=>`${e.family}|${e.weight??400}|${e.style??"normal"}`,ne=e=>{const t=Te(e);J.has(t)||(V().GlobalFonts.register(e.data,e.family),J.add(t))},dt=[{file:"Inter-Regular.ttf",family:E,weight:400},{file:"Inter-SemiBold.ttf",family:E,weight:600}],ut=[{file:"inter-latin-400-normal.woff",family:E,weight:400},{file:"inter-latin-600-normal.woff",family:E,weight:600}],ft="@fontsource/inter",ht=()=>{try{const e=ye.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:_&&_.tagName.toUpperCase()==="SCRIPT"&&_.src||new URL("index.cjs",document.baseURI).href),t=O.dirname(e.resolve("@graphysdk/node-renderer/package.json"));return O.join(t,"assets")}catch{return O.resolve(O.dirname(at.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:_&&_.tagName.toUpperCase()==="SCRIPT"&&_.src||new URL("index.cjs",document.baseURI).href)),"../assets")}},Re=(e,t,o)=>{try{return ce.existsSync(e)?(ne({family:t,data:ce.readFileSync(e),weight:o}),!0):!1}catch{return!1}},gt=()=>{const e=ht();for(const{file:t,family:o,weight:n}of dt)Re(O.join(e,t),o,n)&&(z=!0)},mt=()=>{const e=ye.createRequire(typeof document>"u"?require("url").pathToFileURL(__filename).href:_&&_.tagName.toUpperCase()==="SCRIPT"&&_.src||new URL("index.cjs",document.baseURI).href);for(const{file:t,family:o,weight:n}of ut)if(!J.has(Te({family:o,data:Buffer.alloc(0),weight:n})))try{const r=e.resolve(`${ft}/files/${t}`);Re(r,o,n)&&(z=!0)}catch{}},Ee=()=>(de||(de=!0,gt(),mt()),z),C=(e,t)=>e.x+t*e.width,v=(e,t)=>e.y+(1-t)*e.height,$=e=>e==="catmull-rom"?I.curveCatmullRom:I.curveLinear,Le=e=>{switch(e){case"dashed":return[8,4];case"dotted":return[2,2];case"solid":return[]}},D=e=>e,At=(e,t)=>t!=="connect"?e:e.filter(o=>d.getX(o)!==null&&d.getY(o)!==null),bt=(e,t,o)=>{const n=$(t.interpolate),r=I.area().curve(n),s=I.line().curve(n);if(e.mainAxis==="y"){const i=a=>v(o,d.getY(a)??0),l=a=>C(o,d.getXMin(a)??0),c=a=>C(o,d.getXMax(a)??d.getX(a)??0);r.y(i).x0(l).x1(c),s.y(i).x(c)}else{const i=a=>C(o,d.getX(a)??0),l=a=>v(o,d.getYMin(a)??0),c=a=>v(o,d.getYMax(a)??d.getY(a)??0);r.x(i).y0(l).y1(c),s.x(i).y(c)}if(t.missingValues==="gap"){const i=l=>d.getX(l)!==null&&d.getY(l)!==null;r.defined(i),s.defined(i)}return{areaGenerator:r,lineGenerator:s}},pt=D({geom:"area",coord:"cartesian",draw:(e,{layer:t,coordSystem:o,panel:n,colorScheme:r})=>{const s=d.createStyleResolver({colorScheme:r}).geomReaders(t),{areaGenerator:i,lineGenerator:l}=bt(o,t.params,n),c=e;t.data.groupBy(d.GROUP_VARIABLES.group).forEach(a=>{const u=At([...a],t.params.missingValues),h=u[0];if(!h)return;const f=s.get("color",h),g=s.get("alpha",h),m=s.get("strokeWidth",h),p=Le(s.get("lineType",h));e.save(),e.globalAlpha=g,e.fillStyle=f,e.beginPath(),i.context(c)(u),e.fill(),e.restore(),e.save(),e.globalAlpha=s.get("strokeAlpha",h),e.strokeStyle=f,e.lineWidth=m,e.setLineDash(p),e.lineJoin="round",e.lineCap="round",e.beginPath(),l.context(c)(u),e.stroke(),e.restore()})}}),ue=(e,t,o,n,r,s)=>{const i=Math.max(0,Math.min(s.rx??s.ry??0,n/2)),l=Math.max(0,Math.min(s.ry??s.rx??0,r/2)),c=Math.PI/2;e.moveTo(t+i,o),e.lineTo(t+n-i,o),e.ellipse(t+n-i,o+l,i,l,0,-c,0),e.lineTo(t+n,o+r-l),e.ellipse(t+n-i,o+r-l,i,l,0,0,c),e.lineTo(t+i,o+r),e.ellipse(t+i,o+r-l,i,l,0,c,Math.PI),e.lineTo(t,o+l),e.ellipse(t+i,o+l,i,l,0,Math.PI,Math.PI*1.5),e.closePath()},yt=D({geom:"bar",coord:"cartesian",draw:(e,{layer:t,coordSystem:o,panel:n,colorScheme:r})=>{const{Path2D:s}=V(),i=d.createStyleResolver({colorScheme:r}).geomReaders(t),l=o.mainAxis,c=new Map;for(const a of t.data){const u=d.getBarRectBounds(l,a);if(!u)continue;const h=C(n,u.x),f=n.y+u.y*n.height,g={x:h,y:f,width:u.width*n.width,height:u.height*n.height,fill:i.get("color",a),opacity:i.get("alpha",a)},m=d.buildColumnKey(l,u),p=c.get(m);p?p.bars.push(g):c.set(m,{bars:[g],style:{borderColor:i.get("borderColor",a),borderWidth:i.get("borderWidth",a),borderRadius:i.get("borderRadius",a),borderAlpha:i.get("alpha",a)}})}for(const{bars:a,style:u}of c.values()){const{borderColor:h,borderRadius:f,borderWidth:g,borderAlpha:m}=u,p=d.resolveBarBorderTreatment(g),b=f==="full"?void 0:d.resolveBarCornerRadiiPx({borderRadius:f,mainAxis:l});if(!(a.length>1)){const[A]=a;if(!A)continue;const w=b??d.resolveBarCornerRadiiPx({borderRadius:f,mainAxis:l,bounds:{width:A.width,height:A.height}}),L=new s;ue(L,A.x,A.y,A.width,A.height,w),e.save(),e.globalAlpha=A.opacity,e.fillStyle=A.fill,e.fill(L),h!==void 0&&(e.clip(L),e.strokeStyle=h,e.lineWidth=p.outlineWidth,e.stroke(L)),e.restore();continue}const S=d.getBoundingRect(a),R=b??d.resolveBarCornerRadiiPx({borderRadius:f,mainAxis:l,bounds:{width:S.width,height:S.height}}),T=new s;ue(T,S.x,S.y,S.width,S.height,R),e.save(),e.clip(T);for(const A of a)e.globalAlpha=A.opacity,e.fillStyle=A.fill,e.fillRect(A.x,A.y,A.width,A.height),h!==void 0&&(e.strokeStyle=h,e.lineWidth=p.separatorWidth,e.strokeRect(A.x,A.y,A.width,A.height));h!==void 0&&(e.globalAlpha=m,e.strokeStyle=h,e.lineWidth=p.outlineWidth,e.stroke(T)),e.restore()}}}),fe=(e,t)=>{const o=/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(e.trim());if(o?.[1]!==void 0){const r=o[1],s=r.length===3?[...r].map(a=>a+a).join(""):r.slice(0,6),i=Number.parseInt(s.slice(0,2),16),l=Number.parseInt(s.slice(2,4),16),c=Number.parseInt(s.slice(4,6),16);return`rgba(${i}, ${l}, ${c}, ${t})`}const n=/^rgba?\(([^)]+)\)$/i.exec(e.trim());if(n?.[1]!==void 0){const r=n[1].split(",").map(c=>c.trim()),[s,i,l]=r;if(s!==void 0&&i!==void 0&&l!==void 0)return`rgba(${s}, ${i}, ${l}, ${t})`}return t===0?"rgba(0, 0, 0, 0)":e},St=(e,t)=>t!=="connect"?e:e.filter(o=>d.getX(o)!==null&&d.getY(o)!==null),Tt=(e,t)=>{const{seriesObservations:o,fillGenerator:n,panel:r,color:s,fillAlpha:i}=t,l=o.map(a=>d.getY(a)).filter(a=>a!==null).map(a=>v(r,a));if(l.length===0)return;const c=e.createLinearGradient(0,Math.min(...l),0,r.y+r.height);c.addColorStop(0,s),c.addColorStop(.7,fe(s,0)),c.addColorStop(1,fe(s,0)),e.save(),e.globalAlpha=i,e.fillStyle=c,e.beginPath(),n.context(e)(o),e.fill(),e.restore()},Rt=D({geom:"line",coord:"cartesian",draw:(e,{layer:t,panel:o,colorScheme:n})=>{const r=d.createStyleResolver({colorScheme:n}).geomReaders(t),s=I.line().x(l=>C(o,d.getX(l)??0)).y(l=>v(o,d.getY(l)??0)).curve($(t.params.interpolate)),i=I.area().x(l=>C(o,d.getX(l)??0)).y0(o.y+o.height).y1(l=>v(o,d.getY(l)??0)).curve($(t.params.interpolate));if(t.params.missingValues==="gap"){const l=c=>d.getX(c)!==null&&d.getY(c)!==null;s.defined(l),i.defined(l)}t.data.groupBy(d.GROUP_VARIABLES.group).forEach(l=>{const c=St([...l],t.params.missingValues),a=c[0];if(!a)return;const u=r.get("strokeWidth",a),h=Le(r.get("lineType",a)),f=r.get("color",a),g=r.get("fillAlpha",a);g!==void 0&&Tt(e,{seriesObservations:c,fillGenerator:i,panel:o,color:f,fillAlpha:g}),e.save(),e.globalAlpha=r.get("alpha",a),e.strokeStyle=f,e.lineWidth=u,e.setLineDash(h),e.lineJoin="round",e.lineCap="round",e.beginPath(),s.context(e)(c),e.stroke(),e.restore()})}}),Et=D({geom:"point",coord:"cartesian",draw:(e,{layer:t,panel:o,colorScheme:n})=>{const r=d.createStyleResolver({colorScheme:n}).geomReaders(t);for(const s of t.data){const i=d.getX(s),l=d.getY(s);if(i===null||l===null)continue;const c=C(o,i),a=v(o,l),u=r.get("size",s)/2,h=r.get("borderWidth",s);e.save(),e.globalAlpha=r.get("alpha",s),e.fillStyle=r.get("color",s),e.strokeStyle=r.get("borderColor",s),e.lineWidth=h,e.beginPath(),e.arc(c,a,u,0,Math.PI*2),e.fill(),h>0&&e.stroke(),e.restore()}}}),re=11,Lt="sans-serif",wt=500,k=5,we=5,x=13,ve=6,K=12,he=21.6,vt=(e,t)=>{const o=e.mapping.y!==void 0,n=t.mainAxis==="y";return o!==n},_t=(e,t,o)=>{const n=d.getRuleDashPattern(t,o);e.setLineDash(n),n.length>0&&(e.lineCap="round")},Ct=(e,t)=>X(e)&&X(t)?`${e}: ${t}`:X(e)?e:X(t)?t:null,X=e=>e!=null&&e.trim()!=="",Bt=e=>{e.beginPath(),e.moveTo(2.48935,16.9323),e.lineTo(9.07098,9.82964),e.bezierCurveTo(9.51595,9.34944,9.51504,8.60728,9.0689,8.12818),e.lineTo(2.48866,1.06172),e.bezierCurveTo(1.85811,.384586,.974477,0,.049217,0),e.lineTo(0,0),e.lineTo(0,18),e.lineTo(.0443689,18),e.bezierCurveTo(.972463,18,1.85854,17.6131,2.48935,16.9323),e.closePath()},_e=(e,t,o,n,r,s)=>{const i=Math.min(s,n/2,r/2);e.beginPath(),e.moveTo(t+i,o),e.lineTo(t+n-i,o),e.arcTo(t+n,o,t+n,o+i,i),e.lineTo(t+n,o+r-i),e.arcTo(t+n,o+r,t+n-i,o+r,i),e.lineTo(t+i,o+r),e.arcTo(t,o+r,t,o+r-i,i),e.lineTo(t,o+i),e.arcTo(t,o,t+i,o,i),e.closePath(),e.fill()},Pt=(e,t,o,n,r,s,i,l)=>{const c=o+k*2,a=re+we*2,u=n==="start",h=u?s.x:s.x+s.width,f=v(s,r),g=u?-x:-(c-x),m=u?g+c-k:g+k-K;e.save(),e.translate(h,f),e.translate(0,-a/2),e.fillStyle=i,_e(e,g,0,c,a,ve),e.save(),u||(e.translate(m+K/2,a/2),e.rotate(Math.PI),e.translate(-(m+K/2),-a/2)),e.translate(m,(a-he)/2),e.scale(K/10,he/18),e.fillStyle=i,Bt(e),e.fill(),e.restore(),e.fillStyle=l,e.textAlign="left",e.textBaseline="middle",e.fillText(t,g+k,a/2),e.restore()},It=(e,t,o,n,r,s,i,l)=>{const c=o+k*2,a=re+we*2,u=n==="start",h=C(s,r),f=u?s.y+s.height:s.y,g=u?-x:-8;e.save(),e.translate(h,f),e.translate(-c/2,0),e.fillStyle=i,_e(e,0,g,c,a,ve),e.fillStyle=l,e.textAlign="left",e.textBaseline="middle",e.fillText(t,k,g+a/2),e.restore()},Nt=D({geom:"rule",coord:"cartesian",draw:(e,{layer:t,coordSystem:o,panel:n,compiled:r,textMeasurer:s,formattingLocale:i,colorScheme:l})=>{const c=t.data.getFirst();if(!c)return;const a=vt(t,o),u=a?d.getY(c):d.getX(c);if(u===null)return;const h=d.createStyleResolver({colorScheme:l}).geomReaders(t),f=h.get("color",c),g=d.getRuleLabelTextColor(f),m=h.get("strokeWidth",c);if(e.save(),e.strokeStyle=f,e.lineWidth=m,_t(e,h.get("lineType",c),m),e.beginPath(),a){const T=v(n,u);e.moveTo(n.x,T),e.lineTo(n.x+n.width,T)}else{const T=C(n,u);e.moveTo(T,n.y),e.lineTo(T,n.y+n.height)}e.stroke(),e.restore();const p=Ct(t.params.label,d.formatRuleValue({guides:r.guides,numberFormat:r.config.numberFormat,layer:t,locale:i??r.config.parsingLocale}));if(p===null)return;const b=r.config.appearance.textScale,y={family:Lt,size:re*b,weight:wt};e.font=d.buildFontString(y);const S=s.measureText(p,y).width;(a?Pt:It)(e,p,S,t.params.labelPosition,u,n,f,g)}}),U=I.arc();U.digits(8);const kt=D({geom:"bar",coord:"polar",draw:(e,{layer:t,coordSystem:o,panel:n,colorScheme:r})=>{const s=n.x+n.width/2,i=n.y+n.height/2,l=Math.min(n.width,n.height)/2,{Path2D:c}=V(),a=d.createStyleResolver({colorScheme:r}).geomReaders(t);e.save(),e.translate(s,i),e.scale(l,l);const u=e,h=new Map;for(const f of t.data){const{startAngle:g,endAngle:m}=d.getAngleExtent(f),{innerRadius:p,outerRadius:b}=d.getRadiusExtent(f);if(g===null||m===null||p===null||b===null)continue;const y={startAngle:g,endAngle:m,innerRadius:p,outerRadius:b,fill:a.get("color",f),opacity:a.get("alpha",f)},S=d.buildSliceGroupKey(o.bandAxis,y),R=h.get(S);R?R.items.push(y):h.set(S,{items:[y],style:{borderColor:a.get("borderColor",f),borderWidth:a.get("borderWidth",f),borderRadius:a.get("borderRadius",f),borderAlpha:a.get("alpha",f)}})}for(const{items:f,style:g}of h.values()){const{borderColor:m,borderRadius:p,borderWidth:b,borderAlpha:y}=g,S=d.resolveBarBorderTreatment(b),R=m!==void 0&&l>0,T=d.getUnionExtent(f),A=d.resolvePolarBarCornerRadiusUnit(p,T.outerRadius-T.innerRadius),w=l>0&&(R||A>0);e.save();let L;w&&(L=new c,U.cornerRadius(A),U.context(L)(T),e.clip(L)),U.cornerRadius(0);for(const N of f)e.globalAlpha=N.opacity,e.fillStyle=N.fill,e.beginPath(),U.context(u)(N),e.fill(),R&&(e.strokeStyle=m,e.lineWidth=S.separatorWidth/l,e.stroke());R&&L&&(e.globalAlpha=y,e.strokeStyle=m,e.lineWidth=S.outlineWidth/l,e.stroke(L)),e.restore()}e.restore()}}),Ft={bar:{cartesian:yt,polar:kt},line:{cartesian:Rt},area:{cartesian:pt},point:{cartesian:Et},rule:{cartesian:Nt}},Ce=(e,t)=>Ft[e.geom]?.[t.type]??null,Dt=(e,t,o)=>{e.draw(t,o)};let ge;const Be=()=>(ge??=d.createCompiler(),ge),se=["line","areaStacked","bar","barStacked","barStackedFill","column","columnStacked","columnStackedFill","combo","pie","donut","scatter","bubble"],Pe=["funnel","heatmap","waterfall","mekko","table"],Ot=new Set(se),Ut={supportedGraphTypes:[...se],unsupportedGraphTypes:[...Pe],supportedGeoms:{cartesian:["bar","line","area","point","rule"],polar:["bar"]}},P=e=>({ok:!1,reason:e}),q=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),Ht=e=>{if(!q(e))return!1;const{columns:t,rows:o}=e;return!Array.isArray(t)||!Array.isArray(o)?!1:t.every(n=>q(n)&&typeof n.key=="string")},Mt=e=>{if("_unstable_mapping"in e&&e._unstable_mapping!==void 0)return!0;const t=e.referenceLines;return q(t)?t.trendline!==void 0||t.averageLine!==void 0:!1},Ie=e=>{if(!q(e))return P("Chart config must be a plain object.");if(!Ht(e.data))return P("Chart config is missing a valid `data` object (columns + rows).");const{data:t,...o}=e;return{ok:!0,input:o,data:t}},Ne=e=>{const t=Ie(e);if(!t.ok)return t;if(Mt(e))return P("Canvas renderer does not support `_unstable_mapping`, `referenceLines.trendline`, or `referenceLines.averageLine`.");const o=t.input.type??"column";if(!Ot.has(o))return P(`Unsupported chart type for canvas rendering: ${o}.`);try{const n=Be(),r=lt.convertGraphConfig(t.input,t.data),s=n.compile({input:r,data:t.data});if(!s.ok)return P(`Chart config failed to compile: ${s.errors.map(i=>i.message).join("; ")}`);for(const i of s.compiled.layers)if(Ce(i,s.compiled.coordSystem)===null)return P(`No canvas geom renderer for ${i.geom} (${s.compiled.coordSystem.type} coord).`);return{ok:!0,compiled:s.compiled}}catch(n){const r=n instanceof Error?n.message:String(n);return P(`Chart config failed to compile: ${r}`)}},ke=E,M=12,ie=1.3,G=10,W=12,F=6,Fe=16,Gt=24,De=6,Oe=3,ee=4,Wt=8,Vt="#9ca3af",Ue=16,Kt=1.3,He=13,Xt=1.4,Me=12,Yt=1.4,j=8,ae=12,zt=1.3,qt=200,jt=120,Qt=80,Ge=22,Zt=9,Jt=11,$t=10,Y=9,me=12,xt='-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif',eo=11.5,to=550,oo={light:.55,mid:.75,dark:.08},no={light:.62,mid:.8,dark:.85},ro=.22,so=.65,io={family:ke,size:M},ao=[2,3],lo=[1,3],te=e=>{switch(e){case"dashed":return ao;case"dotted":return lo;case"solid":return[]}},co=(e,t,o,n,r,s)=>{if(!t.isVisible||t.ticks.length===0)return;const i=t.position==="bottom"||t.position==="top";e.save(),e.font=d.buildFontString(d.toFontSpec(r,E)),e.fillStyle=r.textColor,e.strokeStyle=s.color,e.lineWidth=s.strokeWidth,e.setLineDash(te(s.lineType));for(const l of t.ticks){const c=i?l.position:1-l.position;t.ticksVisible&&fo(e,t.position,c,o,n,s.length),go(e,t.position,c,o,n,l.formattedLabel,t.labelRotation,r.offset)}e.restore()},uo=(e,t,o,n,r)=>{if(e==="bottom"||e==="top"){const c=n.x+t*n.width,a=e==="top"?o.y+o.height:o.y,u=e==="top"?-r:r;return{x1:c,y1:a,x2:c,y2:a+u}}const s=n.y+t*n.height,i=e==="right"?o.x:o.x+o.width,l=e==="right"?r:-r;return{x1:i,y1:s,x2:i+l,y2:s}},fo=(e,t,o,n,r,s)=>{const{x1:i,y1:l,x2:c,y2:a}=uo(t,o,n,r,s);e.beginPath(),e.moveTo(i,l),e.lineTo(c,a),e.stroke()},ho=(e,t,o,n,r)=>{if(e==="bottom"||e==="top"){const i=n.x+t*n.width;return e==="bottom"?{x:i,y:o.y+r,textAlign:"center",textBaseline:"top"}:{x:i,y:o.y+o.height-r,textAlign:"center",textBaseline:"alphabetic"}}const s=n.y+t*n.height;return e==="left"?{x:o.x+o.width-r,y:s,textAlign:"right",textBaseline:"middle"}:{x:o.x+r,y:s,textAlign:"left",textBaseline:"middle"}},go=(e,t,o,n,r,s,i,l)=>{if(i!==0&&(t==="top"||t==="bottom")){const a=r.x+o*r.width,u=t==="top";e.save(),e.translate(a,u?n.y+n.height-l:n.y+l),e.rotate(i*Math.PI/180),e.textAlign=u?"left":"right",e.textBaseline="middle",e.fillText(s,0,0),e.restore();return}const c=ho(t,o,n,r,l);e.textAlign=c.textAlign,e.textBaseline=c.textBaseline,e.fillText(s,c.x,c.y)},mo=(e,t,o,n)=>{if(!t.isVisible||!t.label)return;e.save(),e.font=d.buildFontString({family:n.fontFamily??E,size:n.fontSize,weight:n.fontWeight}),e.fillStyle=n.textColor,e.textBaseline="middle";const{x:r,y:s,alignment:i}=Ao(t.position,o);e.textAlign=i,e.fillText(t.label,r,s),e.restore()},Ao=(e,t)=>{const o=t.y+t.height/2;return e==="left"?{x:t.x,y:o,alignment:"start"}:e==="right"?{x:t.x+t.width,y:o,alignment:"end"}:{x:t.x+t.width/2,y:o,alignment:"center"}},bo="data:image/png;base64,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",B=Ge;let Z;const po=()=>{if(Z)return Z;const{Image:e}=V(),t=new e,o=bo.replace(/^data:image\/png;base64,/,"");return t.src=ct.Buffer.from(o,"base64"),Z=t,t},We=(e,t,o="full")=>!e||t.width<jt||t.height<Qt?"hidden":t.width<qt||o==="mini"?"mini":"full",yo=e=>{const t=So(e);if(t===null)return"light";const o=To(t);return o<=ro?"dark":o<=so?"mid":"light"},oe=(e,t,o)=>e.placement!==o||We(e.enabled,t,e.variant)==="hidden"?0:Ge,Ve=(e,t,o,n,r,s)=>{if(t.placement!==s)return;const i=We(t.enabled,r,t.variant);if(i==="hidden")return;const l=yo(n.background),c=l==="dark",a={family:xt,size:eo,weight:400},u={...a,weight:to};let h=0;i==="full"&&(e.font=d.buildFontString(a),h=e.measureText("Made with ").width,e.font=d.buildFontString(u),h+=e.measureText("Graphy").width);const f=i==="mini"?0:Zt,g=i==="mini"?0:Jt,m=i==="mini"?0:$t,p=i==="mini"?B:f+Y+m+h+g,b=o.x+o.width-p,y=o.y+Math.max(0,(o.height||B)/2-B/2);e.save(),e.globalAlpha=no[l],e.textBaseline="middle",e.textAlign="left",c||(e.shadowColor="rgba(0, 0, 0, 0.09)",e.shadowBlur=4,e.shadowOffsetY=1),e.beginPath(),e.roundRect(b,y,p,B,B/2),e.fillStyle=`rgba(255, 255, 255, ${oo[l]})`,e.fill(),e.shadowColor="transparent",e.shadowBlur=0,e.shadowOffsetY=0;const S=c?"#FFFFFF":"#2A2A28",R=i==="mini"?b+(p-Y)/2:b+f,T=y+(B-me)/2;if(e.save(),c&&(e.filter="invert(1)"),e.drawImage(po(),R,T,Y,me),e.restore(),i==="full"){const A=b+f+Y+m,w=y+B/2;e.fillStyle=S,e.font=d.buildFontString(a),e.fillText("Made with ",A,w);const L=e.measureText("Made with ").width;e.font=d.buildFontString(u),e.fillText("Graphy",A+L,w)}e.restore()},So=e=>{const t=e.trim();if(!t.startsWith("#"))return null;const o=t.slice(1);if(o.length===3){const n=o[0],r=o[1],s=o[2];return n===void 0||r===void 0||s===void 0?null:{red:Number.parseInt(n+n,16),green:Number.parseInt(r+r,16),blue:Number.parseInt(s+s,16)}}return o.length>=6?{red:Number.parseInt(o.slice(0,2),16),green:Number.parseInt(o.slice(2,4),16),blue:Number.parseInt(o.slice(4,6),16)}:null},To=({red:e,green:t,blue:o})=>{const n=r=>{const s=r/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4};return .2126*n(e)+.7152*n(t)+.0722*n(o)},Ro={family:E,size:Ue,weight:600},Eo={family:E,size:He},Lo={family:E,size:Me},wo={family:E,size:ae,weight:500},vo={family:E,size:ae},Ke=Ue*Kt,_o=He*Xt,Xe=Me*Yt,Ye=ae*zt,ze=e=>{if(e===null)return null;if(e.label!==void 0&&e.label!=="")return e.label;if(e.url!==void 0&&e.url!==""&&d.isSafeUrl(e.url))try{return new URL(e.url).hostname}catch{return e.url}return null},Co=(e,t)=>{let o=0;const n=e.isTitleVisible&&e.title!==null,r=e.isSubtitleVisible&&e.subtitle!==null;n&&(o+=Ke),r&&(o>0&&(o+=j),o+=_o);const s=oe(e.brandMark,t,"header");!n&&!r&&s>0&&(o=s);const i=e.isCaptionVisible&&e.caption!==null,l=e.isSourceVisible&&ze(e.source)!==null,c=oe(e.brandMark,t,"footer");let a=0;return i&&(a+=Xe),(l||c>0)&&(a>0&&(a+=j),a+=Math.max(Ye,c)),{headerHeight:o,footerHeight:a}},Bo=(e,t,o,n,r)=>{if(o.height===0)return;e.save(),e.textBaseline="top",e.textAlign="left";let s=o.y;t.isTitleVisible&&t.title!==null&&(e.font=d.buildFontString(Ro),e.fillStyle=n.textPrimary,e.fillText(d.extractPlainText(t.title),o.x,s),s+=Ke+j),t.isSubtitleVisible&&t.subtitle!==null&&(e.font=d.buildFontString(Eo),e.fillStyle=n.textSecondary,e.fillText(d.extractPlainText(t.subtitle),o.x,s)),e.restore(),Ve(e,t.brandMark,o,n,r,"header")},Po=(e,t,o,n,r)=>{if(o.height===0)return;const s=t.isCaptionVisible?t.caption:null,i=t.isSourceVisible?ze(t.source):null,l=oe(t.brandMark,r,"footer");if(s===null&&i===null&&l===0)return;e.save(),e.textBaseline="top",e.textAlign="left";let c=o.y;if(s!==null&&(e.font=d.buildFontString(Lo),e.fillStyle=n.textSecondary,e.fillText(d.extractPlainText(s),o.x,c),c+=Xe+j),i!==null){let a=o.x;a=Ae(e,"Source: ",wo,n.textSecondary,a,c),Ae(e,i,vo,n.textSecondary,a,c)}e.restore(),Ve(e,t.brandMark,{x:o.x,y:c,width:o.width,height:Math.max(Ye,l)},n,r,"footer")},Ae=(e,t,o,n,r,s)=>(e.font=d.buildFontString(o),e.fillStyle=n,e.fillText(t,r,s),r+e.measureText(t).width),Io=(e,t,o,n)=>{e.save(),e.lineCap="round";for(const r of d.computePanelBorderPaths(d.resolvePanelBorderStyle(o),n))e.strokeStyle=r.color,e.lineWidth=r.strokeWidth,e.setLineDash(te(r.lineType)),No(e,r.segments),e.stroke();for(const r of t){if(!r.gridVisible)continue;const s=r.position==="top"||r.position==="bottom",i=d.resolveGridLineStyle(o,d.getAestheticFromScaleAestheticKey(r.scaleAestheticKey));e.strokeStyle=i.color,e.lineWidth=i.strokeWidth,e.setLineDash(te(i.lineType));for(const l of r.ticks){if(l.position<=0||l.position>=1)continue;const c=s?l.position:1-l.position;if(e.beginPath(),s){const a=n.x+c*n.width;e.moveTo(a,n.y),e.lineTo(a,n.y+n.height)}else{const a=n.y+c*n.height;e.moveTo(n.x,a),e.lineTo(n.x+n.width,a)}e.stroke()}}e.restore()},No=(e,t)=>{e.beginPath();for(const o of t)switch(o.type){case"move":e.moveTo(o.x,o.y);break;case"line":e.lineTo(o.x,o.y);break;case"arc":e.arc(o.cx,o.cy,o.radius,o.startAngle,o.endAngle);break;case"close":e.closePath();break}},ko=(e,t,o,n)=>{e.save(),e.font=d.buildFontString(io),e.textBaseline="middle";for(const s of t)s.display==="direct"&&Fo(e,s,o,n);const r=new Map;for(const s of t){if(s.display!=="pill"||s.items.length===0)continue;const i=r.get(s.position);i?i.push(s):r.set(s.position,[s])}for(const[s,i]of r){const l=o[s];l&&(s==="top"||s==="bottom"?Do(e,i,l,n):Oo(e,i,l,n))}e.restore()},Fo=(e,t,o,n)=>{const r=o[t.position];if(r){e.textAlign="left";for(const s of t.items)s.normalizedY!==null&&(e.fillStyle=typeof s.visual.color=="string"?s.visual.color:n.textPrimary,e.fillText(s.formattedLabel,r.x+Wt,v(r,s.normalizedY)))}},Do=(e,t,o,n)=>{const r=qe(t),s=r.reduce((a,u,h)=>a+Ho(u)+e.measureText(u.label).width+(h===0?0:be(u)),0),i=M*ie;let l=o.x+Math.max(0,(o.width-s)/2);const c=o.y+De+Math.max(i,W)/2;for(let a=0;a<r.length;a++){const u=r[a];u&&(a>0&&(l+=be(u)),l=je(e,u,l,c,n))}},Oo=(e,t,o,n)=>{const r=qe(t),s=Math.max(M*ie,W),i=4,l=r.length*s+Math.max(0,r.length-1)*i;let c=o.y+Math.max(0,(o.height-l)/2)+s/2;for(const a of r)je(e,a,o.x,c,n),c+=s+i},qe=e=>{const t=[];for(const o of e){const n=o.aesthetics.includes("size");o.items.forEach((r,s)=>{const i=r.visual.size,l=n&&typeof i=="number"&&Number.isFinite(i)&&i>0?i:void 0;t.push({label:r.formattedLabel,colors:Uo(r.visual.color),bubbleSize:l,isFirstInGroup:s===0})})}return t},Uo=e=>typeof e=="string"?[e]:Array.isArray(e)?e.filter(t=>typeof t=="string"):[],be=e=>e.isFirstInGroup?Gt:Fe,Ho=e=>{if(e.bubbleSize!==void 0)return e.bubbleSize+F;const t=e.colors.length;if(t===0)return 0;if(t===1)return G+F;const o=Math.min(t,Oe);return G+(o-1)*ee+F},je=(e,t,o,n,r)=>{let s=o;if(t.bubbleSize!==void 0){const i=t.bubbleSize/2;e.fillStyle=t.colors[0]??Vt,e.beginPath(),e.arc(s+i,n,i,0,Math.PI*2),e.fill(),s+=t.bubbleSize+F}else if(t.colors.length>0){const i=t.colors.slice(0,Oe);for(let l=0;l<i.length;l++){const c=i[l];c&&(e.fillStyle=c,e.fillRect(s+l*ee,n-W/2,G,W))}s+=G+(i.length-1)*ee+F}return e.fillStyle=r.textPrimary,e.textAlign="left",e.fillText(t.label,s,n),s+e.measureText(t.label).width},pe=(e,t)=>Math.min(Math.max(...e),t),Mo=(e,t,o)=>n=>{if(!n.isVisible||n.ticks.length===0)return 0;const r=n.position==="top"||n.position==="bottom",s=d.getAestheticFromScaleAestheticKey(n.scaleAestheticKey),{offset:i,...l}=t[s],c=n.ticksVisible?Math.max(i,o[s].length):i,a=d.toFontSpec(l,E),u=n.ticks.map(g=>e.measureText(g.formattedLabel,a)),h=n.labelMaxWidthPx??Number.POSITIVE_INFINITY;if(r){if(n.labelRotation!==0){const g=u.map(m=>m.width);return pe(g,h)+2*c}return Math.max(...u.map(g=>g.height))+c}const f=u.map(g=>g.width);return pe(f,h)+c},Go=e=>t=>{if(t.items.length===0)return 0;const o={family:ke,size:M};if(t.position==="top"||t.position==="bottom"){const s=M*ie;return Math.max(s,W)+De*2}const r=t.items.map(s=>{const i=e.measureText(s.formattedLabel,o).width;return G+F+i});return Math.max(...r)+Fe},Wo=e=>(t,o)=>{const{labelLineHeight:n,labelFontWeight:r}=d.getDifferenceArrowDimensions(o,1);return e.measureText(t,{family:E,size:n,weight:r})},Vo=(e,t)=>(o,n,r)=>{const s=t[o][n],i=e.measureText(r,d.toFontSpec(s,E));return{...i,width:i.width+s.paddingInline*2,height:i.height+s.paddingBlock*2}},Ko=({textMeasurer:e,axisLabelStyles:t,dataLabelStyles:o,tickLabelStyles:n,tickLineStyles:r})=>({measureAxis:Mo(e,n,r),measureAxisLabel:s=>d.computeLineBoxHeight(t[d.getAestheticFromScaleAestheticKey(s.scaleAestheticKey)]),measureLegend:Go(e),measureTickLabel:(s,i)=>e.measureText(s,d.toFontSpec(n[i],E)),measureDifferenceArrowLabel:Wo(e),measureDataLabel:Vo(e,o),measureHeadline:()=>({width:0,height:0}),measureHeadlineItemWidths:()=>[]});class Qe{constructor(){this.currentFont="";const t=V().createCanvas(1,1);this.ctx=t.getContext("2d")}measureText(t,o){const n=d.buildFontString(o);this.currentFont!==n&&(this.ctx.font=n,this.currentFont=n);const r=this.ctx.measureText(t);return{width:r.width,height:r.fontBoundingBoxAscent+r.fontBoundingBoxDescent,ascent:r.fontBoundingBoxAscent,descent:r.fontBoundingBoxDescent}}}const Ze={background:"#ffffff",textPrimary:"#111827",textSecondary:"#6b7280",gridLine:"#e5e7eb",legendPillBackground:"rgba(0, 0, 0, 0.04)",legendPillBorder:"rgba(0, 0, 0, 0.08)"},Je={background:"#0b0f17",textPrimary:"#e5e7eb",textSecondary:"#9ca3af",gridLine:"#1f2937",legendPillBackground:"rgba(255, 255, 255, 0.06)",legendPillBorder:"rgba(255, 255, 255, 0.12)"},Xo=async({input:e,data:t},o)=>{const r=Be().compile({input:e,data:t});if(!r.ok)throw new Error(`Failed to compile graph spec: ${r.errors.map(s=>s.message).join("; ")}`);return $e(r.compiled,o)},$e=async(e,t)=>{const{Canvas:o}=await Se();if(Ee(),t.fonts)for(const w of t.fonts)ne(w);const n=d.formatLegends({legends:e.guides.legends.drawn,numberFormat:e.config.numberFormat,parsingLocale:e.config.parsingLocale,formattingLocale:t.formattingLocale}),r={width:t.width,height:t.height},{headerHeight:s,footerHeight:i}=Co(e.config.content,r),l={headerSize:{width:t.width,height:s},footerSize:{width:t.width,height:i}},c=t.colorScheme??"light",a=d.createStyleResolver({colorScheme:c}).chromeReaders(e.chrome),u=e.config.appearance.textScale,h={x:d.resolveAxisLabelStyle(a,"x",u),y:d.resolveAxisLabelStyle(a,"y",u)},f={x:d.resolveTickLabelStyle(a,"x",u),y:d.resolveTickLabelStyle(a,"y",u)},g={x:d.resolveTickLineStyle(a,"x"),y:d.resolveTickLineStyle(a,"y")},m={};for(const w of d.DATA_LABEL_ROLES){const L={};for(const N of d.DATA_LABEL_POSITIONS)L[N]=d.resolveDataLabelStyle(a,w,N,u);m[w]=L}const p=new Qe,b=Ko({textMeasurer:p,axisLabelStyles:h,dataLabelStyles:m,tickLabelStyles:f,tickLineStyles:g}),{layout:y,formattedAxes:S}=new d.LayoutCompiler(b).compile({axes:e.guides.axes,numberFormat:e.config.numberFormat,parsingLocale:e.config.parsingLocale,formattedLegends:n,containerSize:{width:t.width,height:t.height},externalMeasurements:l,formattingLocale:t.formattingLocale,layout:e.config.layout}),R=t.pixelRatio??2,T=new o(t.width*R,t.height*R),A=T.getContext("2d");return A.scale(R,R),Yo({ctx:A,theme:c==="dark"?Je:Ze,colorScheme:c,chromeReaders:a,axisLabelStyles:h,tickLabelStyles:f,tickLineStyles:g,width:t.width,height:t.height,compiled:e,formattedAxes:S,formattedLegends:n,layout:y,textMeasurer:p,...t.formattingLocale===void 0?{}:{formattingLocale:t.formattingLocale}}),T.encode("png")},Yo=({ctx:e,theme:t,colorScheme:o,chromeReaders:n,axisLabelStyles:r,tickLabelStyles:s,tickLineStyles:i,width:l,height:c,compiled:a,formattedAxes:u,formattedLegends:h,layout:f,textMeasurer:g,formattingLocale:m})=>{e.fillStyle=t.background,e.fillRect(0,0,l,c),Io(e,u,n,f.panel),e.save(),e.beginPath(),e.rect(f.panel.x,f.panel.y,f.panel.width,f.panel.height),e.clip();const p={coordSystem:a.coordSystem,panel:f.panel,compiled:a,theme:t,colorScheme:o,textMeasurer:g,formattingLocale:m};for(const b of a.layers){const y=Ce(b,a.coordSystem);y&&Dt(y,e,{...p,layer:b})}e.restore();for(const b of u){const y=f.axes[b.position];if(y){const S=d.getAestheticFromScaleAestheticKey(b.scaleAestheticKey);co(e,b,y,f.panel,s[S],i[S])}}for(const b of a.guides.axes){const y=f.axisLabels[b.position];y&&mo(e,b,y,r[d.getAestheticFromScaleAestheticKey(b.scaleAestheticKey)])}ko(e,h,f.legends,t),Bo(e,a.config.content,f.header,t,{width:l,height:c}),Po(e,a.config.content,f.footer,t,{width:l,height:c})};class xe extends Error{constructor(t){super(t),this.name="ChartConfigRenderError"}}const zo=async(e,t)=>{const o=Ne(e);if(!o.ok)throw new xe(o.reason);return $e(o.compiled,t)};exports.CANVAS_CAPABILITY_MATRIX=Ut;exports.CANVAS_SUPPORTED_GRAPH_TYPES=se;exports.CANVAS_UNSUPPORTED_GRAPH_TYPES=Pe;exports.ChartConfigRenderError=xe;exports.NodeCanvasTextMeasurer=Qe;exports.canRenderConfigWithCanvas=Ne;exports.darkTheme=Je;exports.ensureDefaultFonts=Ee;exports.lightTheme=Ze;exports.loadCanvasRuntime=Se;exports.parseChartConfig=Ie;exports.registerFont=ne;exports.renderChartConfigToPng=zo;exports.renderGraphToPng=Xo;
|