chart = {
const series = d3.rollup(data, (values, i) => d3.sort(values, d => d.date), d => d.name);
const marginTop = 30;
const marginRight = 10;
const marginBottom = 0;
const marginLeft = 10;
const width = 928;
const size = 25;
const height = series.size * size + marginTop + marginBottom;
const padding = 1;
const x = d3.scaleUtc()
.domain(d3.extent(data, d => d.date))
.range([0, width])
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([size, size - bands * (size - padding)]);
const area = d3.area()
.defined(d => !isNaN(d.value))
.x((d) => x(d.date))
.y0(size)
.y1((d) => y(d.value));
const uid = `O-${Math.random().toString(16).slice(2)}`;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");
const g = svg.append("g")
.selectAll("g")
.data(series)
.join("g")
.attr("transform", (d, i) => `translate(0,${i * size + marginTop})`);
const defs = g.append("defs");
defs.append("clipPath")
.attr("id", (_, i) => `${uid}-clip-${i}`)
.append("rect")
.attr("y", padding)
.attr("width", width)
.attr("height", size - padding);
defs.append("path")
.attr("id", (_, i) => `${uid}-path-${i}`)
.attr("d", ([, values]) => area(values));
g.append("g")
.attr("clip-path", (_, i) => `url(${new URL(`#${uid}-clip-${i}`, location)})`)
.selectAll("use")
.data((_ ,i) => new Array(bands).fill(i))
.enter().append("use")
.attr("xlink:href", (i) => `${new URL(`#${uid}-path-${i}`, location)}`)
.attr("fill", (_, i) => colors[i])
.attr("transform", (_, i) => `translate(0,${i * size})`);
g.append("text")
.attr("x", 4)
.attr("y", (size + padding) / 2)
.attr("dy", "0.35em")
.text(([name]) => name);
svg.append("g")
.attr("transform", `translate(0,${marginTop})`)
.call(d3.axisTop(x).ticks(width / 80).tickSizeOuter(0))
.call(g => g.selectAll(".tick").filter(d => x(d) < marginLeft || x(d) >= width - marginRight).remove())
.call(g => g.select(".domain").remove());
return svg.node();
}