diff --git a/bun.lockb b/bun.lockb index c5b266f..993fd13 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/examples/basic.pdf b/examples/basic.pdf deleted file mode 100644 index 6d33715..0000000 Binary files a/examples/basic.pdf and /dev/null differ diff --git a/examples/composed.pdf b/examples/composed.pdf deleted file mode 100644 index f2ed29c..0000000 Binary files a/examples/composed.pdf and /dev/null differ diff --git a/examples/index.ts b/examples/index.ts index c2a719b..3b8c0ef 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -13,8 +13,9 @@ console.error = function (message) { }; const main = async () => { - await import('./basic'); - await import('./composed'); + await import('./recharts-basic'); + await import('./recharts-composed'); + await import('./victory-basic'); // rome-ignore lint/nursery/noConsoleLog: return console.log('✅ /examples updated!'); diff --git a/examples/recharts-basic.pdf b/examples/recharts-basic.pdf new file mode 100644 index 0000000..21d1c34 Binary files /dev/null and b/examples/recharts-basic.pdf differ diff --git a/examples/basic.png b/examples/recharts-basic.png similarity index 100% rename from examples/basic.png rename to examples/recharts-basic.png diff --git a/examples/basic.tsx b/examples/recharts-basic.tsx similarity index 94% rename from examples/basic.tsx rename to examples/recharts-basic.tsx index 8524a18..1af7b42 100644 --- a/examples/basic.tsx +++ b/examples/recharts-basic.tsx @@ -68,4 +68,4 @@ const MyDocument = () => ( const __dirname = fileURLToPath(new URL('.', import.meta.url)); -ReactPDF.render(, `${__dirname}/basic.pdf`); +ReactPDF.render(, `${__dirname}/recharts-basic.pdf`); diff --git a/examples/recharts-composed.pdf b/examples/recharts-composed.pdf new file mode 100644 index 0000000..afd42d1 Binary files /dev/null and b/examples/recharts-composed.pdf differ diff --git a/examples/composed.tsx b/examples/recharts-composed.tsx similarity index 95% rename from examples/composed.tsx rename to examples/recharts-composed.tsx index 71500f6..a90cab0 100644 --- a/examples/composed.tsx +++ b/examples/recharts-composed.tsx @@ -87,4 +87,4 @@ const MyDocument = () => ( const __dirname = fileURLToPath(new URL('.', import.meta.url)); -ReactPDF.render(, `${__dirname}/composed.pdf`); +ReactPDF.render(, `${__dirname}/recharts-composed.pdf`); diff --git a/examples/victory-basic.pdf b/examples/victory-basic.pdf new file mode 100644 index 0000000..b996c0b Binary files /dev/null and b/examples/victory-basic.pdf differ diff --git a/examples/victory-basic.tsx b/examples/victory-basic.tsx new file mode 100644 index 0000000..24bbdcd --- /dev/null +++ b/examples/victory-basic.tsx @@ -0,0 +1,35 @@ +import ReactPDFChart from '../src'; +import { Document, Page } from '@react-pdf/renderer'; +import ReactPDF from '@react-pdf/renderer'; +import { fileURLToPath } from 'node:url'; +import React from 'react'; +import { VictoryBar, VictoryChart } from 'victory'; + +const data = [ + { x: 1, y: 2, y0: 1 }, + { x: 2, y: 3, y0: 2 }, + { x: 3, y: 5, y0: 2 }, + { x: 4, y: 4, y0: 3 }, + { x: 5, y: 6, y0: 3 }, +]; + +const MyDocument = () => ( + + + + + + + + + +); + +const __dirname = fileURLToPath(new URL('.', import.meta.url)); + +ReactPDF.render(, `${__dirname}/victory-basic.pdf`); diff --git a/package.json b/package.json index 09eb156..ce59c53 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "recharts": "2.7.2", "rome": "12.1.3", "semantic-release": "21.0.7", - "typescript": "5.1.6" + "typescript": "5.1.6", + "victory": "36.6.11" }, "engines": { "node": ">=16" diff --git a/src/ReactPDFChart.tsx b/src/ReactPDFChart.tsx index 8ee7614..5cb8268 100644 --- a/src/ReactPDFChart.tsx +++ b/src/ReactPDFChart.tsx @@ -110,12 +110,56 @@ const getElementStyle = ( // Apply inline styles that react-pdf supports if (attribs.style) { attribs.style.split(';').forEach((styleString) => { - const [key, value] = styleString.split(':'); + const [rawKey, value] = styleString.split(':'); + const key = rawKey.toLowerCase(); + if (['backgroundColor', 'color'].includes(key)) { style.push({ [key]: value }); + } else { + // This warning is super noisy, but can be helpful when debugging + // console.warn( + // ` detected that your chart has a node with an unsupported inline style. "${attribs.style}" mentions "${key}" which isn't supported in react-pdf yet.`, + // ); + } + }); + } + return style; +}; + +// For SVG elements this will process inline styles into something react-pdf +// can understand +const getSvgElementStyle = (attribs: TagElementType['attribs']) => { + const style: SVGPresentationAttributes = {}; + + // Apply inline styles that react-pdf supports + if (attribs.style) { + attribs.style.split(';').forEach((styleString) => { + const [rawKey, value] = styleString.split(':'); + const key = rawKey.toLowerCase(); + + switch (key) { + case 'color': + case 'fill': + case 'opacity': + case 'stroke': + style[key] = value; + break; + case 'stroke-width': + style.strokeWidth = value; + break; + case 'stroke-linecap': + style.strokeLineCap = + value as SVGPresentationAttributes['strokeLineCap']; + break; + default: + // This warning is super noisy, but can be helpful when debugging + // console.warn( + // ` detected that your chart has a node with an unsupported inline style. "${attribs.style}" mentions "${key}" which isn't supported in react-pdf yet.`, + // ); } }); } + return style; }; @@ -231,6 +275,7 @@ const webSvgToPdfSvg = (children: React.ReactElement, chartStyle?: Style) => { cx={attribs.cx} cy={attribs.cy} r={attribs.r} + style={getSvgElementStyle(attribs)} > {children} @@ -252,6 +297,7 @@ const webSvgToPdfSvg = (children: React.ReactElement, chartStyle?: Style) => { cy={attribs.cy} rx={attribs.rx} ry={attribs.ry} + style={getSvgElementStyle(attribs)} > {children} @@ -266,6 +312,7 @@ const webSvgToPdfSvg = (children: React.ReactElement, chartStyle?: Style) => { x2={attribs.x2} y1={attribs.y1} y2={attribs.y2} + style={getSvgElementStyle(attribs)} > {children} @@ -291,19 +338,31 @@ const webSvgToPdfSvg = (children: React.ReactElement, chartStyle?: Style) => { ); case 'path': return ( - + {children} ); case 'polygon': return ( - + {children} ); case 'polyline': return ( - + {children} ); @@ -328,6 +387,7 @@ const webSvgToPdfSvg = (children: React.ReactElement, chartStyle?: Style) => { height={attribs.height} rx={attribs.rx} ry={attribs.ry} + style={getSvgElementStyle(attribs)} width={attribs.width} x={attribs.x} y={attribs.y}