inkplot 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.
- package/LICENSE +21 -0
- package/README.md +46 -2
- package/dist/adapt.d.ts +10 -0
- package/dist/adapt.js +34 -0
- package/dist/annotation.d.ts +120 -0
- package/dist/annotation.js +267 -0
- package/dist/aria.d.ts +24 -0
- package/dist/aria.js +31 -0
- package/dist/attrs.d.ts +81 -0
- package/dist/attrs.js +84 -0
- package/dist/axis.d.ts +137 -0
- package/dist/axis.js +185 -0
- package/dist/bars.d.ts +80 -0
- package/dist/bars.js +255 -0
- package/dist/boxplot.d.ts +57 -0
- package/dist/boxplot.js +177 -0
- package/dist/boxzoom.d.ts +39 -0
- package/dist/boxzoom.js +138 -0
- package/dist/brush.d.ts +60 -0
- package/dist/brush.js +185 -0
- package/dist/bucket.d.ts +22 -0
- package/dist/bucket.js +62 -0
- package/dist/callout.d.ts +30 -0
- package/dist/callout.js +98 -0
- package/dist/chart.d.ts +126 -0
- package/dist/chart.js +257 -0
- package/dist/crosshair.d.ts +28 -0
- package/dist/crosshair.js +78 -0
- package/dist/cursor.d.ts +76 -0
- package/dist/cursor.js +344 -0
- package/dist/curve.d.ts +50 -0
- package/dist/curve.js +87 -0
- package/dist/curves.d.ts +104 -0
- package/dist/curves.js +375 -0
- package/dist/data.d.ts +209 -0
- package/dist/data.js +276 -0
- package/dist/decimation.d.ts +86 -0
- package/dist/decimation.js +410 -0
- package/dist/density.d.ts +55 -0
- package/dist/density.js +252 -0
- package/dist/dimension.d.ts +103 -0
- package/dist/dimension.js +205 -0
- package/dist/dom-platform.d.ts +53 -0
- package/dist/dom-platform.js +190 -0
- package/dist/element.d.ts +232 -0
- package/dist/element.js +414 -0
- package/dist/errors.d.ts +85 -0
- package/dist/errors.js +237 -0
- package/dist/events.d.ts +144 -0
- package/dist/events.js +19 -0
- package/dist/focus.d.ts +22 -0
- package/dist/focus.js +51 -0
- package/dist/furniture.d.ts +70 -0
- package/dist/furniture.js +166 -0
- package/dist/geometry.d.ts +40 -0
- package/dist/geometry.js +7 -0
- package/dist/heatmap.d.ts +57 -0
- package/dist/heatmap.js +207 -0
- package/dist/hit.d.ts +103 -0
- package/dist/hit.js +428 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +73 -0
- package/dist/input.d.ts +42 -0
- package/dist/input.js +166 -0
- package/dist/jsx-dev-runtime.d.ts +9 -0
- package/dist/jsx-dev-runtime.js +13 -0
- package/dist/jsx-runtime.d.ts +59 -0
- package/dist/jsx-runtime.js +81 -0
- package/dist/key.d.ts +118 -0
- package/dist/key.js +199 -0
- package/dist/legend.d.ts +36 -0
- package/dist/legend.js +220 -0
- package/dist/mapped.d.ts +80 -0
- package/dist/mapped.js +106 -0
- package/dist/marker.d.ts +143 -0
- package/dist/marker.js +213 -0
- package/dist/panzoom.d.ts +119 -0
- package/dist/panzoom.js +467 -0
- package/dist/plane.d.ts +173 -0
- package/dist/plane.js +370 -0
- package/dist/platform.d.ts +113 -0
- package/dist/platform.js +80 -0
- package/dist/png.d.ts +44 -0
- package/dist/png.js +71 -0
- package/dist/pointer.d.ts +54 -0
- package/dist/pointer.js +132 -0
- package/dist/quantile.d.ts +3 -0
- package/dist/quantile.js +11 -0
- package/dist/radial.d.ts +116 -0
- package/dist/radial.js +336 -0
- package/dist/react.d.ts +441 -0
- package/dist/react.js +252 -0
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +51 -0
- package/dist/renderer.d.ts +191 -0
- package/dist/renderer.js +164 -0
- package/dist/scale.d.ts +37 -0
- package/dist/scale.js +19 -0
- package/dist/scales.d.ts +69 -0
- package/dist/scales.js +134 -0
- package/dist/serialize.d.ts +77 -0
- package/dist/serialize.js +321 -0
- package/dist/series.d.ts +304 -0
- package/dist/series.js +513 -0
- package/dist/simple.d.ts +35 -0
- package/dist/simple.js +20 -0
- package/dist/sources.d.ts +116 -0
- package/dist/sources.js +237 -0
- package/dist/stack.d.ts +61 -0
- package/dist/stack.js +172 -0
- package/dist/stats.d.ts +38 -0
- package/dist/stats.js +159 -0
- package/dist/steps.d.ts +50 -0
- package/dist/steps.js +154 -0
- package/dist/stub.d.ts +3 -0
- package/dist/stub.js +5 -0
- package/dist/style-names.d.ts +1 -0
- package/dist/style-names.js +6 -0
- package/dist/summary.d.ts +44 -0
- package/dist/summary.js +58 -0
- package/dist/surface.d.ts +94 -0
- package/dist/surface.js +145 -0
- package/dist/table.d.ts +39 -0
- package/dist/table.js +37 -0
- package/dist/text.d.ts +23 -0
- package/dist/text.js +44 -0
- package/dist/theme.d.ts +174 -0
- package/dist/theme.js +73 -0
- package/dist/themes.d.ts +9 -0
- package/dist/themes.js +56 -0
- package/dist/time-intl.d.ts +194 -0
- package/dist/time-intl.js +144 -0
- package/dist/time-temporal.d.ts +236 -0
- package/dist/time-temporal.js +58 -0
- package/dist/time.d.ts +216 -0
- package/dist/time.js +154 -0
- package/dist/trend.d.ts +151 -0
- package/dist/trend.js +500 -0
- package/dist/web-components.d.ts +62 -0
- package/dist/web-components.js +264 -0
- package/package.json +53 -3
package/dist/hit.js
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
const DEFAULT_RADIUS = 10;
|
|
2
|
+
/** The least a series' hit radius is while the last input was a finger: a fingertip is not a mouse pointer. */
|
|
3
|
+
const COARSE_RADIUS = 24;
|
|
4
|
+
/** Distance from (x, y) to a point, with a NaN coordinate of the pointer leaving that direction out. */
|
|
5
|
+
function between(px, py, x, y) {
|
|
6
|
+
const dx = x !== x ? 0 : px - x, dy = y !== y ? 0 : py - y;
|
|
7
|
+
return Math.hypot(dx, dy);
|
|
8
|
+
}
|
|
9
|
+
/** The nearest drawn point; points that are gaps (NaN) are skipped. Null when there is none, or both coordinates are NaN. */
|
|
10
|
+
export function nearestPoint(points, x, y) {
|
|
11
|
+
if (x !== x && y !== y)
|
|
12
|
+
return null;
|
|
13
|
+
const { data, count, stride } = points;
|
|
14
|
+
let best = -1, bestD = Infinity;
|
|
15
|
+
for (let i = 0, k = 0; k < count; k++, i += stride) {
|
|
16
|
+
const px = data[i], py = data[i + 1];
|
|
17
|
+
if (px !== px || py !== py)
|
|
18
|
+
continue;
|
|
19
|
+
const d = between(px, py, x, y);
|
|
20
|
+
if (d < bestD) {
|
|
21
|
+
bestD = d;
|
|
22
|
+
best = k;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return best < 0 ? null : { index: best, distance: bestD };
|
|
26
|
+
}
|
|
27
|
+
/** The distance to the nearest point of the polyline through the points (a gap breaks it), and the nearer end of that segment. */
|
|
28
|
+
export function nearestSegment(points, x, y) {
|
|
29
|
+
if (x !== x || y !== y)
|
|
30
|
+
return nearestPoint(points, x, y);
|
|
31
|
+
const { data, count, stride } = points;
|
|
32
|
+
let best = -1, bestD = Infinity;
|
|
33
|
+
for (let k = 0, i = 0; k < count; k++, i += stride) {
|
|
34
|
+
const ax = data[i], ay = data[i + 1];
|
|
35
|
+
if (ax !== ax || ay !== ay)
|
|
36
|
+
continue;
|
|
37
|
+
// A point on its own (or the end of a run) is still something to hit.
|
|
38
|
+
const own = Math.hypot(ax - x, ay - y);
|
|
39
|
+
if (own < bestD) {
|
|
40
|
+
bestD = own;
|
|
41
|
+
best = k;
|
|
42
|
+
}
|
|
43
|
+
if (k + 1 >= count)
|
|
44
|
+
continue;
|
|
45
|
+
const bx = data[i + stride], by = data[i + stride + 1];
|
|
46
|
+
if (bx !== bx || by !== by)
|
|
47
|
+
continue;
|
|
48
|
+
const sx = bx - ax, sy = by - ay, len2 = sx * sx + sy * sy;
|
|
49
|
+
const t = len2 > 0 ? Math.max(0, Math.min(1, ((x - ax) * sx + (y - ay) * sy) / len2)) : 0;
|
|
50
|
+
const d = Math.hypot(ax + t * sx - x, ay + t * sy - y);
|
|
51
|
+
if (d < bestD) {
|
|
52
|
+
bestD = d;
|
|
53
|
+
best = t < 0.5 ? k : k + 1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return best < 0 ? null : { index: best, distance: bestD };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Whether (x, y) is inside the shape that a run of points makes with its baseline (the same points, placed against the
|
|
60
|
+
* baseline value, which `base` holds one row each for). Runs are the stretches between gaps, each its own shape. The
|
|
61
|
+
* nearest point of that run is returned when it is, else null.
|
|
62
|
+
*/
|
|
63
|
+
export function insideArea(points, base, x, y) {
|
|
64
|
+
if (x !== x || y !== y)
|
|
65
|
+
return null;
|
|
66
|
+
const { data, count, stride } = points, b = base.data, bs = base.stride;
|
|
67
|
+
const valid = (k) => data[k * stride] === data[k * stride] && data[k * stride + 1] === data[k * stride + 1] && b[k * bs + 1] === b[k * bs + 1];
|
|
68
|
+
for (let from = 0; from < count;) {
|
|
69
|
+
if (!valid(from)) {
|
|
70
|
+
from++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
let to = from;
|
|
74
|
+
while (to + 1 < count && valid(to + 1))
|
|
75
|
+
to++;
|
|
76
|
+
// Even-odd ray casting over the run forward and its baseline back.
|
|
77
|
+
const n = to - from + 1;
|
|
78
|
+
const vx = (j) => (j < n ? data[(from + j) * stride] : b[(to - (j - n)) * bs]);
|
|
79
|
+
const vy = (j) => (j < n ? data[(from + j) * stride + 1] : b[(to - (j - n)) * bs + 1]);
|
|
80
|
+
let inside = false;
|
|
81
|
+
for (let j = 0, prev = 2 * n - 1; j < 2 * n; prev = j++) {
|
|
82
|
+
const yj = vy(j), yp = vy(prev), xj = vx(j), xp = vx(prev);
|
|
83
|
+
if ((yj > y) !== (yp > y) && x < ((xp - xj) * (y - yj)) / (yp - yj) + xj)
|
|
84
|
+
inside = !inside;
|
|
85
|
+
}
|
|
86
|
+
if (inside) {
|
|
87
|
+
let best = from, bestD = Infinity;
|
|
88
|
+
for (let k = from; k <= to; k++) {
|
|
89
|
+
const d = Math.hypot(data[k * stride] - x, data[k * stride + 1] - y);
|
|
90
|
+
if (d < bestD) {
|
|
91
|
+
bestD = d;
|
|
92
|
+
best = k;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return best;
|
|
96
|
+
}
|
|
97
|
+
from = to + 1;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The shape the pointer is inside (distance 0), else the one whose outline is nearest, by the shape's index. Shapes
|
|
103
|
+
* made of NaN are left out. A NaN coordinate of the pointer means "ignore this direction", and the shapes' own points
|
|
104
|
+
* then stand for them, as for any other mode.
|
|
105
|
+
*/
|
|
106
|
+
export function nearestShape(shapes, points, x, y) {
|
|
107
|
+
if (x !== x || y !== y)
|
|
108
|
+
return nearestPoint(points, x, y);
|
|
109
|
+
const { data, perShape: m, count } = shapes;
|
|
110
|
+
let best = -1, bestD = Infinity;
|
|
111
|
+
for (let k = 0; k < count; k++) {
|
|
112
|
+
const at = k * m * 2;
|
|
113
|
+
if (data[at] !== data[at] || data[at + 1] !== data[at + 1])
|
|
114
|
+
continue;
|
|
115
|
+
// Quick out: a shape whose bounding box is farther than the best so far cannot be nearer.
|
|
116
|
+
let x0 = Infinity, x1 = -Infinity, y0 = Infinity, y1 = -Infinity;
|
|
117
|
+
for (let j = 0; j < m; j++) {
|
|
118
|
+
const px = data[at + 2 * j], py = data[at + 2 * j + 1];
|
|
119
|
+
if (px < x0)
|
|
120
|
+
x0 = px;
|
|
121
|
+
if (px > x1)
|
|
122
|
+
x1 = px;
|
|
123
|
+
if (py < y0)
|
|
124
|
+
y0 = py;
|
|
125
|
+
if (py > y1)
|
|
126
|
+
y1 = py;
|
|
127
|
+
}
|
|
128
|
+
if (Math.hypot(Math.max(x0 - x, 0, x - x1), Math.max(y0 - y, 0, y - y1)) >= bestD)
|
|
129
|
+
continue;
|
|
130
|
+
let inside = false, edge = Infinity;
|
|
131
|
+
for (let j = 0, prev = m - 1; j < m; prev = j++) {
|
|
132
|
+
const ax = data[at + 2 * prev], ay = data[at + 2 * prev + 1], bx = data[at + 2 * j], by = data[at + 2 * j + 1];
|
|
133
|
+
if ((by > y) !== (ay > y) && x < ((ax - bx) * (y - by)) / (ay - by) + bx)
|
|
134
|
+
inside = !inside;
|
|
135
|
+
const sx = bx - ax, sy = by - ay, len2 = sx * sx + sy * sy;
|
|
136
|
+
const t = len2 > 0 ? Math.max(0, Math.min(1, ((x - ax) * sx + (y - ay) * sy) / len2)) : 0;
|
|
137
|
+
const d = Math.hypot(ax + t * sx - x, ay + t * sy - y);
|
|
138
|
+
if (d < edge)
|
|
139
|
+
edge = d;
|
|
140
|
+
}
|
|
141
|
+
const d = inside ? 0 : edge;
|
|
142
|
+
if (d < bestD) {
|
|
143
|
+
bestD = d;
|
|
144
|
+
best = k;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return best < 0 ? null : { index: best, distance: bestD };
|
|
148
|
+
}
|
|
149
|
+
/** Where the runs of a path are: each stretch between NaN points, as the index of its first vertex and one past its last. */
|
|
150
|
+
function runsIn(path) {
|
|
151
|
+
const out = [], { data, count, stride } = path;
|
|
152
|
+
let from = -1;
|
|
153
|
+
for (let k = 0; k <= count; k++) {
|
|
154
|
+
const real = k < count && data[k * stride] === data[k * stride] && data[k * stride + 1] === data[k * stride + 1];
|
|
155
|
+
if (real && from < 0)
|
|
156
|
+
from = k;
|
|
157
|
+
else if (!real && from >= 0) {
|
|
158
|
+
out.push([from, k]);
|
|
159
|
+
from = -1;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Whether (x, y) is inside a shape a trace draws: each run of its line closed back along the same run of its baseline.
|
|
166
|
+
* The point it belongs to is the one owning the nearest vertex of the line in that run, else null.
|
|
167
|
+
*/
|
|
168
|
+
export function insideTrace(trace, x, y) {
|
|
169
|
+
const base = trace.base;
|
|
170
|
+
if (!base || x !== x || y !== y)
|
|
171
|
+
return null;
|
|
172
|
+
const tops = runsIn(trace.line), feet = runsIn(base), a = trace.line, b = base;
|
|
173
|
+
for (let r = 0; r < tops.length && r < feet.length; r++) {
|
|
174
|
+
const [t0, t1] = tops[r], [f0, f1] = feet[r], n = t1 - t0, m = f1 - f0, total = n + m;
|
|
175
|
+
// The line forward, then the baseline back.
|
|
176
|
+
const vx = (j) => (j < n ? a.data[(t0 + j) * a.stride] : b.data[(f1 - 1 - (j - n)) * b.stride]);
|
|
177
|
+
const vy = (j) => (j < n ? a.data[(t0 + j) * a.stride + 1] : b.data[(f1 - 1 - (j - n)) * b.stride + 1]);
|
|
178
|
+
let inside = false;
|
|
179
|
+
for (let j = 0, prev = total - 1; j < total; prev = j++) {
|
|
180
|
+
const yj = vy(j), yp = vy(prev), xj = vx(j), xp = vx(prev);
|
|
181
|
+
if ((yj > y) !== (yp > y) && x < ((xp - xj) * (y - yj)) / (yp - yj) + xj)
|
|
182
|
+
inside = !inside;
|
|
183
|
+
}
|
|
184
|
+
if (inside) {
|
|
185
|
+
let best = t0, bestD = Infinity;
|
|
186
|
+
for (let k = t0; k < t1; k++) {
|
|
187
|
+
const d = Math.hypot(a.data[k * a.stride] - x, a.data[k * a.stride + 1] - y);
|
|
188
|
+
if (d < bestD) {
|
|
189
|
+
bestD = d;
|
|
190
|
+
best = k;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return trace.owner[best];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
/** The nearest point under `mode` ('line' or 'area') to a path a renderer traces, by the point each vertex belongs to. */
|
|
199
|
+
export function nearestTraced(trace, mode, x, y) {
|
|
200
|
+
if (mode === 'area') {
|
|
201
|
+
const inside = insideTrace(trace, x, y);
|
|
202
|
+
if (inside !== null)
|
|
203
|
+
return { index: inside, distance: 0 };
|
|
204
|
+
}
|
|
205
|
+
const found = nearestSegment(trace.line, x, y);
|
|
206
|
+
return found && { index: trace.owner[found.index], distance: found.distance };
|
|
207
|
+
}
|
|
208
|
+
/** The nearest point under `mode`; `base` is the baseline for an area (ignored otherwise). */
|
|
209
|
+
export function nearest(points, mode, base, x, y) {
|
|
210
|
+
if (mode === 'point')
|
|
211
|
+
return nearestPoint(points, x, y);
|
|
212
|
+
if (mode === 'area' && base) {
|
|
213
|
+
const inside = insideArea(points, base(), x, y);
|
|
214
|
+
if (inside !== null)
|
|
215
|
+
return { index: inside, distance: 0 };
|
|
216
|
+
}
|
|
217
|
+
return nearestSegment(points, x, y);
|
|
218
|
+
}
|
|
219
|
+
// ─── Series and planes ───
|
|
220
|
+
/** The hit for drawn point `index` of a series, with the pointer `distance` away. */
|
|
221
|
+
export function pointHit(series, index, distance = 0) { return hitAt(series, index, distance); }
|
|
222
|
+
function hitAt(series, index, distance) {
|
|
223
|
+
const d = series.drawn;
|
|
224
|
+
if (!d)
|
|
225
|
+
return null;
|
|
226
|
+
const { raw, stride, points } = d, names = d.channels, bound = names.length, at = index * stride, channels = {};
|
|
227
|
+
for (let k = 0; k < bound; k++)
|
|
228
|
+
channels[names[k]] = raw[at + stride - bound + k];
|
|
229
|
+
const row = d.rowOf?.(index);
|
|
230
|
+
// In a stack the point is drawn above its own value by the layers below it.
|
|
231
|
+
const own = raw[at + d.secondColumn], lift = d.top && d.additive ? d.top[index] - own : NaN;
|
|
232
|
+
return {
|
|
233
|
+
series, plane: d.plane, index, ...(row === undefined || row < 0 ? {} : { row }), ...(lift === lift ? { lift } : {}),
|
|
234
|
+
first: raw[at + d.firstColumn], second: raw[at + d.secondColumn], channels,
|
|
235
|
+
px: points.data[index * points.stride], py: points.data[index * points.stride + 1], distance,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The nearest drawn point of a series to a position in plot pixels, within `maxDistance` (default: its `hit` radius), as
|
|
240
|
+
* its `hit` mode measures it. A NaN for `x` or `y` leaves that direction out, so `hitTest(series, x, NaN, Infinity)` is
|
|
241
|
+
* the point nearest in x whatever its height. Null if nothing is near enough, or the series takes no hits.
|
|
242
|
+
*/
|
|
243
|
+
export function hitTest(series, x, y, maxDistance) {
|
|
244
|
+
const h = series.attrs.hit, d = series.drawn;
|
|
245
|
+
if (h === false || !d || d.points.count === 0)
|
|
246
|
+
return null;
|
|
247
|
+
const o = typeof h === 'string' ? { mode: h } : h ?? {};
|
|
248
|
+
const mode = o.mode ?? series.hitHint ?? 'point';
|
|
249
|
+
const tracedMode = mode === 'line' || mode === 'area' ? mode : null;
|
|
250
|
+
// A path a renderer traces (steps, curves) is what is measured, but a pointer with a coordinate left out measures to points.
|
|
251
|
+
const traced = tracedMode && x === x && y === y ? series.trace() : null;
|
|
252
|
+
const found = mode === 'shape'
|
|
253
|
+
? (() => { const g = series.shapes(); return g ? nearestShape(g, d.points, x, y) : nearestPoint(d.points, x, y); })()
|
|
254
|
+
: traced && tracedMode
|
|
255
|
+
? nearestTraced(traced, tracedMode, x, y)
|
|
256
|
+
: nearest(d.points, mode, mode === 'area' ? () => series.baseline(o.baseline ?? 0) : null, x, y);
|
|
257
|
+
const radius = maxDistance ?? (series.chart?.input?.coarse ? Math.max(o.radius ?? DEFAULT_RADIUS, COARSE_RADIUS) : o.radius ?? DEFAULT_RADIUS);
|
|
258
|
+
if (!found || !(found.distance <= radius))
|
|
259
|
+
return null;
|
|
260
|
+
return hitAt(series, found.index, found.distance);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* The nearest point of any series in the plane that takes hits, within each series' own radius, by that series' `hit`
|
|
264
|
+
* mode. A tie goes to the series drawn last, which is the one on top.
|
|
265
|
+
*/
|
|
266
|
+
export function hitPlane(plane, x, y) {
|
|
267
|
+
const series = plane.series;
|
|
268
|
+
let best = null;
|
|
269
|
+
for (let i = series.length - 1; i >= 0; i--) {
|
|
270
|
+
const h = hitTest(series[i], x, y);
|
|
271
|
+
if (h && (!best || h.distance < best.distance))
|
|
272
|
+
best = h;
|
|
273
|
+
}
|
|
274
|
+
return best;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* The nearest point of every series that takes hits, topmost first. `radius` replaces each series' own, and is unlimited
|
|
278
|
+
* by default, so `hitAll(plane, x, NaN)` is each series at the pointer's x: what a crosshair tooltip lists.
|
|
279
|
+
*/
|
|
280
|
+
export function hitAll(plane, x, y, radius = Infinity) {
|
|
281
|
+
const out = [];
|
|
282
|
+
const series = plane.series;
|
|
283
|
+
for (let i = series.length - 1; i >= 0; i--) {
|
|
284
|
+
const h = hitTest(series[i], x, y, radius);
|
|
285
|
+
if (h)
|
|
286
|
+
out.push(h);
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* The point of every series that is nearest the pointer *along the first axis*, whatever its distance across: what a
|
|
292
|
+
* reading shared by all series, such as a crosshair tooltip, lists. It is measured in the axis' own terms and not in
|
|
293
|
+
* pixels, so it is right wherever the plane puts that axis: across a Cartesian plane, up one whose domain is vertical, and
|
|
294
|
+
* round a radial plane, where the nearest point is the one nearest in angle (and a full turn wraps, so a pointer just
|
|
295
|
+
* before the start of the sweep finds the last points). Topmost series first. Series that take no hits are left out.
|
|
296
|
+
*/
|
|
297
|
+
export function hitAcross(plane, x, y) {
|
|
298
|
+
const out = [], series = plane.series;
|
|
299
|
+
for (let i = series.length - 1; i >= 0; i--) {
|
|
300
|
+
const s = series[i], d = s.drawn;
|
|
301
|
+
if (s.attrs.hit === false || !d || d.points.count === 0)
|
|
302
|
+
continue;
|
|
303
|
+
const a = s.firstAxis, b = s.secondAxis, target = a.fractionOf(plane.unplace(x, y, a, b)[0]);
|
|
304
|
+
if (target !== target)
|
|
305
|
+
continue;
|
|
306
|
+
const wraps = plane.cyclic(a), { raw, stride, firstColumn, secondColumn } = d;
|
|
307
|
+
let best = -1, bestD = Infinity;
|
|
308
|
+
for (let k = 0, at = 0; k < d.points.count; k++, at += stride) {
|
|
309
|
+
const v = raw[at + firstColumn], w = raw[at + secondColumn];
|
|
310
|
+
if (v !== v || w !== w)
|
|
311
|
+
continue;
|
|
312
|
+
let gap = Math.abs(a.fractionOf(v) - target);
|
|
313
|
+
if (wraps) {
|
|
314
|
+
gap -= Math.floor(gap);
|
|
315
|
+
if (gap > 0.5)
|
|
316
|
+
gap = 1 - gap;
|
|
317
|
+
}
|
|
318
|
+
if (gap < bestD) {
|
|
319
|
+
bestD = gap;
|
|
320
|
+
best = k;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (best < 0)
|
|
324
|
+
continue;
|
|
325
|
+
const px = d.points.data[best * d.points.stride], py = d.points.data[best * d.points.stride + 1];
|
|
326
|
+
const h = hitAt(s, best, Math.hypot(px - x, py - y));
|
|
327
|
+
if (h)
|
|
328
|
+
out.push(h);
|
|
329
|
+
}
|
|
330
|
+
return out;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Where a series' line is at position `first` of its first axis, read as a straight line between the two drawn points
|
|
334
|
+
* either side of it, in data terms (so it is exact for a `LinePath` on a linear scale, and may sit off a curve or a line
|
|
335
|
+
* drawn another way: see the tooltip's `interpolate`). Only a domain series has one; others, a series that takes no
|
|
336
|
+
* hits, a position outside the data and one beside a gap give null. The hit is `interpolated`: its `index` and `row`
|
|
337
|
+
* are the nearer of the two points, and `px`, `py` are where the line is.
|
|
338
|
+
*/
|
|
339
|
+
export function interpolate(series, first) {
|
|
340
|
+
const d = series.drawn;
|
|
341
|
+
if (!d || !d.alongDomain || series.attrs.hit === false)
|
|
342
|
+
return null;
|
|
343
|
+
const { raw, stride: rs, plane } = d, n = d.points.count;
|
|
344
|
+
if (n < 2 || !(first >= raw[0] && first <= raw[(n - 1) * rs]))
|
|
345
|
+
return null;
|
|
346
|
+
// The last point at or before `first`, found by halving: the domain ascends.
|
|
347
|
+
let lo = 0, hi = n - 1;
|
|
348
|
+
while (hi - lo > 1) {
|
|
349
|
+
const mid = (lo + hi) >> 1;
|
|
350
|
+
if (raw[mid * rs] <= first)
|
|
351
|
+
lo = mid;
|
|
352
|
+
else
|
|
353
|
+
hi = mid;
|
|
354
|
+
}
|
|
355
|
+
const d0 = raw[lo * rs], d1 = raw[hi * rs], v0 = raw[lo * rs + 1], v1 = raw[hi * rs + 1];
|
|
356
|
+
// In a stack the line is drawn through the stacked values, though it reads as the series' own.
|
|
357
|
+
const tops = d.top, p0 = tops ? tops[lo] : v0, p1 = tops ? tops[hi] : v1;
|
|
358
|
+
// On a point exactly, that point is the answer, even at the end of a run with a gap after it.
|
|
359
|
+
const onPoint = first === d0 && v0 === v0;
|
|
360
|
+
if (!onPoint && (v0 !== v0 || v1 !== v1))
|
|
361
|
+
return null;
|
|
362
|
+
const traced = onPoint ? null : series.trace();
|
|
363
|
+
if (traced)
|
|
364
|
+
return interpolateTraced(series, first, traced);
|
|
365
|
+
const t = onPoint || !(d1 > d0) ? 0 : (first - d0) / (d1 - d0), value = onPoint ? v0 : v0 + t * (v1 - v0);
|
|
366
|
+
const plotted = onPoint ? p0 : p0 + t * (p1 - p0);
|
|
367
|
+
const buf = new Float64Array([first, plotted]), a = series.firstAxis, b = series.secondAxis;
|
|
368
|
+
a.normalize(buf, 1, 2, 0);
|
|
369
|
+
b.normalize(buf, 1, 2, 1);
|
|
370
|
+
plane.place({ data: buf, stride: 2, count: 1 }, a, b);
|
|
371
|
+
const near = hitAt(series, t < 0.5 ? lo : hi, 0);
|
|
372
|
+
return near && { ...near, first, second: value, px: buf[0], py: buf[1], interpolated: true };
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* A reading between two points of a series whose renderer draws something other than straight lines through them: where a
|
|
376
|
+
* line across the plot at `first` (a spoke on a polar plane) crosses the traced path, read back into data. The value is the
|
|
377
|
+
* path's own there, less what a stack lays under it, so a step reads as its level and a curve as the height it is drawn at.
|
|
378
|
+
*/
|
|
379
|
+
function interpolateTraced(series, first, trace) {
|
|
380
|
+
const d = series.drawn;
|
|
381
|
+
if (!d)
|
|
382
|
+
return null;
|
|
383
|
+
const { plane, raw, stride: rs } = d, a = series.firstAxis, b = series.secondAxis;
|
|
384
|
+
// The line at `first` across the second axis, in pixels.
|
|
385
|
+
const probe = new Float64Array([a.fractionOf(first), 0, a.fractionOf(first), 1]);
|
|
386
|
+
plane.place({ data: probe, stride: 2, count: 2 }, a, b);
|
|
387
|
+
const rx = probe[2] - probe[0], ry = probe[3] - probe[1];
|
|
388
|
+
const { data, count, stride } = trace.line, eps = 1e-9;
|
|
389
|
+
for (let k = 0; k + 1 < count; k++) {
|
|
390
|
+
const ax = data[k * stride], ay = data[k * stride + 1], bx = data[(k + 1) * stride], by = data[(k + 1) * stride + 1];
|
|
391
|
+
if (ax !== ax || ay !== ay || bx !== bx || by !== by)
|
|
392
|
+
continue;
|
|
393
|
+
const sx = bx - ax, sy = by - ay, cross = rx * sy - ry * sx;
|
|
394
|
+
if (Math.abs(cross) < 1e-12)
|
|
395
|
+
continue; // parallel to the probe: its ends are met by the pieces either side
|
|
396
|
+
const qx = ax - probe[0], qy = ay - probe[1];
|
|
397
|
+
const along = (qx * sy - qy * sx) / cross, u = (qx * ry - qy * rx) / cross; // along the probe, and along this piece
|
|
398
|
+
if (along < -eps || along > 1 + eps || u < -eps || u > 1 + eps)
|
|
399
|
+
continue;
|
|
400
|
+
const px = ax + u * sx, py = ay + u * sy, oa = trace.owner[k], ob = trace.owner[k + 1];
|
|
401
|
+
const plotted = plane.unplace(px, py, a, b)[1];
|
|
402
|
+
const own = (i) => raw[i * rs + d.secondColumn];
|
|
403
|
+
let value = plotted;
|
|
404
|
+
if (d.top && oa >= 0 && ob >= 0) {
|
|
405
|
+
// In a stack the path is drawn at the stacked value, which reads as the series' own: take off what is under it.
|
|
406
|
+
if (d.additive) {
|
|
407
|
+
const sa = d.top[oa] - own(oa), sb = d.top[ob] - own(ob);
|
|
408
|
+
value = plotted - (sa + u * (sb - sa));
|
|
409
|
+
}
|
|
410
|
+
else
|
|
411
|
+
value = own(oa) + u * (own(ob) - own(oa));
|
|
412
|
+
}
|
|
413
|
+
const near = hitAt(series, u < 0.5 ? oa : ob, 0);
|
|
414
|
+
return near && { ...near, first, second: value, px, py, interpolated: true };
|
|
415
|
+
}
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
/** Every series' line read at the pointer, topmost first: `interpolate` at the pointer's place along each series' first axis. */
|
|
419
|
+
export function interpolateAll(plane, x, y) {
|
|
420
|
+
const out = [];
|
|
421
|
+
const series = plane.series;
|
|
422
|
+
for (let i = series.length - 1; i >= 0; i--) {
|
|
423
|
+
const s = series[i], h = interpolate(s, plane.unplace(x, y, s.firstAxis, s.secondAxis)[0]);
|
|
424
|
+
if (h)
|
|
425
|
+
out.push(h);
|
|
426
|
+
}
|
|
427
|
+
return out;
|
|
428
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inkplot.
|
|
3
|
+
*
|
|
4
|
+
* Conventions
|
|
5
|
+
* - Erasable TypeScript only, so Node can run it directly.
|
|
6
|
+
* - Members are `private` unless another class genuinely needs them. Where elements have to talk to
|
|
7
|
+
* each other (a plane driving its series, a series driving its axes) the methods are public, named
|
|
8
|
+
* without an underscore, and documented as protocol under an "Engine protocol" comment.
|
|
9
|
+
* - A parent declares its children as a tuple type, so order and arity are checked by the compiler.
|
|
10
|
+
* - Options that are declared and not yet supported (`bind` on a line, area or bar) throw when used, via stub.ts.
|
|
11
|
+
*/
|
|
12
|
+
export { type Extent, type Insets, type LayoutRequest, type Rect, type Side, type Size } from './geometry.ts';
|
|
13
|
+
export { type ArrangeEvent, type AttachEvent, type ChartEvent, type ChartEventInit, type ChartKeyEvent, type ChartPointerEvent, EVENT_ARRANGE, EVENT_ATTACH, EVENT_FOCUS, EVENT_HOVER, EVENT_KEY, EVENT_MEASURE, EVENT_PAINT, EVENT_POINTER, EventBase, type FocusEvent, type Hit, type HoverEvent, type MeasureEvent, type PaintEvent } from './events.ts';
|
|
14
|
+
export { type FontSpec, type Platform, type PlatformNode, type RawFocus, type RawKey, type RawPointer, StringPlatform, type SvgTag, type TextMeasurer, type Unsubscribe, estimateTextWidth } from './platform.ts';
|
|
15
|
+
export { type DOMContainer, DOMPlatform, type DOMPlatformOptions } from './dom-platform.ts';
|
|
16
|
+
export { type Counters, type NodeOptions, type Placement, type StageName, Surface } from './surface.ts';
|
|
17
|
+
export { type AnyElement, type BaseAttributes, ChartElement, type ElementArgs, type ElementClass, type ElementRef, type FixedIndex, type Meta, type VariadicChild, childrenOfType, closestAncestorOfType, descendantsOfType, findById, firstDescendantOfType, resolveRef, walk } from './element.ts';
|
|
18
|
+
export { IntlTimeScale, type IntlTimeScaleAttributes } from './time-intl.ts';
|
|
19
|
+
export { TemporalTimeScale, type TemporalLike, type TemporalTimeScaleAttributes, type ZonedLike } from './time-temporal.ts';
|
|
20
|
+
export { TimeScale, type TimeRank, type TimeScaleAttributes, type TimeUnit } from './time.ts';
|
|
21
|
+
export { Scale, type ScaleAttributes } from './scale.ts';
|
|
22
|
+
export { BandScale, type BandScaleAttributes, LinearScale, LogScale, type LogScaleAttributes, SqrtScale } from './scales.ts';
|
|
23
|
+
export { Dimension, type DimensionAttributes, type Tick } from './dimension.ts';
|
|
24
|
+
export { Axis, type AxisAttributes, type AxisOrientation, type CartesianOrientation, type PolarOrientation, type Ruler, type TitleSpot } from './axis.ts';
|
|
25
|
+
export { applyText } from './text.ts';
|
|
26
|
+
export { type AxisMetrics, type BaseTheme, type LineProps, type MarkerMetrics, type Roots, type SelectorName, type Selectors, type ShapeProps, type TextProps, type Theme, extendTheme, resolveStyle } from './theme.ts';
|
|
27
|
+
export { darkTheme, lightTheme } from './themes.ts';
|
|
28
|
+
export { type DataNode, DataSource, type DataSourceAttributes, type DataStage, DataTransform, type FillPlan, type FillResult, type PlanContext, type PointBuffer, type PointView } from './data.ts';
|
|
29
|
+
export { type Column, CompositeDataSource, type CompositeDataSourceAttributes, type Field, FlatDataSource, type FlatDataSourceAttributes, ObjectDataSource, type ObjectDataSourceAttributes, SyntheticDataSource, type SyntheticDataSourceAttributes } from './sources.ts';
|
|
30
|
+
export { DecimationKernel, Decimator, type DecimatorAttributes, LttbKernel, M4Kernel, MinMaxKernel, type ReduceResult, StrideKernel } from './decimation.ts';
|
|
31
|
+
export { AreaPath, type AreaPathAttributes, LinePath, type LinePathAttributes, type PolygonSet, type ResolvedBinding, type Trace, SeriesRenderer, type SeriesRendererAttributes, type StyleBindable } from './renderer.ts';
|
|
32
|
+
export { Curve, type CurveAttributes, LinearCurve, areaOutline, polyline } from './curve.ts';
|
|
33
|
+
export { ArcCurve, type ArcCurveAttributes, BasisCurve, BumpCurve, type BumpCurveAttributes, CardinalCurve, type CardinalCurveAttributes, CatmullRomCurve, type CatmullRomCurveAttributes, MonotoneCurve, NaturalCurve, type Piece, type Push, QuadraticCurve, StrokeCurve, arcTo, cubicTo, hermiteTo, lineTo, quadTo, smoothTo } from './curves.ts';
|
|
34
|
+
export { StepCurve, type StepCurveAttributes, type StepMode, type Stepped, stepLines } from './steps.ts';
|
|
35
|
+
export { BoxPath, type BoxPathAttributes } from './boxplot.ts';
|
|
36
|
+
export { BoxStats, type BoxStatsAttributes } from './stats.ts';
|
|
37
|
+
export { quantile } from './quantile.ts';
|
|
38
|
+
export { Density, type DensityAttributes } from './density.ts';
|
|
39
|
+
export { ErrorBand, type ErrorBandAttributes, ErrorBars, type ErrorBarsAttributes } from './errors.ts';
|
|
40
|
+
export { barShift } from './bars.ts';
|
|
41
|
+
export { BarLinePath, type BarLinePathAttributes, BarPath, type BarPathAttributes, BarRenderer, type BarRendererAttributes, type BarOptions, barShapes, stemLines } from './bars.ts';
|
|
42
|
+
export { Stack, type StackAttributes, type StackAlign, type StackMode, type Layout, alignRows, layOut } from './stack.ts';
|
|
43
|
+
export { DomainSeries, type DomainSeriesAttributes, type Drawn, type Rows, Series, type SeriesGroup, type StackLayer, seriesOf, paintSample, type SampleCache, type SeriesAttributes, type SeriesChildren, XYSeries, type XYSeriesAttributes } from './series.ts';
|
|
44
|
+
export { CartesianPlane, type CartesianPlaneAttributes, Plane, type PlaneAttributes, type PlaneChildMap, type PlaneChildren } from './plane.ts';
|
|
45
|
+
export { PolarPlane, type PolarPlaneAttributes, RadarPlane, type RadarPlaneAttributes, RadialPlane, type RadialPlaneAttributes } from './radial.ts';
|
|
46
|
+
export { type PngHost, type PngOptions, svgToPng, toPng } from './png.ts';
|
|
47
|
+
export { BoxZoom, type BoxZoomAttributes } from './boxzoom.ts';
|
|
48
|
+
export { Brush, type BrushAttributes, type BrushRange, type BrushSelection } from './brush.ts';
|
|
49
|
+
export { DEFAULT_PANZOOM_KEYS, PanZoom, type PanZoomAction, type PanZoomAttributes, type PanZoomKeys } from './panzoom.ts';
|
|
50
|
+
export { type ChartFacts, ChartSummary, type ChartSummaryAttributes, englishSummary } from './summary.ts';
|
|
51
|
+
export { type AriaDefaults, hideFromAssistive, writeAria } from './aria.ts';
|
|
52
|
+
export { drawFocusRing, makeTabStop, pressesButton } from './focus.ts';
|
|
53
|
+
export { type Table, type TableOptions, readTable } from './table.ts';
|
|
54
|
+
export { InputHost, inputOf } from './input.ts';
|
|
55
|
+
export { Chart, type ChartAttributes, type Describer, type ChartChildMap, type ChartChildren, type FlushStats, type SvgOptions, toSvgString } from './chart.ts';
|
|
56
|
+
export { type Binding, type Bindings, ColorAxis, type ColorAxisAttributes, type ColorRampName, MappedDimension, type MappedDimensionAttributes, SizeAxis, type SizeAxisAttributes } from './mapped.ts';
|
|
57
|
+
export { Legend, type LegendAttributes } from './legend.ts';
|
|
58
|
+
export { ColorKey, Key, SizeKey, type ColorKeyAttributes, type KeyAttributes, type KeyOrientation, type SizeKeyAttributes } from './key.ts';
|
|
59
|
+
export { Trendline, LinearTrend, PolynomialTrend, SinusoidalTrend, LoessTrend, type LinearTrendAttributes, type LoessTrendAttributes, type PolynomialTrendAttributes, type SinusoidalTrendAttributes, type TrendFit, type TrendModel, type TrendlineAttributes } from './trend.ts';
|
|
60
|
+
export { HeatMap, type HeatMapAttributes, type HeatMapBindable } from './heatmap.ts';
|
|
61
|
+
export { CircleMarker, CrossMarker, DotMarker, LineMarker, Marker, PlusMarker, ShapeMarker, SquareMarker, type DotMarkerAttributes, type DotMarkerBindable, type LineMarkerBindable, type MarkerAttributes, type MarkerStyle, type ShapeMarkerBindable } from './marker.ts';
|
|
62
|
+
export { type HitMode, type HitOptions, hitAcross, hitAll, hitPlane, hitTest, insideArea, insideTrace, interpolate, interpolateAll, nearest, nearestPoint, nearestSegment, nearestShape, nearestTraced, pointHit } from './hit.ts';
|
|
63
|
+
export { type DragInfo, PointerListener, type PointerListenerAttributes, type PointerInfo } from './pointer.ts';
|
|
64
|
+
export { type CalloutLook, calloutSize, clearCallout, paintCallout } from './callout.ts';
|
|
65
|
+
export { Cursor, type CursorAction, type CursorAttributes, type CursorChild, type CursorChildMap, type CursorKeys, type CursorState, DEFAULT_CURSOR_KEYS } from './cursor.ts';
|
|
66
|
+
export { Crosshair, type CrosshairAttributes } from './crosshair.ts';
|
|
67
|
+
export { ChartTitle, type ChartTitleAttributes, ChartTooltip, type ChartTooltipAttributes, type TitleRole } from './furniture.ts';
|
|
68
|
+
export { CalloutAnnotation, type CalloutAnnotationAttributes, LineAnnotation, type LineAnnotationAttributes, type LineAnnotationCommon } from './annotation.ts';
|
|
69
|
+
export { LINE_HEIGHT, measureBlock, paintLines } from './text.ts';
|
|
70
|
+
export { type ElementJSON, type ElementRegistry, Refs, type SerializeOptions, applyJSON, fromJSON, toJSON } from './serialize.ts';
|
|
71
|
+
export { registry } from './registry.ts';
|
|
72
|
+
export { type LineSeriesOptions, lineSeries } from './simple.ts';
|
|
73
|
+
export { AUTO, BOOLEAN, NUMBER, STRING, type AttrTypes, type AttrTypesFor, type Coerce, type ExpandOptions, expandAttributes } from './attrs.ts';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inkplot.
|
|
3
|
+
*
|
|
4
|
+
* Conventions
|
|
5
|
+
* - Erasable TypeScript only, so Node can run it directly.
|
|
6
|
+
* - Members are `private` unless another class genuinely needs them. Where elements have to talk to
|
|
7
|
+
* each other (a plane driving its series, a series driving its axes) the methods are public, named
|
|
8
|
+
* without an underscore, and documented as protocol under an "Engine protocol" comment.
|
|
9
|
+
* - A parent declares its children as a tuple type, so order and arity are checked by the compiler.
|
|
10
|
+
* - Options that are declared and not yet supported (`bind` on a line, area or bar) throw when used, via stub.ts.
|
|
11
|
+
*/
|
|
12
|
+
export {} from './geometry.js';
|
|
13
|
+
export { EVENT_ARRANGE, EVENT_ATTACH, EVENT_FOCUS, EVENT_HOVER, EVENT_KEY, EVENT_MEASURE, EVENT_PAINT, EVENT_POINTER, EventBase } from './events.js';
|
|
14
|
+
export { StringPlatform, estimateTextWidth } from './platform.js';
|
|
15
|
+
export { DOMPlatform } from './dom-platform.js';
|
|
16
|
+
export { Surface } from './surface.js';
|
|
17
|
+
export { ChartElement, childrenOfType, closestAncestorOfType, descendantsOfType, findById, firstDescendantOfType, resolveRef, walk } from './element.js';
|
|
18
|
+
export { IntlTimeScale } from './time-intl.js';
|
|
19
|
+
export { TemporalTimeScale } from './time-temporal.js';
|
|
20
|
+
export { TimeScale } from './time.js';
|
|
21
|
+
export { Scale } from './scale.js';
|
|
22
|
+
export { BandScale, LinearScale, LogScale, SqrtScale } from './scales.js';
|
|
23
|
+
export { Dimension } from './dimension.js';
|
|
24
|
+
export { Axis } from './axis.js';
|
|
25
|
+
export { applyText } from './text.js';
|
|
26
|
+
export { extendTheme, resolveStyle } from './theme.js';
|
|
27
|
+
export { darkTheme, lightTheme } from './themes.js';
|
|
28
|
+
export { DataSource, DataTransform } from './data.js';
|
|
29
|
+
export { CompositeDataSource, FlatDataSource, ObjectDataSource, SyntheticDataSource } from './sources.js';
|
|
30
|
+
export { DecimationKernel, Decimator, LttbKernel, M4Kernel, MinMaxKernel, StrideKernel } from './decimation.js';
|
|
31
|
+
export { AreaPath, LinePath, SeriesRenderer } from './renderer.js';
|
|
32
|
+
export { Curve, LinearCurve, areaOutline, polyline } from './curve.js';
|
|
33
|
+
export { ArcCurve, BasisCurve, BumpCurve, CardinalCurve, CatmullRomCurve, MonotoneCurve, NaturalCurve, QuadraticCurve, StrokeCurve, arcTo, cubicTo, hermiteTo, lineTo, quadTo, smoothTo } from './curves.js';
|
|
34
|
+
export { StepCurve, stepLines } from './steps.js';
|
|
35
|
+
export { BoxPath } from './boxplot.js';
|
|
36
|
+
export { BoxStats } from './stats.js';
|
|
37
|
+
export { quantile } from './quantile.js';
|
|
38
|
+
export { Density } from './density.js';
|
|
39
|
+
export { ErrorBand, ErrorBars } from './errors.js';
|
|
40
|
+
export { barShift } from './bars.js';
|
|
41
|
+
export { BarLinePath, BarPath, BarRenderer, barShapes, stemLines } from './bars.js';
|
|
42
|
+
export { Stack, alignRows, layOut } from './stack.js';
|
|
43
|
+
export { DomainSeries, Series, seriesOf, paintSample, XYSeries } from './series.js';
|
|
44
|
+
export { CartesianPlane, Plane } from './plane.js';
|
|
45
|
+
export { PolarPlane, RadarPlane, RadialPlane } from './radial.js';
|
|
46
|
+
export { svgToPng, toPng } from './png.js';
|
|
47
|
+
export { BoxZoom } from './boxzoom.js';
|
|
48
|
+
export { Brush } from './brush.js';
|
|
49
|
+
export { DEFAULT_PANZOOM_KEYS, PanZoom } from './panzoom.js';
|
|
50
|
+
export { ChartSummary, englishSummary } from './summary.js';
|
|
51
|
+
export { hideFromAssistive, writeAria } from './aria.js';
|
|
52
|
+
export { drawFocusRing, makeTabStop, pressesButton } from './focus.js';
|
|
53
|
+
export { readTable } from './table.js';
|
|
54
|
+
export { InputHost, inputOf } from './input.js';
|
|
55
|
+
export { Chart, toSvgString } from './chart.js';
|
|
56
|
+
export { ColorAxis, MappedDimension, SizeAxis } from './mapped.js';
|
|
57
|
+
export { Legend } from './legend.js';
|
|
58
|
+
export { ColorKey, Key, SizeKey } from './key.js';
|
|
59
|
+
export { Trendline, LinearTrend, PolynomialTrend, SinusoidalTrend, LoessTrend } from './trend.js';
|
|
60
|
+
export { HeatMap } from './heatmap.js';
|
|
61
|
+
export { CircleMarker, CrossMarker, DotMarker, LineMarker, Marker, PlusMarker, ShapeMarker, SquareMarker } from './marker.js';
|
|
62
|
+
export { hitAcross, hitAll, hitPlane, hitTest, insideArea, insideTrace, interpolate, interpolateAll, nearest, nearestPoint, nearestSegment, nearestShape, nearestTraced, pointHit } from './hit.js';
|
|
63
|
+
export { PointerListener } from './pointer.js';
|
|
64
|
+
export { calloutSize, clearCallout, paintCallout } from './callout.js';
|
|
65
|
+
export { Cursor, DEFAULT_CURSOR_KEYS } from './cursor.js';
|
|
66
|
+
export { Crosshair } from './crosshair.js';
|
|
67
|
+
export { ChartTitle, ChartTooltip } from './furniture.js';
|
|
68
|
+
export { CalloutAnnotation, LineAnnotation } from './annotation.js';
|
|
69
|
+
export { LINE_HEIGHT, measureBlock, paintLines } from './text.js';
|
|
70
|
+
export { Refs, applyJSON, fromJSON, toJSON } from './serialize.js';
|
|
71
|
+
export { registry } from './registry.js';
|
|
72
|
+
export { lineSeries } from './simple.js';
|
|
73
|
+
export { AUTO, BOOLEAN, NUMBER, STRING, expandAttributes } from './attrs.js';
|
package/dist/input.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { AnyElement } from './element.ts';
|
|
2
|
+
import type { Chart } from './chart.ts';
|
|
3
|
+
import type { PlatformNode, RawFocus, RawKey, RawPointer, Unsubscribe } from './platform.ts';
|
|
4
|
+
export declare class InputHost {
|
|
5
|
+
#private;
|
|
6
|
+
/** True while the last pointer input came from a finger, which hits use to be more forgiving. */
|
|
7
|
+
coarse: boolean;
|
|
8
|
+
constructor(chart: Chart);
|
|
9
|
+
/** Listen to the chart's platform. Called by `inputOf`; a platform with no input of a kind simply gives none. */
|
|
10
|
+
start(): void;
|
|
11
|
+
/** Stop listening and forget everything held: `Chart.detach()` calls it. */
|
|
12
|
+
stop(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Ask for HOVER events (where the pointer is in a plane) for as long as the returned function has not been called.
|
|
15
|
+
* Elements outside the plane that follow the pointer (a tooltip) subscribe when they attach.
|
|
16
|
+
*/
|
|
17
|
+
watchPointer(element: AnyElement): Unsubscribe;
|
|
18
|
+
/**
|
|
19
|
+
* Ask for POINTER events in the chart's own pixels (not a plane's), for elements that are not in a plane and take
|
|
20
|
+
* input of their own: a legend's entries. Set `handled` on one to keep the planes from also acting on it. Returns the
|
|
21
|
+
* way to stop.
|
|
22
|
+
*/
|
|
23
|
+
watchInput(element: AnyElement): Unsubscribe;
|
|
24
|
+
/**
|
|
25
|
+
* Make a node reachable by keyboard: give it a `tabindex` (0 for a place in the tab order, -1 to be focusable by script
|
|
26
|
+
* only) and say which element it belongs to, which then gets its KEY and FOCUS events. Call again with the same node
|
|
27
|
+
* freely.
|
|
28
|
+
*/
|
|
29
|
+
focusable(element: AnyElement, node: PlatformNode): void;
|
|
30
|
+
/** Say something to a screen reader, if the platform has one to tell. */
|
|
31
|
+
speak(text: string): void;
|
|
32
|
+
/** Move keyboard focus to a node an element made `focusable`. Does nothing on a platform without focus. */
|
|
33
|
+
focus(node: PlatformNode): void;
|
|
34
|
+
/** One raw pointer: to what listens outside planes first, then to the plane it is over. True when something used it. */
|
|
35
|
+
route(p: RawPointer): boolean;
|
|
36
|
+
/** A key on a focused node, to the element that made the node focusable. */
|
|
37
|
+
routeKey(k: RawKey, node: PlatformNode): boolean;
|
|
38
|
+
/** Focus entering or leaving a node, to its owner. */
|
|
39
|
+
routeFocus(f: RawFocus): void;
|
|
40
|
+
}
|
|
41
|
+
/** The chart's input host, made and started on the first ask. Elements that take input call this as they attach. */
|
|
42
|
+
export declare function inputOf(chart: Chart): InputHost;
|