chart = {
const svgW = (root.x1 - root.x0);
const svgH = (root.y1 - root.y0);
const svg = d3.select(DOM.svg(svgW, svgH))
.attr('width','100%')
.attr('height','auto')
.style('font', '10px sans-serif');
const chart = svg.append('g')
const shadow = DOM.uid('shadow');
chart.append('filter')
.attr('id', shadow.id)
.append('feDropShadow')
.attr('flood-opacity', 0.3)
.attr('dx', 0)
.attr('stdDeviation', 3);
const node = chart.selectAll('g')
.data(d3.nest().key(d => d.height).entries(root.descendants()))
.join('g')
.attr('filter', shadow)
.selectAll('g')
.data(d => d.values)
.join('g')
.attr('transform', d => `translate(${d.x0},${d.y0})`);
node.append('title')
.text(d => `${d.ancestors().reverse().map(d => d.data.name).join('/')}\n${format(d.value)}`);
node.append('rect')
.attr('id', d => (d.nodeUid = DOM.uid('node')).id)
.attr('fill', d => color(d.height))
.attr('width', d => d.x1 - d.x0)
.attr('height', d => d.y1 - d.y0);
node.append('clipPath')
.attr('id', d => (d.clipUid = DOM.uid('clip')).id)
.append('use')
.attr('xlink:href', d => d.nodeUid.href);
node.append('text')
.attr('clip-path', d => d.clipUid)
.selectAll('tspan')
.data(d => d.data.name.split(/(?=[A-Z][^A-Z])/g).concat(format(d.value)))
.join('tspan')
.attr('fill-opacity', (d, i, nodes) => i === nodes.length - 1 ? 0.7 : null)
.text(d => d);
node.filter(d => d.children).selectAll('tspan')
.attr('dx', 3)
.attr('y', 13);
node.filter(d => !d.children).selectAll('tspan')
.attr('x', 3)
.attr('y', (d, i, nodes) => `${(i === nodes.length - 1) * 0.3 + 1.1 + i * 0.9}em`);
const container = document.createElement('div');
container.setAttribute('style','overflow: scroll;');
container.appendChild(svg.node());
return container;
}