PercentGrowth = ({
data=[{target:10, actual:8}, {target:12, actual:9}],
title="Monthly growth",
width=700,
height=20,
titleWidth=100}) => {
const perc = (a, b) => (b-a)/a;
const target=perc(data[0].target, data[1].target), actual=perc(data[0].actual, data[1].actual);
const wTitle=titleWidth, wLegend=117, wActual=140;
const legendSize=(height-3)/2;
const wBar=width-wTitle-wActual-wLegend;
const sign = actual>=0 ? 1 : -1;
const range = actual>=target? actual : (actual>=0) ? target : (target-actual);
const xScale = (x) => (x - (actual<0 ? actual : 0))/range * wBar;
const opacity = 0.3;
const style = svg.fragment`<style>
.small, .legendTitle{ font: 10px sans-serif; font-weight:600; }
.legendTitle {font-weight:300; }
.title { font: 14px sans-serif; color: white}
.big { font: 14px sans-serif; color: white}
</style>`
const Title = svg.fragment`<text y=${height/2} dominant-baseline="central" class="title">${title}</text>`
const Actuals = svg.fragment`
<text x=${width-wActual} y=${height/2} dominant-baseline="central" class="legendTitle">actuals</text>
<text x=${width} y=${height/2} dominant-baseline="central" class="big" text-anchor="end">${d3.format(".3s")(data[0].actual)} → ${d3.format(".3s")(data[1].actual)}</text>`
const Target = svg.fragment`<rect x=${wTitle+xScale(0)} width=${xScale(target)-xScale(0)} height=${height} style="fill:none; stroke:gray; stroke-width:1; stroke-opacity:0.3;" />
<line x1=${wTitle+xScale(target)} x2=${wTitle+xScale(target)} y2=${height} style="stroke:black; stroke-width:2; stroke-opacity:0.9;" />`
const Actual = svg.fragment`<g transform="translate(${wTitle},0)">
<polygon points="
${xScale(0)},0
${xScale(actual)-sign*height/2},0
${xScale(actual)},${height/2}
${xScale(actual)-sign*height/2},${height}
${xScale(0)},${height}"
style="fill:${actual>=0 ? "steelblue" : "red"}; fill-opacity:${opacity};" />
<polyline points="
${xScale(actual)-sign*height/2},0
${xScale(actual)},${height/2}
${xScale(actual)-sign*height/2},${height}"
fill=none stroke=${actual>=0 ? "steelblue" : "red"} style="stroke-width:2;" />
</g>`
const Percent = svg.fragment`
<text x=${wTitle+50} y=${height/2} dominant-baseline="central" text-anchor="end" class="big">${d3.format(".0%")(actual/target)}</text>
<text x=${wTitle+55} y=${height/2} dominant-baseline="central" class="legendTitle">of target growth rate</text>`
const Legend = svg.fragment`<g transform="translate(${wTitle+wBar+30},0)">
<rect width=${legendSize} height=${legendSize} style="fill:none; stroke:gray; stroke-width:1; stroke-opacity:0.3;" />
<rect y=${legendSize+3} width=${legendSize} height=${legendSize} style="fill:${actual>=0 ? "steelblue" : "red"}; stroke:gray; stroke-width:1; fill-opacity:${opacity}; stroke-opacity:0.3;" />
<text x=${legendSize+3} y=${legendSize/2} dominant-baseline="central" class="legendTitle">target</text>
<text x=${legendSize+3} y=${3 + 3*legendSize/2} dominant-baseline="central" class="legendTitle">actual</text>
<text x=${legendSize+60} y=${legendSize/2} dominant-baseline="central" text-anchor="end" class="small">${d3.format(".0%")(target)}</text>
<text x=${legendSize+60} y=${3 + 3*legendSize/2} dominant-baseline="central" text-anchor="end" class="small">${d3.format(".0%")(actual)}</text>
</g>`
return html`<svg width=${width} height=${height} style="border: 0px solid">
${style} ${Title} ${Percent} ${Actuals} ${Target} ${Legend} ${Actual} </svg>`
}