Use Data Window
Fetch what the window shows, and nothing twice.
Preview
Scroll to zoom, drag to pan. Hovering the sequence highlights the position across the domain/site/coverage tracks.
About
track-viewer is the only component here that streams, not because the others don't need to but because the logic lived inside its render function with no way to reach it. viewer-frame owns the display half of async; this is the windowed half, and the four behaviours that make panning usable: debounce (a pan fires at pointer rate), overfetch (so a small pan is served from what's in hand), a cache test that rejects a span too much wider than the view to be detailed enough, and aborting superseded requests so a drag's trail of answers can't land out of order. Last-good data is retained through a refetch, which is what stops a pan from strobing empty.
Usage
import { useDataWindow } from "@/components/ui/use-data-window"
const { data, status, refreshing } = useDataWindow({
window: { start: viewport.start, end: viewport.end },
bounds: [0, chromLength],
deps: [refName],
load: (query, signal) => source.getFeatures({ refName, ...query }, signal),
})components/ui/use-data-window.ts