function BarChart(
data,
{
x = (d, i) => i,
y = (d) => d,
title,
marginTop = 20,
marginRight = 0,
marginBottom = 30,
marginLeft = 40,
width = 640,
height = 400,
xDomain,
xRange = [marginLeft, width - marginRight],
yType = d3.scaleLinear,
yDomain,
yRange = [height - marginBottom, marginTop],
xPadding = 0.1,
yFormat,
yLabel,
color = (d) => d
} = {}
) {
const X = d3.map(data, x);
const Y = d3.map(data, y);
const Color = d3.map(data, color);
if (xDomain === undefined) xDomain = X;
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
xDomain = new d3.InternSet(xDomain);
// Omit any data not present in the x-domain.
const I = d3.range(X.length).filter((i) => xDomain.has(X[i]));
// Construct scales, axes, and formats.
const xScale = d3.scaleBand(xDomain, xRange).padding(xPadding);
const yScale = yType(yDomain, yRange);
const xAxis = d3.axisBottom(xScale).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);
// Compute titles.
if (title === undefined) {
const formatValue = yScale.tickFormat(100, yFormat);
title = (i) => `${X[i]}\n${formatValue(Y[i])}`;
} else {
const O = d3.map(data, (d) => d);
const T = title;
title = (i) => T(O[i], i, data);
}
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr(
"style",
"max-width: 100%; height: auto; height: intrinsic;background-color:#404040"
);
svg
.append("g")
.attr("class", "axisWhite")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call((g) => g.select(".domain").remove())
.call((g) =>
g
.selectAll(".tick line")
.clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.25)
)
.call((g) =>
g
.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("text-anchor", "start")
.text(yLabel)
);
const bar = svg
.append("g")
.selectAll("rect")
.data(I)
.join("rect")
.attr("fill", (i) => Color[i])
.attr("x", (i) => xScale(X[i]))
.attr("y", (i) => yScale(Y[i]))
.attr("height", (i) => yScale(0) - yScale(Y[i]))
.attr("width", xScale.bandwidth());
if (title) bar.append("title").text(title);
svg
.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.attr("class", "axisWhite")
.call(xAxis);
return svg.node();
}