Here is the component—it's pretty ugly, I think—but this used to be in the Svelte file within the route of a dashboard page. Figured it was a good idea to extract it out as a component. Now that it's working, I wanted to write about it to make sure I completely understand the process and nail down all the Svelte concepts that are still a little unclear to me. ```ts <script lang="ts"> import { onMount } from "svelte"; import * as d3 from "d3"; import { pointer } from "d3-selection"; export let width = 1040; export let height = 400; export let marginTop = 20; export let marginRight = 20; export let marginBottom = 30; export let marginLeft = 40; type ObservationPlotData = { datetime: string; value: number; }; let svg; let gx; let gy; let gp; let gvertline; export let observations: ObservationPlotData[]; $: xScale = d3 .scaleTime() .domain(d3.extent(observations, (d) => new Date(d.datetime))) .range([marginLeft, width - marginRight]); $: yScale = d3 .scaleLinear() .domain(d3.extent(observations, (d) => parseFloat(d.value))) .range([height - marginBottom, marginTop]); $: lineGenerator = d3 .line() .x((d) => xScale(new Date(d.datetime))) .y((d) => yScale(parseFloat(d.value))); $: path = lineGenerator(observations); onMount(() => { const svg_element = d3.select("svg"); // set up the xaxis gx = svg_element .append("g") .attr("transform", `translate(0, ${height - marginBottom})`) .call(d3.axisBottom(xScale)); // set up the yaxis gy = svg_element .append("g") .attr("transform", `translate(${marginLeft},0)`) .call(d3.axisLeft(yScale)); gp = svg_element .append("g") .attr("fill", "none") .attr("stroke", "steelblue") .attr("stroke-width", 1.5); gp.append("path").attr("d", path); gvertline = svg_element.append("g").attr("pointer-events", "none"); gvertline .append("path") .attr("stroke", "#999") .attr("stroke-width", 1) .attr("stroke-dasharray", "5,5"); svg_element.on("mousemove", handle_mouse_event).on("mouseleave", handle_mouse_leave); }); function handle_mouse_event(event) { const [mouse_position] = pointer(event); console.log("handling the mouse event, mouse it at:", mouse_position); const nearest_date_index = d3 .bisector((d) => new Date(d.datetime)) .left(observations, xScale.invert(mouse_position)); const nearest_obs = observations[nearest_date_index]; if (nearest_obs) { gvertline .attr("transform", `translate(${xScale(new Date(nearest_obs.datetime))},0)`) .style("display", null); gvertline.select("path").attr("d", `M0,${height - marginBottom}V${marginTop}`); } } function handle_mouse_leave() { gvertline.style("display", "none"); } </script> <svg bind:this={svg} {width} {height}></svg> ```