Observed since 20 Oct, 22:12 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Vue 3 graph card for kal-rrd-graph time series: visible-first loading, live tails and linked pan/zoom.
Vue 3 graph card for the time series served by the kal-rrd-graph HTTP
API (api/graph, api/watch). One card fetches and draws one graph,
keeps its data while a new window loads, follows file changes with small
tail requests, and reports user pan/zoom so linked charts move together.
A chart's legend is as wide as its longest label (up to 240 pixels,
longer labels are ellipsized), and the charts of a page share the widest
legend so their plots line up. Several cards on a page share one
scheduler: visible cards load first, then the next four below are
prefetched.
The package knows nothing about how the host organizes its graphs, routing or period selection: the host gives each card a graph descriptor and a time window, and decides what a pan/zoom does.
npm install @0k/rrd-graph vue
vue (^3.5.12) is a peer dependency. Load the card stylesheet
after the host stylesheet (see Styling):
import './styles.css'
import '@0k/rrd-graph/style.css'
A card without an injected scheduler schedules itself: it loads once it is on screen.
<script setup lang="ts">
import { computed, ref } from 'vue'
import { GraphCard, useGraphWatch, type GraphDescriptor, type TimeWindow } from '@0k/rrd-graph'
const graph: GraphDescriptor = { id: 'load-average', title: 'Load average', type: 'line', stack_toggle: false, unit: null }
const now = ref(Math.floor(Date.now() / 1000))
// The last day, live, until the user pans or zooms the chart.
const pinned = ref<TimeWindow | null>(null)
const timeWindow = computed<TimeWindow>(() => pinned.value ?? { start: now.value - 86400, end: now.value, live: true })
// Optional: tail the graph when its RRD files change.
const changes = useGraphWatch(computed(() => [graph.id]), timeWindow, now)
function onWindow(start: number, end: number): void {
pinned.value = { start, end, live: false }
}
</script>
<template>
<aside class="host-panel">…</aside>
<GraphCard :graph="graph" :window="timeWindow" :change="changes[graph.id] ?? 0" @window="onWindow" />
</template>
A live window is computed from now: useGraphWatch advances now
when a change arrives, and a pure live slide only pans the data already
held.
Provide one scheduler for the displayed cards, in display order:
import { computed, provide, type Ref } from 'vue'
import { GRAPH_SCHEDULER, useGraphScheduler, useGraphWatch, type GraphDescriptor, type TimeWindow } from '@0k/rrd-graph'
// The host's displayed graphs, window and clock, as in the example above.
declare const graphs: Ref<GraphDescriptor[]>, timeWindow: Ref<TimeWindow>, now: Ref<number>
const ids = computed(() => graphs.value.map(graph => graph.id))
provide(GRAPH_SCHEDULER, useGraphScheduler(ids))
const changes = useGraphWatch(ids, timeWindow, now)
GraphCard| Prop | Type | Default | Meaning |
|---|---|---|---|
graph | GraphDescriptor | required | id, title, type (line / stacked), stack_toggle, unit |
window | TimeWindow | required | { start, end, live } in Unix seconds |
revision | number | 0 | Host configuration revision; a change reloads the window |
change | number | 0 | Change counter from useGraphWatch; a change fetches a tail |
tall | boolean | false | Taller chart, for a page showing a single graph |
apiBase | string | api/ | URL prefix of the kal-rrd-graph API |
Event window(start, end): the user panned or zoomed the chart (Unix
seconds).
A failed request, or data the chart refuses to draw (for instance a
point whose min exceeds its max), shows its message in the card's
error banner with a Retry button.
apiBase is relative by default, so the host works at / and behind a
reverse-proxy prefix. Never pass an absolute /api/.
TimeSeriesChart: the chart alone (data, window, tall,
stacked props; window, ready and error(message) events:
error replaces ready when @0k/time-chart rejects the data).useGraphScheduler(order), GRAPH_SCHEDULER, admitted,
PRELOAD_COUNT: visible-first admission.useGraphWatch(ids, window, now, { apiBase }): one api/watch
subscription for the displayed set; returns per-graph change counters.fetchGraph, parseGraph, parseGraphDescriptor,
parseWatchSnapshot, parseGraphChange, requestJson, apiUrl and
the expect* validators. Also available without Vue from
@0k/rrd-graph/api.tailRange, mergeTail, toTimeSeries, toYAxis, samplePoints,
isStale, formatValue, formatDate.The graph YAML's drawing keys (documented in kal-rrd-graph's README,
"Series entries" and "Y axis") reach the card as optional api/graph
fields, which parseGraph validates and the chart passes to
@0k/time-chart unchanged in meaning:
api/graph field | @0k/time-chart option |
|---|---|
series color | TimeSeries.color |
series dash | TimeSeries.dash: solid, dashed or dotted |
series width | TimeSeries.width |
series fill | TimeSeries.fill (area to the axis bottom) |
series band: {pattern, opacity} | TimeSeries.band over min / max |
series line: false | TimeSeries.line: false (no line, no tooltip) |
graph y_axis.min / max | yAxis.min / yAxis.max |
graph y_axis.interval | yAxis.interval |
graph y_axis.minor_interval | yAxis.minorInterval |
Absent fields set nothing, so unstyled graphs draw as before. Series are
drawn in list order. A tail merge takes the drawing keys of the newest
response. The y axis is fixed when a chart is created; a changed
y-axis applies the next time the card's chart is created (e.g. when it
becomes visible again).
style.css lays out the card and the chart. Colours are custom
properties with light defaults; map them to the host theme:
:root {
--rrd-graph-placeholder-background: var(--c-bg);
--rrd-graph-muted: var(--c-text-muted);
--rrd-graph-accent: var(--c-accent);
--rrd-graph-accent-soft: var(--c-accent-soft);
--rrd-graph-danger: var(--c-danger);
--rrd-graph-danger-soft: var(--c-danger-soft);
--rrd-graph-radius: var(--radius-sm);
--rrd-graph-small-font-size: var(--fs-small);
}
The card frame uses host classes: section, section__head,
section__note, error-banner, muted, and the host's button style.
.graph-card overrides the .section padding, hence the load order
above.
npm install
npm test # vitest run, source modules
npm run typecheck
npm run build # dist/: ES modules, style.css, declarations
npm run test:package # Vitest built-artifact checks (after build)
npm run check # all of the above
MIT
Describe the card as a client of the kal-rrd-graph HTTP API. [Valentin Lab]
The README.org, the npm description and keywords, and the comments of
the shipped modules said the time series and apiBase belonged to one
application using the card. They are served by the kal-rrd-graph HTTP
API (api/graph, api/watch), so the documentation now names it.
Draw the series styles, bands and y-axis steps that kal-rrd-graph serves. [Valentin Lab]
kal-rrd-graph graphs can set each series' color, dash,
width and fill, draw a band between two data sources (solid
or hatched, without a line) and set the y axis bounds and tick steps.
The card now hands these to @0k/time-chart: series fields map onto
the TimeSeries options of the same name (band painting the
series' min to max area, line: false leaving out its line and
tooltip entry), and the graph's y_axis onto yAxis, with
minor_interval becoming minorInterval.
parseGraph validates these fields when present and rejects malformed
ones: an unknown dash or band pattern, a width not above 0, a fill or
opacity outside (0, 1], a band without min and max, an unknown
y_axis key, an interval not above 0, a minor_interval that
does not divide interval into 2 to 99 steps. Absent fields set
nothing, so unstyled graphs draw as before. A tail merge takes the
drawing keys of the newest response; the y axis is set when a chart is
created.
Data the chart still refuses, such as a point whose min exceeds its
max or a filled series switched to stacked, shows its message in the
card's error banner instead of leaving a blank chart, and the card
counts as loaded, so the page goes on prefetching the next cards.
TimeSeriesChart emits it as an error event in place of
ready.
New exports: toYAxis and the SeriesStyle, GraphYAxis,
Dash and BandPattern types.
Show live RRD graphs served by kal-rrd-graph in a Vue card. [Valentin Lab]
GraphCard fetches one graph from api/graph and draws it with
@0k/time-chart. It loads only when scrolled into view, follows the
window chosen by the page, and while the window reaches the present it
watches the graph's RRD files through api/watch and fetches only
the new tail when they change.
A card used on its own creates its own scheduler, so an application can
embed a single graph; a page showing many graphs shares one. Requests
use a relative apiBase, so the app works behind a path prefix.
Extracted from rrd-ui without any change of behavior, except that a
graph response with an empty series label is now rejected, as
@0k/time-chart cannot draw it. The entries load through both
import and require() (Node 22.12+), and their declarations use
.js specifiers, so the framework-free @0k/rrd-graph/api entry
is typed under node16 module resolution too.
Give the plot the width the legend does not need. [Valentin Lab]
Chart legends were a fixed 300 pixels wide however short the series
labels, and that width was taken from the plot. A legend now fits its
widest label (up to 240 pixels; longer labels are ellipsized). As every
chart of the package shares one link key, each mounted chart takes
the widest legend among them, so the plots of a page's cards still line
up.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.1Registry latest | 12 Oct 2026 | 9 | |
| 0.1.0 | 12 Oct 2026 | 9 | |
| 0.0.0-stage | 12 Oct 2026 | 0 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 22:12 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:f7a8fb4abb86b3c13480267513fc20bf16993e7070c54966a6225245243be077