Askr documentation
UI & Components

Live Data and View State

Live Data and View State: anatomy, keyboard behavior, state, and theming in Askr.

Example

import { state } from '@askrjs/askr';
import { createPlot, type PlotView } from '@askrjs/charts';

const Plot = createPlot<MetricRow>();

function LiveLatency() {
  const [view, setView] = state<PlotView>({});
  return <Plot.Root
    data={rows()}
    rowKey="id"
    label="Live latency"
    view={view()}
    onViewChange={setView}
    followLatest={{ durationMs: 300_000, field: 'timestamp' }}
  ><Plot.Line x="timestamp" y="latencyMs" /></Plot.Root>;
}

Append and upsert

`appendPlotRows(rows, additions)` adds one or many rows to the end of an array without mutating the original. `upsertPlotRows(rows, updates, rowKey)` replaces any row whose key matches an update and appends the rest, and rejects duplicate keys within the update batch itself — both return a frozen result, or the original array when nothing actually changed.

Trim rows

`trimPlotRows(rows, options)` keeps a live array from growing without bound. Pass a plain number (or `{ rows: N }`) to retain the latest N rows by position, or `{ durationMs, field, now? }` to retain only rows whose `Date` field falls within a trailing time window — the natural pairing for a plot that's also using `followLatest`.

Follow latest

`Root`'s `followLatest` prop accepts a bare number as row-count shorthand, `{ rows: N }`, or `{ durationMs, field }` for a time-based window, and keeps the visible view pinned to the newest data as it arrives. Any user pan or zoom pauses following immediately, and it stays paused — even as more rows come in — until the app calls `PlotApi.resumeLive()`, so an operator inspecting an anomaly is never yanked back to "now" mid-investigation.

Controlled view

`PlotView` holds optional `x` and `y` domain tuples plus a `scales` map for named coordinate scales; `x`/`y` are shorthand aliases for the primary scales, and an entry in `scales` takes precedence for that specific scale. Use `defaultView` when the view can live entirely inside the plot, or `view` together with `onViewChange` when a URL, route, or sibling control needs to own and synchronize the visible domain.