Observed since 20 Oct, 22:12 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
@0k/time-chart
Framework-free linked time-series charts with local calendar guides.
Linked, zoomable time-series charts for the browser, built on Apache ECharts. No framework required.
link key
zoom together.npm install @0k/time-chart
import { createTimeChart } from '@0k/time-chart';
const now = Date.now();
const chart = createTimeChart(document.getElementById('chart')!, {
series: [{
id: 'sensor-a',
label: 'Sensor A',
points: [[now - 3_600_000, 2], [now, 3]],
}],
formatValue: value => value.toFixed(2),
onWindowChange: (start, end) => { /* fetch data for this window */ },
});
chart.setSeries(newSeries); // keeps the current window and hidden series
chart.setWindow(start, end);
chart.destroy();
The element must have a nonzero size. Times are Unix milliseconds.
| Field | Description |
|---|---|
id | Unique identifier |
label | Name shown in the legend and tooltip |
points | [time, value] pairs sorted by time; null value is a gap |
min, max | Optional band bounds, one per point |
group | Series of a group get close colors |
stack | Stack with the other stacked series |
color | Explicit CSS color instead of the generated one |
dash | 'solid' (default), 'dashed' or 'dotted' line style |
width | Finite positive line width in pixels (default 1); highlighting doubles it, dimming halves it |
fill | Opacity in (0,1]; fill to the bottom of the y axis, not stacked; cannot be combined with stack: true |
band | {pattern, opacity} for min / max bounds; pattern is 'solid' (default) or diagonal 'hatch' in the series color; opacity is in (0,1] (default 0.18) |
line | Draw the line (default true); false keeps its band/fill and legend entry but excludes it from the tooltip |
| Option | Default | Description |
|---|---|---|
series | required | Series to draw |
window | data extent | Initial {start, end} shown |
formatValue | localized number | Formats y-axis labels and tooltip values |
formatTime | localized date/time | Formats the tooltip time |
yAxis | {min, max, name, interval, minorInterval}; max: 'data' fixes it at 1.2 × data maximum (default) | |
yAxis.interval | automatic | Finite positive major tick and label step |
yAxis.minorInterval | disabled | Finite positive minor tick step with dashed minor split lines; requires interval and must divide it into an integer count from 2 to 99 |
tooltip | 'axis' | 'axis' (all series) or 'item' (one) |
legend | {show, collapsed, width, maxWidth}, scrolls, on right | |
legend.width | 340 | Column width in pixels, or 'auto' to fit the widest label |
legend.maxWidth | 240 for 'auto' | Caps the column; when set, also caps a numeric width |
link | Charts with the same key zoom, pan and hover together by time; their 'auto' legends share the widest column | |
onWindowChange | Called after the user zooms or pans | |
onLegendToggle | Called when the user toggles a series | |
locale | browser locale | Locale for labels and default formatters |
theme | 'auto' | 'auto', 'light' or 'dark' |
With legend: { width: 'auto' } the legend column is as wide as its
widest label: at least 80 pixels (less only if maxWidth is smaller),
at most maxWidth; longer labels are ellipsized and shown in full on
hover. Labels are measured again when setSeries changes them. Charts
sharing a link key and an 'auto' legend all take the widest column
of the group, each within its own maxWidth, so with the same
maxWidth their plots line up; the group adjusts when one of them
changes labels or is destroyed. A chart with a numeric width keeps it.
Charts sharing a link key are linked by time: after a user zoom or pan
they all show the same time window, and hovering one puts the others'
pointers at the same time, even when their data covers different ranges
or different timestamps. With tooltip: 'axis' each linked chart also
shows its tooltip, with the values of its own points nearest to that
time; with 'item' only the pointer is linked. A chart hides its
pointer when the time is outside the span of its points or outside its
window. onWindowChange fires on every affected chart after 150 ms
without another zoom or pan, with that chart's current window.
setWindow changes only the receiving chart and never fires the
callback; set it on each linked chart when choosing a range
programmatically.
| Method | Description |
|---|---|
setSeries(series) | Replace the data |
setWindow(start, end) | Show this time range (no onWindowChange) |
getWindow() | Current {start, end} |
setHidden(ids) | Hide these series |
highlight(ids) | Emphasize these series; null resets |
setLegendCollapsed(bool) | Hide or show the legend |
resize() | Redraw after a size change |
destroy() | Release the chart; safe to call twice |
calendarGuides(start, end, widthPx, now, locale?) is also exported: it
returns the guide lines and weekend bands for a time range, without
drawing anything.
npm install
npm run check # typecheck, tests, build
npm run demo # http://127.0.0.1:5187/demo/
To use a working copy from another project without changing its committed files:
npm run watch # here
npm install --no-save /path/to/time-chart # in the other project
MIT
Fit the legend to its labels, keeping linked charts aligned. [Valentin Lab]
With legend: { width: 'auto' } the legend column fits its widest label,
measured in the legend's font, between 80 pixels and legend.maxWidth
(240 by default; an explicit maxWidth below 80 wins); longer labels are
ellipsized. Charts sharing a link key with auto legends all take the
group's widest column, each within its own maxWidth, so with the same
maxWidth their plots line up; they adjust when one of them changes
labels or is destroyed.
maxWidth also caps a numeric width; an invalid value for either
now throws. The demo charts switch to auto legends.
Choose the step between y-axis labels, with dashed minor lines. [Valentin Lab]
yAxis.interval sets the step between y-axis labels, and
yAxis.minorInterval subdivides it with dashed minor lines. Invalid
values throw: minorInterval requires interval and must divide it
into an integer count from 2 to 99 (ECharts ignores more). Minor ticks
are drawn in the palette's axis color, so they follow the light and dark
themes.
Draw dashed, dotted, thick, filled, hatched and line-less series. [Valentin Lab]
Each series can now set its line style with dash ('solid',
'dashed' or 'dotted') and width in pixels, which highlighting
doubles and dimming halves. fill shades the area down to the bottom of
the y axis at the given opacity, without stacking.
band: {pattern, opacity} draws the min/max band solid or
hatched diagonally in the series color, at a chosen opacity.
line: false draws only a series' fill or band: it keeps its legend
entry but is left out of the tooltip.
Invalid widths and opacities throw, as do fill with stack: true and
band on a series without min and max.
Depend on ECharts 6, which npm audit no longer flags. [Valentin Lab]
ECharts 5 has a security advisory (GHSA-fgmj-fm8m-jvvx, an XSS in the
tooltip of lines series) that only 6.1.0 fixes, and 5.x gets no more
fixes. The charts drawn here never used a lines series, but every
consumer's npm audit reported it, with no way to resolve it.
Two ECharts 6 defaults are pinned back so the charts look as before:
grid.outerBoundsMode: "none": ECharts 6 shrinks the plot to fit
wide axis labels, which would move the plot away from the calendar
guides, the legend and the alignment of linked charts.yAxis.nameMoveOverlap: false: ECharts 6 pushes the y-axis name past
its labels, off the canvas; it stays 46 px from the axis line.AGENTS.md now names ~/dev/ts/rrd-graph as the consumer that uses
this working copy.
Contract:
echarts is ^6.1.0; the public API and options are unchanged.test/option.test.ts; demo/verify.py passes in Chrome,
and the demo renders as with ECharts 5.6 apart from ECharts' own
time-axis labelling.Link charts by time, so zoom, pan and hover line up when their data differs. [Valentin Lab]
echarts.connect relays a zoom as a percentage of each chart's own time
axis, and a hover as a data index of the hovered chart. Linked charts
whose data covered different ranges therefore showed different windows,
and hovering one put the other charts' pointers and tooltips at other
times, sometimes 600 px away, or nowhere.
The link registry now relays by time instead of using connect:
tooltip: "item", without a tooltip.Contract:
link group shows the same
window and fires onWindowChange once, after 150 ms; no echo.setWindow and setSeries never move another chart's window or
pointer; only a change of the shared auto-legend width redraws them.test/link.test.ts (real ECharts), test/chart.test.ts,
demo/verify.py in Chrome.Let a long legend scroll, aligned with the top of the plot. [Valentin Lab]
The legend was the canvas legend of echarts, which can only page with
small arrow buttons when its entries do not fit: the mouse wheel over it
zoomed the chart instead, and its first entry sat a few pixels below the
plot's top edge.
The legend is now an HTML list over the chart's right margin. It spans
exactly the plot's height, scrolls with the wheel without zooming the
chart or scrolling the page, and keeps its scroll position across
redraws. Long labels are truncated clear of overlay scrollbars and show
their full text on hover. Clicking an entry, or pressing Space or Enter
on it, still hides or shows its series and calls onLegendToggle;
hidden series are greyed out. The options and API are unchanged.
A host element with position: static is switched to relative so
the legend can be placed inside it.
Draw linked, zoomable time-series charts with calendar guides. [Valentin Lab]
Framework-free TypeScript library over Apache ECharts: day, month and year
guides fading with zoom density, hatched weekends, a "now" line, time-axis
wheel zoom and drag pan past the data, a y-axis fixed from the full data,
stacked areas, minimum and maximum bands, light and dark palettes following
the OS, and charts sharing a link key zooming together.
Draw the hatching of a weekend already in progress at the window start. [Valentin Lab]
A window starting on a Saturday or Sunday drew no hatching for that weekend, because bands were only emitted for Saturday midnights inside the window. The band of a weekend overlapping the window start is now drawn too.
Keep day guides on local midnight after a DST jump at midnight. [Valentin Lab]
In zones whose clocks jump at midnight (Chile, Azores, Cuba), the jump
day starts at 01:00. Stepping one Date forward with setDate carried
that 01:00 onto every following day guide and weekend band, until the
end of the window. Each day is now built from its date parts, so only
the jump day itself starts at 01:00.
Draw legend icons as solid swatches readable in dark mode. [Valentin Lab]
ECharts' default legend icon is an empty circle filled white, a glaring white dot on a dark background.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
echartsEnvironment{
"local_name": "echarts",
"alias": false,
"peer_metadata": null
} | ^6.1.0 | runtime |
viteEnvironment{
"local_name": "vite",
"alias": false,
"peer_metadata": null
} | 6.4.4 | development |
jsdomEnvironment{
"local_name": "jsdom",
"alias": false,
"peer_metadata": null
} | 25.0.1 | development |
vitestEnvironment{
"local_name": "vitest",
"alias": false,
"peer_metadata": null
} | 5.0.3 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | 5.7.3 | development |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | 22.10.5 | development |
Source distribution
{
"shasum": "ce0b530a7e5a7e0327c3479bd39170bc90acba14",
"tarball": "https://registry.npmjs.org/@0k/time-chart/-/time-chart-0.2.0.tgz",
"integrity": "sha512-u0X5znDqNxBzAox9rMsIhWHV/DZY7rQlFgLQTz7630F4MKZjPh1KJPAUCAgqP2uU6MpeSSDk52GTMLNv2VjKrQ==",
"fileCount": 20,
"unpackedSize": 78341,
"signatures": [
{
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U",
"sig": "MEUCIQDCr+Xoq3pTFoFuadZVm1QV/hkH+9EmJIBGX0BRh62NxgIgJ0y1yy7sVGnDk/mX+s9HxdH7vb12MTKODpm6Qy58bF0="
}
]
}Observed since 20 Oct, 22:12 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:e00c960c91b3277a5710d130bfda2e09cd8af05056caaf46db14413f50e21741