PlotInput = ({
defaultValue = Array.from({ length: 12 }, (_, i) => ({ x: i, y: i }))
} = {}) => {
let data = [].concat(defaultValue);
const width = 600,
height = 400;
const svg = d3.create("svg").attr("width", width).attr("height", height);
let padding = 10;
const xScale = d3
.scaleLinear()
.domain([0, 11])
.range([padding, width - padding]);
const yScale = d3
.scaleLinear()
.domain([0, 11])
.clamp(true)
.range([height - padding, padding]);
const lineGenerator = d3
.line()
.x((d) => xScale(d.x))
.y((d) => yScale(d.y));
const dragger = d3.drag().on("start drag", function (event) {
const x = Math.round(xScale.invert(event.x));
const y = yScale.invert(event.y);
if (x >= 0 && x < 12) {
data[x].y = y;
svg.select(".line").attr("d", lineGenerator(data));
svg
.selectAll(".dot")
.data(data)
.join("circle")
.attr("class", "dot")
.attr("cx", (d) => xScale(d.x))
.attr("cy", (d) => yScale(d.y))
.attr("r", 8);
node.dispatchEvent(new CustomEvent("input"));
}
});
svg
.append("path")
.datum(data)
.attr("class", "line")
.attr("d", lineGenerator)
.attr("fill", "none")
.attr("stroke", "steelblue");
svg
.selectAll(".dot")
.data(data)
.join("circle")
.attr("class", "dot")
.attr("cx", (d) => xScale(d.x))
.attr("cy", (d) => yScale(d.y))
.attr("r", 8);
svg.call(dragger);
const node = svg.node();
Object.defineProperty(node, "value", {
get() {
return data.map((d) => d.y);
},
set(newData) {
data = newData.map((d, i) => ({ x: i, y: d }));
svg
.selectAll(".dot")
.data(data)
.join("circle")
.attr("class", "dot")
.attr("cx", (d) => xScale(d.x))
.attr("cy", (d) => yScale(d.y))
.attr("r", 8);
svg
.select(".line")
.datum(data)
.attr("class", "line")
.attr("d", lineGenerator)
.attr("fill", "none")
.attr("stroke", "steelblue");
}
});
node.value = data.map((d) => d.y);
return node;
}