chart = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, config.width, config.height])
.attr("width", config.width)
.attr("height", config.height)
.attr("style", "max-width: 100%; height: auto; font: 13px sans-serif;");
const defs = svg.append("defs");
const filter = defs
.append("filter")
.attr("id", "drop-shadow")
.attr("height", "150%");
filter
.append("feGaussianBlur")
.attr("in", "SourceAlpha")
.attr("stdDeviation", 5);
filter
.append("feOffset")
.attr("dx", 8)
.attr("dy", 8)
.attr("result", "offsetblur");
filter
.append("feComponentTransfer")
.append("feFuncA")
.attr("type", "linear")
.attr("slope", 1);
filter
.append("feMerge")
.selectAll("feMergeNode")
.data(["offsetblur", "SourceGraphic"])
.enter()
.append("feMergeNode")
.attr("in", (d) => d);
// Add a cell for each leaf of the hierarchy.
const leaf = svg
.selectAll("g")
.data(leaves)
.join("g")
.attr("transform", (d) => `translate(${d.x0},${d.y0})`);
// A unique identifier for clip paths (to avoid conflicts).
const uid = `O-${Math.random().toString(16).slice(2)}`;
leaf
.append("clipPath")
.attr("id", (d) => (d.clipUid = `${uid}-${d.data.id}`))
.append("rect")
.attr("width", (d) => d.x1 - d.x0)
.attr("height", (d) => d.y1 - d.y0);
// Append a tooltip.
const format = d3.format(",d");
leaf.append("title").text((d) => d.data.kapittel);
// Append a color rectangle.
leaf
.append("rect")
.attr("fill", (d) => colorScale(d.data.data.diff))
.attr("fill-opacity", 0.6)
.attr("opacity", 0.4)
.attr("width", (d) => d.x1 - d.x0)
.attr("height", (d) => d.y1 - d.y0)
.attr("filter", (d) =>
d.data.data.kapittel === "Sikt" && highlightSikt
? "url(#drop-shadow)"
: null
); // Apply the filter conditionally
// leaf
// .append("text")
// //.attr("clip-path", (d) => d.clipUid)
// .attr(
// "font-size",
// (d) => tsizes[d.size] - calcSizeMinus(d.data.data.kapittel.length)
// )
// .attr("x", (d) => d.midx)
// .attr("y", (d) => d.midy)
// .attr("text-anchor", "middle")
// .attr("dominant-baseline", "middle")
// .attr("opacity", 0.8)
// .attr("transform", (d) =>
// d.rotate ? `rotate(90, ${d.midx}, ${d.midy})` : ""
// )
// .text((d) => `${d.data.data.kapittel} ${d.data.data.post}`);
const ytpos = (d, i) => {
return ttsizes[d.size] * (i + 1.4);
};
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 0))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => (d.h > 20 ? 1 : 0))
.attr("font-weight", "bold")
// .attr("text-anchor", "end")
.text((d) => d.data.data.kapittel);
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 1))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => (d.h > 30 ? 1 : 0))
// .attr("text-anchor", "end")
.text((d) => d.data.data.post);
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 2))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => (d.h > 36 ? 1 : 0))
// .attr("text-anchor", "end")
.text((d) => numFmt(d.data.data.sum25));
leaf
.append("text")
.attr("clip-path", (d) => `url(#${d.clipUid})`)
.attr("x", (d) => 4)
.attr("y", (d) => ytpos(d, 3))
.attr("font-size", (d) => ttsizes[d.size])
.attr("opacity", (d) => d.h > ytpos(d, 4) + 2)
// .attr("text-anchor", "end")
.text((d) => (d.data.data.diff ? diffFmt(d.data.data.diff) : "Nytt 2025"));
return svg.node();
}