ml-time-graph 1.3.3 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +9 -0
- package/README.md +9 -0
- package/SKILLS.md +183 -0
- package/USAGE.md +91 -4
- package/dist/index.d.ts +21 -5
- package/dist/index.js +34 -34
- package/dist/interaction/index.d.ts +1 -1
- package/dist/internals.d.ts +5 -93
- package/dist/internals.js +22 -22
- package/dist/{scale-CWAa8-uO.d.ts → scale-ByGpczxS.d.ts} +30 -1
- package/dist/{layout-3caueyKS.d.ts → series_renderer-BxGvCHMY.d.ts} +107 -2
- package/package.json +10 -8
package/README.de.md
CHANGED
|
@@ -7,6 +7,15 @@ schnell und unkompliziert aufbereiten, mit Fokus auf Reporting und Incident-Anal
|
|
|
7
7
|
|
|
8
8
|
> Voll typisiert · i18n-aware · DOM-freier SVG-Renderer (Browser & serverseitig) · keine Laufzeit-Abhängigkeiten · ESM-only
|
|
9
9
|
|
|
10
|
+
> 🤖 **Sie arbeiten mit einem KI-Assistenten?** Geben Sie ihm
|
|
11
|
+
> **[SKILLS.md](SKILLS.md)** — die Datei wird mitgeliefert und liegt nach
|
|
12
|
+
> `npm install` unter `node_modules/ml-time-graph/SKILLS.md`. Eine Seite: der
|
|
13
|
+
> kürzeste Weg zum Diagramm, die vier Einstiegspunkte, die üblichen Aufgaben und
|
|
14
|
+
> ein Abschnitt **Traps** für die Stellen, an denen ein Modell danebengreift
|
|
15
|
+
> (Zeitstempel sind Millisekunden, Ränder werden nicht aus den Beschriftungen
|
|
16
|
+
> gemessen, `resolveDash` statt `getLineStyle`). Das ist der Unterschied zwischen
|
|
17
|
+
> Code, der übersetzt, und Code, der zeichnet, was gemeint war.
|
|
18
|
+
|
|
10
19
|
## Installation
|
|
11
20
|
|
|
12
21
|
```bash
|
package/README.md
CHANGED
|
@@ -7,6 +7,15 @@ clear, readable charts quickly, with a focus on reporting and incident analysis.
|
|
|
7
7
|
|
|
8
8
|
> Fully typed · i18n-aware · DOM-free SVG output (browser & server) · zero runtime dependencies · ESM-only
|
|
9
9
|
|
|
10
|
+
> 🤖 **Working with an AI coding assistant?** Point it at
|
|
11
|
+
> **[SKILLS.md](SKILLS.md)** — it ships inside the package, so after
|
|
12
|
+
> `npm install` it sits at `node_modules/ml-time-graph/SKILLS.md`. One page:
|
|
13
|
+
> the shortest path to a chart, the four entry points, the recipes, and a
|
|
14
|
+
> **Traps** section for the places a model guesses wrong (timestamps are epoch
|
|
15
|
+
> milliseconds, margins are not measured from the labels, `resolveDash` vs
|
|
16
|
+
> `getLineStyle`). It is the difference between code that compiles and code
|
|
17
|
+
> that draws what you meant.
|
|
18
|
+
|
|
10
19
|
## Install
|
|
11
20
|
|
|
12
21
|
```bash
|
package/SKILLS.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# SKILLS.md — Agent Quick Start for `ml-time-graph`
|
|
2
|
+
|
|
3
|
+
MLTimeGraph is a TypeScript library for visualizing any time-series measurement data (telemetry, physical sensors, system metrics, logs, finance, laboratory or process measurements). Its standout capability is rich contextual annotation — turning raw curves into explanatory records with free-form annotations (arrows, labels, callout rects in data coordinates), time-range highlights, status/phase bands, and threshold zones. It has a single defining architectural property: it generates SVG as a pure string without touching the DOM — the exact same call runs identically in the browser and on the server.
|
|
4
|
+
|
|
5
|
+
For the exhaustive reference, see [USAGE.md](USAGE.md) next to this file.
|
|
6
|
+
|
|
7
|
+
## Shortest Path to a Visible Chart
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { mount } from 'ml-time-graph';
|
|
11
|
+
|
|
12
|
+
mount('#chart', {
|
|
13
|
+
width: 800,
|
|
14
|
+
height: 400,
|
|
15
|
+
series: [
|
|
16
|
+
{
|
|
17
|
+
name: 'Temperature',
|
|
18
|
+
data: [
|
|
19
|
+
{ time: 1704067200000, value: 21.5 },
|
|
20
|
+
{ time: 1704070800000, value: 22.8 },
|
|
21
|
+
{ time: 1704074400000, value: 20.3 },
|
|
22
|
+
],
|
|
23
|
+
style: { line: { color: '#ef4444' } },
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## When to Use What
|
|
30
|
+
|
|
31
|
+
- `mount(target, options)`: The declarative browser shortcut when a DOM element or selector exists — measures container width, renders SVG, and injects markup in one call.
|
|
32
|
+
- `new MLTimeGraph(options)`: The core headless engine when working with options objects directly — use for Node.js SSR, headless testing, or custom render pipelines.
|
|
33
|
+
- Builders (`GraphBuilder`, etc.): The fluent, imperative chaining API — use when assembling charts dynamically across conditional branches.
|
|
34
|
+
- Go port (`go-time-graph`): The 1:1 server-side Go implementation (`gitlab.com/mlc0911/mlctimegraph/go-time-graph`) — use when rendering charts in Go backends or microservices without a Node runtime.
|
|
35
|
+
|
|
36
|
+
## Package Entry Points
|
|
37
|
+
|
|
38
|
+
- `ml-time-graph`: Core chart rendering API — `mount`, `MLTimeGraph`, `SVGRenderer`, `GraphBuilder`, `attachTooltip`, types, and legend helpers (`resolveDash`, `drawMarker`).
|
|
39
|
+
- `ml-time-graph/analyze`: Pure-math statistics companion — `aggregateBySlot`, `downsample` (LTTB), `detectGaps`, `rollingMkt`, `rollingStdDev`, `computeLimitExcursions`, `StatsAggregator`.
|
|
40
|
+
- `ml-time-graph/interaction`: Headless interaction primitives — `Zoom`, `Minimap`, and coordinate-based interaction state management.
|
|
41
|
+
- `ml-time-graph/internals`: Low-level building blocks for custom renderers — `DrawCommand` model, base `Renderer`, layout engine, scales, and axis renderers.
|
|
42
|
+
|
|
43
|
+
## Common Tasks
|
|
44
|
+
|
|
45
|
+
### Multiple Series & Multi-Axis
|
|
46
|
+
Map series to vertical axes via `yAxisIndex`:
|
|
47
|
+
```ts
|
|
48
|
+
mount('#chart', {
|
|
49
|
+
margin: { top: 20, right: 80, bottom: 40, left: 60 },
|
|
50
|
+
series: [
|
|
51
|
+
{ name: 'Temp', data: tempData, yAxisIndex: 0, style: { line: { color: '#ef4444' } } },
|
|
52
|
+
{ name: 'Humidity', data: humData, yAxisIndex: 1, style: { line: { color: '#3b82f6', style: 'dashed' } } },
|
|
53
|
+
],
|
|
54
|
+
axes: {
|
|
55
|
+
left: { label: 'Temperature (°C)' },
|
|
56
|
+
right: { label: 'Humidity (%)' },
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Thresholds & Zone Colouring
|
|
62
|
+
Define thresholds once and reference them by name to colour lines or zones:
|
|
63
|
+
```ts
|
|
64
|
+
mount('#chart', {
|
|
65
|
+
thresholds: [
|
|
66
|
+
{ name: 'warn', value: 25, color: '#f59e0b', line: 'dashed', label: 'Warning' },
|
|
67
|
+
{ name: 'crit', value: 30, color: '#ef4444', line: 'solid', label: 'Critical' },
|
|
68
|
+
],
|
|
69
|
+
series: [{ name: 'Temp', data: tempData, colorByThresholds: ['warn', 'crit'] }],
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Filled Areas Between Curve and Threshold
|
|
74
|
+
Use `style.fill.regions` with bounds (`from`, `to`, `side`, optional `hatch`):
|
|
75
|
+
```ts
|
|
76
|
+
style: {
|
|
77
|
+
fill: {
|
|
78
|
+
regions: [
|
|
79
|
+
{ from: { threshold: 'warn' }, to: 'series', side: 'above', fill: { color: '#f59e0b33', hatch: 'classic-diagonal' } },
|
|
80
|
+
{ from: { threshold: 'crit' }, to: 'series', side: 'above', fill: '#ef444444' },
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Annotations & Region Highlights
|
|
87
|
+
Enrich charts with domain context: vertical time-span highlights across the plot, free-form annotations in data coordinates (which automatically scale through zoom/resize), and status bands below:
|
|
88
|
+
```ts
|
|
89
|
+
mount('#chart', {
|
|
90
|
+
series,
|
|
91
|
+
// Vertical time-range highlight behind the data:
|
|
92
|
+
highlights: [
|
|
93
|
+
{ startTime: t1, endTime: t2, label: 'Calibration Phase', color: '#3b82f6', opacity: 0.15 },
|
|
94
|
+
],
|
|
95
|
+
// Overlays anchored in data coordinates (time/value) tracking zoom & resize:
|
|
96
|
+
annotations: [
|
|
97
|
+
{ type: 'arrow', from: { time: t1, value: 20 }, to: { time: t2, value: 35 }, color: '#ef4444' },
|
|
98
|
+
{ type: 'label', at: { time: t2, value: 35 }, text: 'Pressure Spike', dy: -10 },
|
|
99
|
+
{ type: 'rect', from: { time: t1, value: 15 }, to: { time: t2, value: 25 }, fill: '#10b98122' },
|
|
100
|
+
],
|
|
101
|
+
// Horizontal status/phase bands below the plot (sharing the time axis):
|
|
102
|
+
annotationBands: [
|
|
103
|
+
{
|
|
104
|
+
name: 'Operating State',
|
|
105
|
+
height: 20,
|
|
106
|
+
items: [
|
|
107
|
+
{ startTime: t1, endTime: t2, label: 'Running', fill: '#22c55e44' },
|
|
108
|
+
{ startTime: t2, endTime: t3, label: 'Standby', fill: '#eab30844' },
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Data Gaps
|
|
116
|
+
`value: null` marks missing data and breaks the line. Connect with a bridge or render gap spans:
|
|
117
|
+
```ts
|
|
118
|
+
series: [{
|
|
119
|
+
name: 'Sensor',
|
|
120
|
+
data: [{ time: 1704067200000, value: 20 }, { time: 1704070800000, value: null }, { time: 1704074400000, value: 25 }],
|
|
121
|
+
style: {
|
|
122
|
+
line: { color: '#3b82f6' },
|
|
123
|
+
gap: { display: 'bridge_line', bridge: { color: '#94a3b8', width: 1.5, style: 'dotted' } },
|
|
124
|
+
},
|
|
125
|
+
}]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Markers
|
|
129
|
+
Render sample markers on curves or standalone timestamp event lines:
|
|
130
|
+
```ts
|
|
131
|
+
series: [{
|
|
132
|
+
name: 'Sensor',
|
|
133
|
+
data: sensorData,
|
|
134
|
+
style: { markers: { type: 'circle', size: 3, stroke: '#3b82f6', fill: '#ffffff', threshold: 100 } },
|
|
135
|
+
}],
|
|
136
|
+
markers: [
|
|
137
|
+
{ time: 1704070800000, value: 25, label: 'Peak event', color: '#ef4444', lineStyle: 'to-value' },
|
|
138
|
+
]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Axes & Margins
|
|
142
|
+
The layout engine cannot measure rendered text. Always allocate sufficient margins for labels:
|
|
143
|
+
```ts
|
|
144
|
+
margin: { top: 20, right: 80, bottom: 40, left: 60 },
|
|
145
|
+
axes: {
|
|
146
|
+
x: { label: 'Time', format: (d: Date) => d.toISOString().slice(11, 16) },
|
|
147
|
+
left: { label: 'Temperature (°C)', format: (v: number) => `${v.toFixed(1)} °C` },
|
|
148
|
+
right: { label: 'Humidity (%)', format: (v: number) => `${v.toFixed(0)} %` },
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Tooltips & Interactive Projections
|
|
153
|
+
Attach DOM tooltips or use pixel/data coordinate projections:
|
|
154
|
+
```ts
|
|
155
|
+
// Built-in DOM tooltip:
|
|
156
|
+
const chart = mount('#chart', { series, tooltip: { show: true } });
|
|
157
|
+
|
|
158
|
+
// Interactive coordinate projections (crosshairs, zoom, scrubbers):
|
|
159
|
+
chart.renderCommands();
|
|
160
|
+
const timeMs = chart.invertTime(pixelX);
|
|
161
|
+
const value = chart.invertValue(pixelY, yAxisIndex);
|
|
162
|
+
const { x, y } = chart.project(timeMs, value, yAxisIndex);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Server-Side Rendering (Node.js)
|
|
166
|
+
Generate pure SVG strings without browser dependencies:
|
|
167
|
+
```ts
|
|
168
|
+
import { MLTimeGraph, SVGRenderer } from 'ml-time-graph';
|
|
169
|
+
import * as fs from 'node:fs';
|
|
170
|
+
|
|
171
|
+
const chart = new MLTimeGraph({ width: 800, height: 400, series });
|
|
172
|
+
const { content } = new SVGRenderer().render(chart.renderCommands());
|
|
173
|
+
fs.writeFileSync('chart.svg', content);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Traps (Read Before Coding)
|
|
177
|
+
|
|
178
|
+
- **Timestamps are numbers, not Date objects:** `time` is always milliseconds since Unix epoch (`number`). Passing a `Date` object fails typechecking or evaluates to `NaN`.
|
|
179
|
+
- **Labels are not measured (fixed margins):** The renderer has no DOM and cannot compute text bounding boxes. Margins default to `{ top: 20, right: 20, bottom: 40, left: 60 }`. If you add a right Y-axis or formatted units (e.g. `120.5 °C`), `right: 20` will clip the labels against the SVG edge. A clipped number is a wrong number, not an incomplete one (`120` clipped to `20`). Always set `margin.right` explicitly (e.g. 70–90 px) when using right axes.
|
|
180
|
+
- **`resolveDash()` vs `getLineStyle()`:** `dashed` and `dotted` predate the scalable dash table and keep fixed SVG patterns (`"4,4"` and `"2,4"`) in the renderer for backwards compatibility. `getLineStyle()` returns the scalable table (`"6, 4"` for width 2). Anyone rendering custom legend swatches must call `resolveDash(variant, width)` so the swatch matches what is actually drawn.
|
|
181
|
+
- **Marker suppression at threshold:** `style.markers.threshold` (and default `theme.pointThreshold = 100`) hides point markers when series sample count exceeds it to prevent visual crowding. Crucially, `chart.legendItems()` also omits the `marker` property when points are suppressed, because a symbol in the legend missing from the curve states something untrue.
|
|
182
|
+
- **Built-in legend is static SVG:** Built-in legends (`inside-right`, etc.) are non-interactive SVG elements. For interactive series toggling or HTML layout below the chart, use `legend: { position: 'separate' }` and render HTML buttons from `chart.legendItems()` using `drawMarker()` and `SVGRenderer` or `resolveDash()`.
|
|
183
|
+
- **Hatch lines adapt to fill colour:** Hatch patterns inherit the opaque colour of the area they belong to (`opaqueColor(fill)`), while the backdrop stays translucent. An earlier default drew fixed blue lines (`#4D88FF`), which falsely signaled an extra state on incident charts where colour is semantic.
|
package/USAGE.md
CHANGED
|
@@ -107,7 +107,7 @@ Define named thresholds once and reference them from a series:
|
|
|
107
107
|
```ts
|
|
108
108
|
new MLTimeGraph({
|
|
109
109
|
thresholds: [
|
|
110
|
-
{ name: 'warn', value: 22, color: '#f59e0b' },
|
|
110
|
+
{ name: 'warn', value: 22, color: '#f59e0b', label: 'Warning' },
|
|
111
111
|
{ name: 'crit', value: 28, color: '#ef4444', fill: 'above', label: 'Critical' },
|
|
112
112
|
],
|
|
113
113
|
series: [
|
|
@@ -118,10 +118,37 @@ new MLTimeGraph({
|
|
|
118
118
|
|
|
119
119
|
- A threshold draws a `line: 'solid' | 'dashed' | 'dotted' | 'none'`, an optional
|
|
120
120
|
half-plane `fill: 'above' | 'below'`, and a `label`
|
|
121
|
-
(`
|
|
121
|
+
(`true | string | { text?, position? }`; position `left | right | above | below | center`).
|
|
122
|
+
- **A threshold is not labelled unless you ask for one** (since 1.5.0). `name` is an
|
|
123
|
+
identifier — it wires `colorByThresholds`, fill regions and CSS classes — so painting it
|
|
124
|
+
into the chart by default leaked internal names next to real captions, loudest on an
|
|
125
|
+
invisible anchor (`line: 'none'`). Pass `label: true` to get the name, a string or
|
|
126
|
+
`{ text }` for your own caption. `label: false` still works and now means the same as
|
|
127
|
+
leaving it out.
|
|
122
128
|
- `colorByThresholds: string[]` colours the line by zone — base colour below the
|
|
123
129
|
lowest threshold, then each threshold's colour for values above it.
|
|
124
130
|
|
|
131
|
+
### Data outside the axis range
|
|
132
|
+
|
|
133
|
+
A series is **clipped to the plot area** (`clipSeries`, default `true`). It only matters
|
|
134
|
+
once you fix the range yourself:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
new MLTimeGraph({
|
|
138
|
+
axes: { x: { domain: [windowFrom, windowTo] } }, // range is FIXED
|
|
139
|
+
series: [{ name: 'Temp', data }], // data reaches beyond it
|
|
140
|
+
// clipSeries: true — the default; the curve ends at the frame
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Handing over a reading from just outside the window is the normal way to make a curve *run
|
|
145
|
+
to the edge* instead of starting in mid-air — the last value before an incident is what
|
|
146
|
+
explains where it came from. Without clipping, line and markers paint over the axis labels.
|
|
147
|
+
|
|
148
|
+
Set `clipSeries: false` if a series should deliberately reach past the plot, or if the clip
|
|
149
|
+
costs you: every clipped group carries a `clip-path`, which a browser may render as its own
|
|
150
|
+
layer. With a handful of series that is nothing; with dozens, measure before you decide.
|
|
151
|
+
|
|
125
152
|
### Fill regions (the structured way)
|
|
126
153
|
|
|
127
154
|
The new `style.fill` model handles every shape of "fill area":
|
|
@@ -174,7 +201,67 @@ legend: {
|
|
|
174
201
|
```
|
|
175
202
|
|
|
176
203
|
`outside-*` reserves margin space (the plot shrinks). `'separate'` draws **no** legend
|
|
177
|
-
in the SVG — call `chart.legendItems()`
|
|
204
|
+
in the SVG — call `chart.legendItems()` and render your own.
|
|
205
|
+
|
|
206
|
+
### Drawing your own legend
|
|
207
|
+
|
|
208
|
+
The built-in legend sits left or right inside the SVG and does nothing when clicked.
|
|
209
|
+
Most applications want neither: a legend below the chart, in HTML, where a click hides
|
|
210
|
+
a series. That is what `'separate'` is for.
|
|
211
|
+
|
|
212
|
+
`legendItems()` returns what a swatch needs:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
interface LegendItem {
|
|
216
|
+
name: string;
|
|
217
|
+
color: string;
|
|
218
|
+
line?: LineVariant; // 'dashed', 'dotted', … — undefined if the series has several lines
|
|
219
|
+
marker?: Exclude<PointStyleType, 'none'>; // only when the chart actually draws markers
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Draw the swatch through the same renderer the chart uses, so it cannot drift from the
|
|
224
|
+
curve it names — a 22×10 line with the series' dashes and, if there is one, its marker:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import { drawMarker, SVGRenderer, type DrawCommand, type LegendItem } from 'ml-time-graph';
|
|
228
|
+
|
|
229
|
+
function swatch(item: LegendItem): string {
|
|
230
|
+
const commands: DrawCommand[] = [
|
|
231
|
+
{ type: 'line', x1: 1, y1: 5, x2: 21, y2: 5, stroke: item.color, strokeWidth: 2, dash: item.line },
|
|
232
|
+
];
|
|
233
|
+
if (item.marker) {
|
|
234
|
+
drawMarker(commands, undefined, item.marker, 11, 5, 3, item.color, item.color, 1.5);
|
|
235
|
+
}
|
|
236
|
+
return new SVGRenderer({ width: 22, height: 10 }).render(commands).content;
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
If you build the swatch in HTML or CSS instead of SVG, use **`resolveDash(variant, width)`**
|
|
241
|
+
— it returns `{ strokeDasharray, strokeLinecap? }`, or `null` for a solid line, and it is the
|
|
242
|
+
same function the renderer uses.
|
|
243
|
+
|
|
244
|
+
> Use `resolveDash`, not `getLineStyle`, for anything that has to match a drawn line.
|
|
245
|
+
> `dashed` and `dotted` predate the variant table and keep their historical patterns
|
|
246
|
+
> (`"4,4"` and `"2,4"`, not scaled by stroke width) so that existing charts did not change
|
|
247
|
+
> when the other variants arrived. `getLineStyle` is the table itself and answers `"6, 4"`
|
|
248
|
+
> for `dashed` — correct as a table, wrong as a description of the curve. The difference is
|
|
249
|
+
> nearly invisible and therefore worth knowing: a swatch dashed 6-on-4 beside a curve
|
|
250
|
+
> dashed 4-on-4.
|
|
251
|
+
|
|
252
|
+
**Why the swatch should not be a coloured block.** As long as series differ only by
|
|
253
|
+
colour, a block is enough. The moment they differ by line style or marker — which is
|
|
254
|
+
what you do when a chart is printed, or read by someone who cannot separate red from
|
|
255
|
+
green — a block says nothing: on a black-and-white page every block is the same grey,
|
|
256
|
+
and the legend is useless exactly where it is needed most, as part of a record.
|
|
257
|
+
|
|
258
|
+
For the same reason `marker` is absent when the chart does not draw one. A series with
|
|
259
|
+
`markers.threshold` hides its markers above that many samples; a symbol in the legend
|
|
260
|
+
that is missing from the curve is a false statement, and on paper nobody can check.
|
|
261
|
+
|
|
262
|
+
> `line` is undefined for a series drawn with **several** lines (`style.line` as an
|
|
263
|
+
> array): there is no single answer, and the first one presented as the truth would be
|
|
264
|
+
> a guess.
|
|
178
265
|
|
|
179
266
|
## Axes
|
|
180
267
|
|
|
@@ -470,7 +557,7 @@ renders the same JSON config to identical SVG.
|
|
|
470
557
|
|
|
471
558
|
| Import | Contents |
|
|
472
559
|
| :--- | :--- |
|
|
473
|
-
| `ml-time-graph` | The rendering API — `mount`, `MLTimeGraph`, `SVGRenderer`, `attachTooltip`, and all option/data types. |
|
|
560
|
+
| `ml-time-graph` | The rendering API — `mount`, `MLTimeGraph`, `SVGRenderer`, `attachTooltip`, the legend helpers `getLineStyle` / `drawMarker` / `getHatch`, and all option/data types. |
|
|
474
561
|
| `ml-time-graph/analyze` | Statistics companion — `aggregateBySlot`, `downsample`, `detectGaps`, `mkt` / `rollingMkt`, `stdDev`, `StatsAggregator`, … (see [Aggregation](#aggregation--helpers)). |
|
|
475
562
|
| `ml-time-graph/interaction` | Optional interaction primitives — `Zoom`, `Minimap`, `Tooltip` (lower-level than `attachTooltip`). |
|
|
476
563
|
| `ml-time-graph/internals` | Building blocks for **custom renderers** — the abstract `Renderer`, free render-functions, scales, axis classes, the `DrawCommand` model. |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LegendOrientation, R as Renderer, M as Marker, a as LegendItem, b as LayoutResult, c as RenderOutput } from './
|
|
2
|
-
export { T as Theme, g as getDefaultTheme, r as resetDefaultTheme, s as setDefaultTheme } from './
|
|
3
|
-
import { L as LineVariant, A as AnySeries, T as Threshold, H as Highlight, G as Gap, a as GapsConfig, b as Annotation, c as AnnotationBandConfig, D as DrawCommand, d as TimeScale, e as LinearScale, S as SeriesStyle, F as FillSpec, f as TimeSeries, g as HatchVariant, h as ThresholdLabelPosition, P as PointStyleType, i as AnnotationBandItem, j as AggregatedPoint, k as AggregatedSeries, l as DataPoint } from './scale-
|
|
4
|
-
export { m as AggregationConfig, n as AggregationMode, o as DataPointRef, E as EnumMap, p as FillBound, q as FillDirectionType, r as FillRegion, s as FillSide, t as FillStyle, u as GapConfig, v as GapLabel, w as GapRegion, x as GapStyle, y as LineDashStyle, z as LineStyle, M as MarkerStyle, B as
|
|
1
|
+
import { L as LegendOrientation, R as Renderer, M as Marker, a as LegendItem, b as LayoutResult, c as RenderOutput } from './series_renderer-BxGvCHMY.js';
|
|
2
|
+
export { T as Theme, d as drawMarker, g as getDefaultTheme, r as resetDefaultTheme, s as setDefaultTheme } from './series_renderer-BxGvCHMY.js';
|
|
3
|
+
import { L as LineVariant, A as AnySeries, T as Threshold, H as Highlight, G as Gap, a as GapsConfig, b as Annotation, c as AnnotationBandConfig, D as DrawCommand, d as TimeScale, e as LinearScale, S as SeriesStyle, F as FillSpec, f as TimeSeries, g as HatchVariant, h as ThresholdLabelPosition, P as PointStyleType, i as AnnotationBandItem, j as AggregatedPoint, k as AggregatedSeries, l as DataPoint } from './scale-ByGpczxS.js';
|
|
4
|
+
export { m as AggregationConfig, n as AggregationMode, o as DataPointRef, E as EnumMap, p as FillBound, q as FillDirectionType, r as FillRegion, s as FillSide, t as FillStyle, u as GapConfig, v as GapLabel, w as GapRegion, x as GapStyle, y as LineDashStyle, z as LineStyle, M as MarkerStyle, B as SVGLineStyle, C as SensorType, I as SeriesOverlay, J as SeriesOverlayKind, K as SeriesType, N as ShadowStyle, O as ThresholdLabelConfig, Q as getLineStyle, R as resolveDash } from './scale-ByGpczxS.js';
|
|
5
5
|
|
|
6
6
|
/*!
|
|
7
7
|
* MLTimeGraph — Copyright (c) 2026 Michael Lechner
|
|
@@ -128,6 +128,20 @@ interface MLTimeGraphOptions {
|
|
|
128
128
|
renderer?: Renderer;
|
|
129
129
|
/** Time series data (raw or aggregated min/max/avg) */
|
|
130
130
|
series?: AnySeries[];
|
|
131
|
+
/**
|
|
132
|
+
* Clip series drawing to the plot area (default `true`).
|
|
133
|
+
*
|
|
134
|
+
* It matters only when data lies outside the axis domain — which happens as soon as you
|
|
135
|
+
* fix `axes.x.domain` and hand over a reading from just outside the window, so the curve
|
|
136
|
+
* runs to the edge instead of starting in mid-air. Without clipping, line and markers
|
|
137
|
+
* paint over the axis labels.
|
|
138
|
+
*
|
|
139
|
+
* Turn it off if you deliberately want a series to reach beyond the plot, or if the
|
|
140
|
+
* clip costs you: every clipped group gets a `clip-path`, and a browser may promote each
|
|
141
|
+
* to its own layer. With a handful of series that is nothing; with dozens on a slow
|
|
142
|
+
* machine it can be worth measuring.
|
|
143
|
+
*/
|
|
144
|
+
clipSeries?: boolean;
|
|
131
145
|
/** Locale for i18n (e.g. 'de-DE') */
|
|
132
146
|
locale?: string;
|
|
133
147
|
/** Integrated legend configuration */
|
|
@@ -177,6 +191,8 @@ declare class MLTimeGraph {
|
|
|
177
191
|
private readonly _renderer?;
|
|
178
192
|
private readonly _locale?;
|
|
179
193
|
private readonly _legend?;
|
|
194
|
+
/** Serien auf die Zeichenflaeche beschneiden (Vorgabe: ja) — siehe options.ts. */
|
|
195
|
+
private readonly _clipSeries;
|
|
180
196
|
private readonly _markers;
|
|
181
197
|
private readonly _thresholds;
|
|
182
198
|
private readonly _highlights;
|
|
@@ -844,4 +860,4 @@ declare function parseSeries(obj: unknown): TimeSeries | DataPoint[];
|
|
|
844
860
|
/** Parse aggregated series (AggregatedPoint[] — min/max/avg per slot) */
|
|
845
861
|
declare function parseAggregated(obj: unknown): AggregatedSeries;
|
|
846
862
|
|
|
847
|
-
export { AggregatedPoint, AggregatedSeries, Annotation, AnnotationBandBuilder, AnnotationBandConfig, AnnotationBandItem, AnnotationBandItemBuilder, AnnotationBuilder, AnySeries, type AxesConfig, type AxisLabelsStyle, type AxisStyle, DataPoint, type FillBetweenThresholdsInput, FillSpec, Gap, GapsConfig, GraphBuilder, type GridLineStyle, type GridStyle, HatchVariant, Highlight, HighlightBuilder, type LegendOptions, type LegendPosition, type LimitStatsPoint, MLTimeGraph, type MLTimeGraphOptions, type Margin, Marker, MarkerBuilder, type MktPoint, PointStyleType, SVGRenderer, SeriesStyle, type StatsAggregatedPoint, type StdDevPoint, Threshold, ThresholdBuilder, ThresholdLabelPosition, type TickConfig, TimeSeries, TimeSeriesBuilder, type TooltipOptions, type TooltipSample, type XAxisConfig, type YAxisConfig, attachTooltip, fillBetweenThresholds, mount, parseAggregated, parseDataPoint, parseSeries };
|
|
863
|
+
export { AggregatedPoint, AggregatedSeries, Annotation, AnnotationBandBuilder, AnnotationBandConfig, AnnotationBandItem, AnnotationBandItemBuilder, AnnotationBuilder, AnySeries, type AxesConfig, type AxisLabelsStyle, type AxisStyle, DataPoint, DrawCommand, type FillBetweenThresholdsInput, FillSpec, Gap, GapsConfig, GraphBuilder, type GridLineStyle, type GridStyle, HatchVariant, Highlight, HighlightBuilder, LegendItem, type LegendOptions, LegendOrientation, type LegendPosition, type LimitStatsPoint, LineVariant, MLTimeGraph, type MLTimeGraphOptions, type Margin, Marker, MarkerBuilder, type MktPoint, PointStyleType, SVGRenderer, SeriesStyle, type StatsAggregatedPoint, type StdDevPoint, Threshold, ThresholdBuilder, ThresholdLabelPosition, type TickConfig, TimeSeries, TimeSeriesBuilder, type TooltipOptions, type TooltipSample, type XAxisConfig, type YAxisConfig, attachTooltip, fillBetweenThresholds, mount, parseAggregated, parseDataPoint, parseSeries };
|