inkplot-scratch 0.0.0-stage → 1.0.0-beta.1

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.
@@ -0,0 +1,141 @@
1
+ # inkplot topic: data sources and big data
2
+
3
+ For: a million points (decimation), data as columns or from a function, updating live data, reading a chart's data back as a table.
4
+
5
+ Read `SKILL.md` first (rules, template, and the attributes of `Chart`, `CartesianPlane`, `Axis`, `LinearScale`, `DomainSeries`, `FlatDataSource`, `ObjectDataSource`, `LinePath`, `LinearCurve`). This file has the rest of what this topic needs: examples, notes, and the attributes of its elements. Everything here is exported from `'inkplot'`.
6
+
7
+ ## Large data, and a live update
8
+
9
+
10
+ `Decimator` takes a **kernel first, then the source**, and goes where the source would. It cannot carry channels or sit on an `XYSeries`.
11
+
12
+ ```ts check title="A million points, then updates"
13
+ import {
14
+ Axis,
15
+ CartesianPlane,
16
+ Chart,
17
+ Decimator,
18
+ DomainSeries,
19
+ FlatDataSource,
20
+ LinePath,
21
+ LinearCurve,
22
+ LinearScale,
23
+ MinMaxKernel,
24
+ PanZoom,
25
+ lightTheme,
26
+ } from 'inkplot';
27
+
28
+ const values = new Float64Array(1_000_000);
29
+ for (let i = 0; i < values.length; i++) values[i] = Math.sin(i / 5000) + Math.sin(i / 37) * 0.1;
30
+ const source = new FlatDataSource({ data: values, regularDomain: { start: 0, step: 1 }, isSorted: true });
31
+
32
+ export const chart = new Chart(
33
+ { theme: lightTheme },
34
+ new CartesianPlane(
35
+ {},
36
+ new Axis({ orientation: 'bottom' }, new LinearScale()),
37
+ new Axis({ orientation: 'left' }, new LinearScale()),
38
+ new DomainSeries(
39
+ { name: 'Signal' },
40
+ new Decimator({}, new MinMaxKernel(), source),
41
+ new LinePath({}, new LinearCurve()),
42
+ ),
43
+ new PanZoom(),
44
+ ),
45
+ );
46
+
47
+ // New data: set the attribute. Edited in place: tell the source.
48
+
49
+ export function replace(next: Float64Array) {
50
+ source.setAttribute('data', next);
51
+ }
52
+
53
+ export function bump(i: number, v: number) {
54
+ values[i] = v;
55
+ source.invalidate();
56
+ }
57
+ ```
58
+
59
+ ## Notes
60
+
61
+ | To… | Use |
62
+ |---|---|
63
+ | Chart data as a table | `readTable(node)` (a source, transform, trendline or `series.data`): typed-array columns and `rows()` |
64
+
65
+ ## Attributes of this topic's elements
66
+
67
+ An attribute followed by `(required)` must be given. Every element also takes `id`, `meta`, `visible` and `style`.
68
+
69
+ <!-- api:start -->
70
+ ### CompositeDataSource
71
+
72
+ Separate columns.
73
+
74
+ **In** a series · **Holds** none
75
+
76
+ | Attribute | Type | |
77
+ |---|---|---|
78
+ | `count` (required) | `number` | |
79
+ | `domain` (required) | `Column` | Where each row is along the domain: for a made-up domain, `(i) => start + step * i`. |
80
+ | `value` (required) | `Column` | |
81
+ | `channels` | `Readonly<Record<Channel, Column>>` | Extra columns that bindings and tooltips can address by name. |
82
+ | `isSorted` | `boolean` | The stored points already ascend in the domain. Default false. |
83
+ | `wrap` | `number` | The domain repeats with this period, and the source delivers one more point: the first, again, one period on. |
84
+
85
+ ### SyntheticDataSource
86
+
87
+ A function sampled when drawn.
88
+
89
+ **In** a series · **Holds** none
90
+
91
+ | Attribute | Type | |
92
+ |---|---|---|
93
+ | `fn` (required) | `(x: number) => number` | Value at a domain position. |
94
+ | `domain` (required) | `Extent` | The span the function is defined over: the data's whole domain. |
95
+ | `count` | `number` | Number of samples, evenly spaced across the domain, always. |
96
+ | `isSorted` | `boolean` | The stored points already ascend in the domain. Default false. |
97
+ | `wrap` | `number` | The domain repeats with this period, and the source delivers one more point: the first, again, one period on. |
98
+
99
+ ### Decimator
100
+
101
+ Reduces large data to what the plot can show.
102
+
103
+ **In** a series · **Holds** 1 kernel, then 1 source
104
+
105
+ | Attribute | Type | |
106
+ |---|---|---|
107
+ | `resolution` | `number` | Pixel columns reduced to per pixel of plot width. Default 1; raise it for high-DPI output. |
108
+ | `enabled` | `boolean` | Turn it off without removing it. Default true. |
109
+
110
+ ### MinMaxKernel
111
+
112
+ Keeps the lowest and highest of each pixel column.
113
+
114
+ **In** Decimator · **Holds** none
115
+
116
+ No attributes of its own.
117
+
118
+ ### M4Kernel
119
+
120
+ First, last, lowest and highest of each column.
121
+
122
+ **In** Decimator · **Holds** none
123
+
124
+ No attributes of its own.
125
+
126
+ ### LttbKernel
127
+
128
+ Largest-triangle-three-buckets: keeps the shape.
129
+
130
+ **In** Decimator · **Holds** none
131
+
132
+ No attributes of its own.
133
+
134
+ ### StrideKernel
135
+
136
+ Every nth point.
137
+
138
+ **In** Decimator · **Holds** none
139
+
140
+ No attributes of its own.
141
+ <!-- api:end -->
@@ -0,0 +1,137 @@
1
+ # inkplot topic: title, legend, annotations, accessibility
2
+
3
+ For: a chart title or caption, a legend, reference lines and callouts, an accessible name and summary.
4
+
5
+ Read `SKILL.md` first (rules, template, and the attributes of `Chart`, `CartesianPlane`, `Axis`, `LinearScale`, `DomainSeries`, `FlatDataSource`, `ObjectDataSource`, `LinePath`, `LinearCurve`). This file has the rest of what this topic needs: examples, notes, and the attributes of its elements. Everything here is exported from `'inkplot'`.
6
+
7
+ ## Example
8
+
9
+ ```ts check title="Title, legend, reference line and callout"
10
+ import {
11
+ Axis,
12
+ CalloutAnnotation,
13
+ CartesianPlane,
14
+ Chart,
15
+ ChartTitle,
16
+ DomainSeries,
17
+ FlatDataSource,
18
+ Legend,
19
+ LineAnnotation,
20
+ LinePath,
21
+ LinearCurve,
22
+ LinearScale,
23
+ lightTheme,
24
+ } from 'inkplot';
25
+
26
+ const line = (name: string, data: number[]) =>
27
+ new DomainSeries(
28
+ { name: name },
29
+ new FlatDataSource({ data: data, regularDomain: { start: 1, step: 1 } }),
30
+ new LinePath({}, new LinearCurve()),
31
+ );
32
+
33
+ export const chart = new Chart(
34
+ {
35
+ theme: lightTheme,
36
+ meta: { title: 'Sales by month', description: 'Two years of monthly sales, 2024 above 2023.' },
37
+ },
38
+ new ChartTitle({ text: 'Monthly sales' }),
39
+ new ChartTitle({ text: 'Source: internal ledger', role: 'caption', side: 'bottom' }),
40
+ new CartesianPlane(
41
+ {},
42
+ new Axis({ orientation: 'bottom', title: 'Month' }, new LinearScale()),
43
+ new Axis({ orientation: 'left', title: 'Sales (k)' }, new LinearScale()),
44
+ line('2023', [12, 15, 14, 18, 22, 25]),
45
+ line('2024', [14, 18, 17, 21, 26, 30]),
46
+ new LineAnnotation({ value: 20, label: 'Target' }),
47
+ new CalloutAnnotation({ domain: 6, value: 30, text: 'Best month' }),
48
+ ),
49
+ new Legend({ side: 'bottom' }),
50
+ );
51
+ ```
52
+
53
+ `ChartTitle` and `Legend` are children of the **chart**; the annotations are children of the **plane**. `role: 'caption'` makes a smaller title; `side` puts it on another edge. Series appear in the legend by `name`; `toggle` lets a click hide one. `meta: { title }` and `meta: { description }` on the `Chart` are its accessible name and description; `new ChartSummary()` makes a spoken summary from the data.
54
+ ## Notes
55
+
56
+ - `Legend` and the keys: `side` is `'top'`, `'right'`, `'bottom'` or `'left'`; `orientation` is `'horizontal'` or `'vertical'`.
57
+
58
+ | To… | Use |
59
+ |---|---|
60
+ | Title / caption | `new ChartTitle({ text: '…' })`, `new ChartTitle({ text: '…', role: 'caption' })` |
61
+ | Accessible name | `meta: { title }`, `meta: { description }` on the `Chart`; `new ChartSummary()` for an automatic one |
62
+
63
+ ## Attributes of this topic's elements
64
+
65
+ An attribute followed by `(required)` must be given. Every element also takes `id`, `meta`, `visible` and `style`.
66
+
67
+ <!-- api:start -->
68
+ ### ChartTitle
69
+
70
+ Text across the top or bottom: a title, subtitle or caption.
71
+
72
+ **In** Chart · **Holds** none
73
+
74
+ | Attribute | Type | |
75
+ |---|---|---|
76
+ | `text` (required) | `string` | The words. |
77
+ | `role` | `TitleRole` | What it is, which decides its look and (unless `side` says) where it goes. Default 'title'. |
78
+ | `side` | `'top' \| 'bottom'` | The edge it spans. Default: the top, except for a caption, which goes at the bottom. |
79
+
80
+ ### Legend
81
+
82
+ Lists the named series; click to hide or show.
83
+
84
+ **In** Chart · **Holds** none
85
+
86
+ | Attribute | Type | |
87
+ |---|---|---|
88
+ | `side` | `Side` | The edge of the chart it sits along. Default 'right'. |
89
+ | `orientation` | `'vertical' \| 'horizontal'` | Entries in a column or a row. Default: along its side, so a column on the left and right, a row on the top and bottom. |
90
+ | `title` | `string` | A heading above the entries. |
91
+ | `toggle` | `boolean` | Clicking an entry hides or shows its series. Default true. |
92
+
93
+ ### ChartSummary
94
+
95
+ A spoken summary of the chart, for screen readers (English, replaceable).
96
+
97
+ **In** Chart · **Holds** none
98
+
99
+ | Attribute | Type | |
100
+ |---|---|---|
101
+ | `text` | `(facts: ChartFacts) => string` | Words the facts. Default: English sentences. |
102
+ | `roleDescription` | `string` | What the chart is, as a screen reader announces it. Default 'chart'. |
103
+
104
+ ### LineAnnotation
105
+
106
+ A reference line in data terms.
107
+
108
+ **In** a plane · **Holds** none
109
+
110
+ | Attribute | Type | |
111
+ |---|---|---|
112
+ | `value` | `number` | A horizontal line at this value (give one of `value`, `domain`, or `from` and `to`). |
113
+ | `domain` | `number` | A vertical line at this domain (give one of `value`, `domain`, or `from` and `to`). |
114
+ | `from` | `readonly [domain: number, value: number]` | One end of a diagonal line, as `[domain, value]` (with `to`). |
115
+ | `to` | `readonly [domain: number, value: number]` | The other end of a diagonal line, as `[domain, value]` (with `from`). |
116
+ | `domainAxis` | `ElementRef<Axis>` | Default: the plane's first axis, as for a series. |
117
+ | `valueAxis` | `ElementRef<Axis>` | Default: the plane's second axis. |
118
+ | `label` | `string` | Text beside the line. |
119
+ | `stroke` | `string` | Line colour: the same as `style: { annotationLine: { color } }`, set directly. |
120
+ | `strokeWidth` | `number` | Line width in pixels: the same as `style: { annotationLine: { width } }`, set directly. |
121
+
122
+ ### CalloutAnnotation
123
+
124
+ A note attached to a data point.
125
+
126
+ **In** a plane · **Holds** none
127
+
128
+ | Attribute | Type | |
129
+ |---|---|---|
130
+ | `domainAxis` | `ElementRef<Axis>` | Default: the plane's first axis. |
131
+ | `valueAxis` | `ElementRef<Axis>` | Default: the plane's second axis. |
132
+ | `domain` (required) | `number` | The point being called out, in data space. |
133
+ | `value` (required) | `number` | The value of the point being called out. |
134
+ | `text` (required) | `string` | What it says. |
135
+ | `dx` | `number` | Where the middle of the box is, in pixels from the point. |
136
+ | `dy` | `number` | Pixels down from the point to the text box (negative is up). |
137
+ <!-- api:end -->
@@ -0,0 +1,169 @@
1
+ # inkplot topic: interaction
2
+
3
+ For: tooltips, a crosshair, pan and zoom, drag-to-zoom, brushing a range, clicks and hovers, touch.
4
+
5
+ Read `SKILL.md` first (rules, template, and the attributes of `Chart`, `CartesianPlane`, `Axis`, `LinearScale`, `DomainSeries`, `FlatDataSource`, `ObjectDataSource`, `LinePath`, `LinearCurve`). This file has the rest of what this topic needs: examples, notes, and the attributes of its elements. Everything here is exported from `'inkplot'`.
6
+
7
+ ## Tooltip, crosshair, pan and zoom, reference line
8
+
9
+
10
+ `Cursor` is a child of the **chart**; `PanZoom` and annotations are children of the **plane**.
11
+
12
+ ```ts check title="Interactive"
13
+ import {
14
+ Axis,
15
+ CartesianPlane,
16
+ Chart,
17
+ ChartTooltip,
18
+ Crosshair,
19
+ Cursor,
20
+ DomainSeries,
21
+ FlatDataSource,
22
+ LineAnnotation,
23
+ LinePath,
24
+ LinearCurve,
25
+ LinearScale,
26
+ PanZoom,
27
+ lightTheme,
28
+ } from 'inkplot';
29
+
30
+ export const chart = new Chart(
31
+ { theme: lightTheme },
32
+ new CartesianPlane(
33
+ { meta: { title: 'Latency' } },
34
+ new Axis({ orientation: 'bottom' }, new LinearScale()),
35
+ new Axis({ orientation: 'left', title: 'ms' }, new LinearScale()),
36
+ new DomainSeries(
37
+ { name: 'p95', hit: 'line' },
38
+ new FlatDataSource({ data: [120, 135, 128, 160, 142, 150, 138], regularDomain: { start: 0, step: 1 } }),
39
+ new LinePath({}, new LinearCurve()),
40
+ ),
41
+ new LineAnnotation({ value: 150, label: 'Target', stroke: '#c0392b' }),
42
+ new PanZoom(),
43
+ ),
44
+ new Cursor({ mode: 'shared' }, new Crosshair(), new ChartTooltip()),
45
+ );
46
+ ```
47
+
48
+ ## Notes
49
+
50
+ - A tooltip's `format` gets a `Hit`: `hit.series` (its `attrs.name`), `hit.first` and `hit.second` (the point's two coordinates in data terms: for a line chart the domain, e.g. a date in milliseconds, and the value), `hit.index`, `hit.channels` (bound channels by name). Hover is live in a browser only; `toSvgString` draws no tooltip, so test the text by calling your `format` on a sample.
51
+
52
+ | To… | Use |
53
+ |---|---|
54
+ | Click a point | `new PointerListener({ onClick: (info) => info.hit && … })` in the plane (before `PanZoom`) |
55
+ | Select a range and report it (no zoom) | `new Brush({ mode: 'x', onBrush: ... })` before `new PanZoom()`; `brush.select()` / `clear()` from code |
56
+ | Zoom to a dragged box | `new BoxZoom({ mode: 'auto' })` in the plane, **before** `new PanZoom()` (Shift-drag; `activate: 'always'` for every drag) |
57
+ | Reset zoom (button) | `chart.resetViews()`; know when it is zoomed with `onViewChange` on an `Axis` |
58
+ | Touch | Default: one finger scrolls the page, two pinch the chart; `new PanZoom({ touch: 'always' })` for one-finger pan |
59
+ | Tooltip text | ``new ChartTooltip({ format: (hit) => `${hit.series.attrs.name}: ${hit.second}` })`` |
60
+
61
+ ## Attributes of this topic's elements
62
+
63
+ An attribute followed by `(required)` must be given. Every element also takes `id`, `meta`, `visible` and `style`.
64
+
65
+ <!-- api:start -->
66
+ ### ChartTooltip
67
+
68
+ A box of text at the cursor.
69
+
70
+ **In** Cursor · **Holds** none
71
+
72
+ | Attribute | Type | |
73
+ |---|---|---|
74
+ | `follow` | `boolean` | Whether the box moves with the cursor, with no arm, or is set beside what is read, with an arm to it. Default: moves with the cursor when the cursor is 'shared' (there is no one point to be beside), else set beside the point. |
75
+ | `swatch` | `boolean` | A sample of the series (its line, box or marker, as drawn on the plot) before its name, or without one before its first line. Default false. |
76
+ | `format` | `(hit: Hit) => string` | The text for one hit. Default: the series name, then each coordinate (with its axis' title if it has one) and the channels. |
77
+ | `announce` | `boolean` | Tell a screen reader what the box says when the cursor is moved by keyboard (see `Platform.announce`), so it can be read without seeing it. Default true. |
78
+
79
+ ### Cursor
80
+
81
+ Finds what the pointer or keyboard is on; its children draw it.
82
+
83
+ **In** Chart · **Holds** Crosshair, ChartTooltip
84
+
85
+ | Attribute | Type | |
86
+ |---|---|---|
87
+ | `mode` | `'nearest' \| 'shared'` | What it finds: the 'nearest' point, or every series 'shared' at its place along the first axis. Default 'nearest'. |
88
+ | `interpolate` | `boolean` | Read the line between its two points at the cursor instead of reporting a point. Default false. |
89
+ | `plane` | `ElementRef<Plane>` | The plane it works in. Default: the plane the pointer is over, and the first plane for the keyboard. |
90
+ | `keys` | `CursorKeys \| false` | Keys for moving it from the keyboard, or `false` for none (and no tab stop). |
91
+
92
+ ### Crosshair
93
+
94
+ Guide lines through the cursor.
95
+
96
+ **In** Cursor · **Holds** none
97
+
98
+ | Attribute | Type | |
99
+ |---|---|---|
100
+ | `lines` | `'first' \| 'second' \| 'both'` | Which guide: the line of constant first coordinate (across a line chart: vertical), of the second, or both. Default 'both'. |
101
+ | `dots` | `boolean` | A dot in the series' colour on each reading under the cursor. Default false. |
102
+ | `dotSize` | `number` | Radius of those dots, in pixels. Default 4. |
103
+ | `snap` | `boolean` | Put the lines through the first reading (a point) rather than through the cursor itself. Default false. |
104
+
105
+ ### PanZoom
106
+
107
+ Drag, wheel, pinch, touch and keys change the view.
108
+
109
+ **In** a plane · **Holds** none
110
+
111
+ | Attribute | Type | |
112
+ |---|---|---|
113
+ | `axes` | `readonly ElementRef<Axis>[]` | The axes it may move, as elements or ids. Default: all of the plane's that can be dragged along: not the rim of a polar or radar plane. |
114
+ | `direction` | `'both' \| 'horizontal' \| 'vertical'` | Which way things may move. Default 'both'. |
115
+ | `pan` | `boolean` | Drag with the primary button to pan. Default true. |
116
+ | `zoom` | `boolean` | Turn the wheel to zoom about the pointer. Default true. |
117
+ | `limit` | `boolean` | Keep the view inside the natural range of each axis, so there is no panning off the data or zooming out past it. Default true. |
118
+ | `zoomSpeed` | `number` | Zoom per wheel pixel, as a natural-log factor. Default 0.002, which is about 20% for one notch of a typical wheel. |
119
+ | `axisZoom` | `boolean` | With the pointer (or both fingers) over an axis, a wheel turn, a pinch or a drag moves that axis alone. Default true. |
120
+ | `pinchSpeed` | `number` | Zoom per pixel of a pinch on a trackpad, which browsers report as small wheel turns with Ctrl held. Default 0.02, ten times the wheel's step per pixel. |
121
+ | `touch` | `'two-finger' \| 'always'` | What a touch does. 'two-finger' (the default): one finger scrolls the page as usual, and two pinch and pan the chart. 'always': one finger pans the chart too, and the page cannot be scrolled from it. |
122
+ | `inertia` | `boolean` | A finger that lets go while still moving carries the view on, slowing to a stop (a flick). Default true. |
123
+ | `resetOnDoubleClick` | `boolean` | Two quick presses put every axis back to its natural range. Default true. |
124
+ | `keys` | `PanZoomKeys \| false` | The keys, once the plot has keyboard focus. |
125
+ | `keyStep` | `number` | How far an arrow moves the view, as a fraction of it. Default 0.1. |
126
+ | `keyZoom` | `number` | The factor of one press of a zoom key. Default 1.25. |
127
+
128
+ ### BoxZoom
129
+
130
+ Drag a box (Shift by default) to zoom to it. Before PanZoom.
131
+
132
+ **In** a plane · **Holds** none
133
+
134
+ | Attribute | Type | |
135
+ |---|---|---|
136
+ | `axes` | `readonly ElementRef<Axis>[]` | The axes it may zoom, as elements or ids. Default: all of the plane's that can be followed along (not the rim of a polar plane). |
137
+ | `activate` | `'shift' \| 'always'` | When a drag makes a box: with Shift held (the default), so a plain drag can pan, or always. |
138
+ | `mode` | `'xy' \| 'x' \| 'y' \| 'auto'` | Which axes the box zooms. Default 'xy'. |
139
+ | `minSize` | `number` | Smallest side of a box, in pixels, along an axis it zooms; below that the box does nothing. Default 8. |
140
+ | `onZoom` | `(box: { x: number; y: number; width: number; height: …` | Called after a zoom, with the box in plot pixels. |
141
+
142
+ ### Brush
143
+
144
+ Drag a range to select it and report it with onBrush; the selection stays drawn. Before PanZoom.
145
+
146
+ **In** a plane · **Holds** none
147
+
148
+ | Attribute | Type | |
149
+ |---|---|---|
150
+ | `axes` | `readonly ElementRef<Axis>[]` | The axes it may cover, as elements or ids. Default: all of the plane's that can be followed along. |
151
+ | `activate` | `'shift' \| 'always'` | When a drag brushes: always (the default) or with Shift held, to leave a plain drag to `PanZoom`. |
152
+ | `mode` | `'xy' \| 'x' \| 'y'` | Which axes it covers. Default 'xy'. |
153
+ | `minSize` | `number` | Smallest side of a brush, in pixels, along an axis it covers; below that a drag only clears. Default 4. |
154
+ | `live` | `boolean` | Call `onBrush` while dragging too. Default false. |
155
+ | `onBrush` | `(selection: BrushSelection \| null) => void` | Called with the selection, or null when it is cleared. |
156
+
157
+ ### PointerListener
158
+
159
+ Calls your functions on hover, click and drag.
160
+
161
+ **In** a plane · **Holds** none
162
+
163
+ | Attribute | Type | |
164
+ |---|---|---|
165
+ | `onHover` | `(info: PointerInfo) => void` | The pointer came onto a point, left it, or moved to another: `info.hit` is the new one, null for none. |
166
+ | `onClick` | `(info: PointerInfo) => void` | A press and release in the same place: on a point, or `info.hit` null on empty plot. |
167
+ | `onDrag` | `(info: DragInfo) => void` | A drag that began on a point. |
168
+ | `dragThreshold` | `number` | How far in pixels the pointer must travel before a press is a drag and no longer a click. Default 3. |
169
+ <!-- api:end -->
@@ -0,0 +1,201 @@
1
+ # inkplot topic: lines, areas and bars
2
+
3
+ For: bars (grouped, stacked), areas, smooth and stepped lines, curves, gaps in the data, several series sharing a plane.
4
+
5
+ Read `SKILL.md` first (rules, template, and the attributes of `Chart`, `CartesianPlane`, `Axis`, `LinearScale`, `DomainSeries`, `FlatDataSource`, `ObjectDataSource`, `LinePath`, `LinearCurve`). This file has the rest of what this topic needs: examples, notes, and the attributes of its elements. Everything here is exported from `'inkplot'`.
6
+
7
+ ## Bars on categories
8
+
9
+
10
+ ```ts check title="Bars"
11
+ import {
12
+ Axis,
13
+ BandScale,
14
+ BarPath,
15
+ CartesianPlane,
16
+ Chart,
17
+ DomainSeries,
18
+ FlatDataSource,
19
+ LinearScale,
20
+ lightTheme,
21
+ } from 'inkplot';
22
+
23
+ export const chart = new Chart(
24
+ { theme: lightTheme },
25
+ new CartesianPlane(
26
+ {},
27
+ new Axis({ orientation: 'bottom' }, new BandScale({ categories: ['Q1', 'Q2', 'Q3', 'Q4'] })),
28
+ new Axis({ orientation: 'left', title: 'Revenue' }, new LinearScale()),
29
+ new DomainSeries(
30
+ { name: '2024' },
31
+ new FlatDataSource({ data: [42, 58, 51, 73], regularDomain: { start: 0, step: 1 } }),
32
+ new BarPath(),
33
+ ),
34
+ ),
35
+ );
36
+ ```
37
+
38
+ Stacked or side by side: wrap several `DomainSeries` in `new Stack({ mode: 'stack' }, …)` (or `"group"`), add `new Legend({ side: 'bottom' })` to the `Chart`.
39
+
40
+ ## Notes
41
+
42
+ - `Stack` `mode`: `'stack'`, `'group'`, `'normalize'`, `'center'`.
43
+ - `BarPath` bars start at `baseline` (default 0, and the axis includes it); the tallest bar touches the top of the plot, so add `padding: 0.05` (a fraction of the span) to the value `Axis` for headroom.
44
+ - Curves: `LinearCurve`, `MonotoneCurve`, `StepCurve`, `NaturalCurve`, `CardinalCurve`, `CatmullRomCurve`, `BasisCurve`, `BumpCurve`, `QuadraticCurve`, `ArcCurve`.
45
+ - `hit` on a series: `'point'`, `'line'`, `'area'`, `'shape'` or `false`. `gaps`: `'break'` (default), `'connect'`, `'zero'`.
46
+
47
+ | To… | Use |
48
+ |---|---|
49
+ | Smooth lines | `new LinePath({}, new MonotoneCurve())`; steps: `new StepCurve({ mode: 'after' })` |
50
+ | Series gaps | `NaN` values are gaps; `gaps: 'connect'` on the series to cross them |
51
+ | Hide a series | `series.setAttribute('visible', false)` |
52
+
53
+ ## Attributes of this topic's elements
54
+
55
+ An attribute followed by `(required)` must be given. Every element also takes `id`, `meta`, `visible` and `style`.
56
+
57
+ <!-- api:start -->
58
+ ### Stack
59
+
60
+ Series that share axes and are laid on each other or side by side.
61
+
62
+ **In** a plane · **Holds** DomainSeries, any number
63
+
64
+ | Attribute | Type | |
65
+ |---|---|---|
66
+ | `mode` | `StackMode` | How the members' values are laid out. Default 'stack'. |
67
+ | `align` | `StackAlign` | How rows are matched up when the members' domains differ. Default 'strict': they must not. |
68
+
69
+ ### AreaPath
70
+
71
+ The region between a line and a baseline.
72
+
73
+ **In** a series · **Holds** 1 curve (required)
74
+
75
+ | Attribute | Type | |
76
+ |---|---|---|
77
+ | `baseline` | `number` | The value the area is filled from, kept inside the value axis' range. Default 0. |
78
+ | `stroke` | `string` | Outline colour (a CSS colour). Default: from the theme. |
79
+ | `strokeWidth` | `number` | Outline width in pixels. Default: from the theme. |
80
+ | `fill` | `string` | Fill colour (a CSS colour; 'none' for no fill). Default: from the theme. |
81
+ | `opacity` | `number` | Opacity from 0 to 1. Default 1. |
82
+ | `bind` | `Bindings<Bindable>` | Attributes fed from data instead of fixed. |
83
+ | `maxNodes` | `number` | Most paths this renderer may create. Default 1000. |
84
+
85
+ ### MonotoneCurve
86
+
87
+ A smooth curve that never overshoots.
88
+
89
+ **In** LinePath or AreaPath · **Holds** none
90
+
91
+ No attributes of its own.
92
+
93
+ ### NaturalCurve
94
+
95
+ A natural cubic spline.
96
+
97
+ **In** LinePath or AreaPath · **Holds** none
98
+
99
+ No attributes of its own.
100
+
101
+ ### CardinalCurve
102
+
103
+ A cardinal spline.
104
+
105
+ **In** LinePath or AreaPath · **Holds** none
106
+
107
+ | Attribute | Type | |
108
+ |---|---|---|
109
+ | `tension` | `number` | How far the curve is tightened towards straight lines, 0 (the Catmull-Rom spline) to 1. Default 0. |
110
+
111
+ ### CatmullRomCurve
112
+
113
+ A Catmull-Rom spline.
114
+
115
+ **In** LinePath or AreaPath · **Holds** none
116
+
117
+ | Attribute | Type | |
118
+ |---|---|---|
119
+ | `alpha` | `number` | The spacing of the knots: 0 even, 0.5 centripetal, 1 chordal. Default 0.5. |
120
+
121
+ ### BasisCurve
122
+
123
+ A B-spline that smooths past the points.
124
+
125
+ **In** LinePath or AreaPath · **Holds** none
126
+
127
+ No attributes of its own.
128
+
129
+ ### BumpCurve
130
+
131
+ S-shaped joins.
132
+
133
+ **In** LinePath or AreaPath · **Holds** none
134
+
135
+ | Attribute | Type | |
136
+ |---|---|---|
137
+ | `along` | `'x' \| 'y'` | Whether the level ends are along x (a line level at each point) or y. Default: along the series' first axis. |
138
+
139
+ ### QuadraticCurve
140
+
141
+ Quadratic joins.
142
+
143
+ **In** LinePath or AreaPath · **Holds** none
144
+
145
+ No attributes of its own.
146
+
147
+ ### ArcCurve
148
+
149
+ Circular arcs.
150
+
151
+ **In** LinePath or AreaPath · **Holds** none
152
+
153
+ | Attribute | Type | |
154
+ |---|---|---|
155
+ | `bend` | `number` | The rise of each arc as a fraction of its chord, positive bulging to the left of the way along. Default 0.3. |
156
+
157
+ ### StepCurve
158
+
159
+ Levels and jumps.
160
+
161
+ **In** LinePath or AreaPath · **Holds** none
162
+
163
+ | Attribute | Type | |
164
+ |---|---|---|
165
+ | `mode` | `StepMode` | Where the value changes between one point and the next. Default 'after'. |
166
+
167
+ ### BarPath
168
+
169
+ Bars, in one path.
170
+
171
+ **In** a series · **Holds** none
172
+
173
+ | Attribute | Type | |
174
+ |---|---|---|
175
+ | `stroke` | `string` | Outline colour (a CSS colour). Default: from the theme. |
176
+ | `strokeWidth` | `number` | Outline width in pixels. Default: from the theme. |
177
+ | `fill` | `string` | Fill colour (a CSS colour; 'none' for no fill). Default: from the theme. |
178
+ | `opacity` | `number` | Opacity from 0 to 1. Default 1. |
179
+ | `bind` | `Bindings<Bindable>` | Attributes fed from data instead of fixed. |
180
+ | `maxNodes` | `number` | Most paths this renderer may create. Default 1000. |
181
+ | `width` | `number` | Fraction of the room each bar fills. Default: a band's own `bandwidth`, else 0.8. |
182
+ | `baseline` | `number` | The value bars grow from when there is no stack to say. Default 0. |
183
+
184
+ ### BarLinePath
185
+
186
+ Bars drawn as stems.
187
+
188
+ **In** a series · **Holds** none
189
+
190
+ | Attribute | Type | |
191
+ |---|---|---|
192
+ | `cap` | `'butt' \| 'round' \| 'square'` | How the end of a stem is finished: 'butt' (flat, at the value), 'round' or 'square' (both reach half a width past). Default 'butt'. |
193
+ | `stroke` | `string` | Outline colour (a CSS colour). Default: from the theme. |
194
+ | `strokeWidth` | `number` | Outline width in pixels. Default: from the theme. |
195
+ | `fill` | `string` | Fill colour (a CSS colour; 'none' for no fill). Default: from the theme. |
196
+ | `opacity` | `number` | Opacity from 0 to 1. Default 1. |
197
+ | `bind` | `Bindings<Bindable>` | Attributes fed from data instead of fixed. |
198
+ | `maxNodes` | `number` | Most paths this renderer may create. Default 1000. |
199
+ | `width` | `number` | Fraction of the room each bar fills. Default: a band's own `bandwidth`, else 0.8. |
200
+ | `baseline` | `number` | The value bars grow from when there is no stack to say. Default 0. |
201
+ <!-- api:end -->