blazeplot 0.1.6 → 0.1.8

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.
Files changed (41) hide show
  1. package/README.md +36 -4
  2. package/dist/core/MinMaxPyramid.d.ts +4 -0
  3. package/dist/core/MinMaxPyramid.d.ts.map +1 -1
  4. package/dist/core/RingBuffer.d.ts +13 -0
  5. package/dist/core/RingBuffer.d.ts.map +1 -1
  6. package/dist/core/SeriesStore.d.ts +14 -1
  7. package/dist/core/SeriesStore.d.ts.map +1 -1
  8. package/dist/core/types.d.ts +19 -1
  9. package/dist/core/types.d.ts.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +824 -80
  13. package/dist/index.js.map +1 -1
  14. package/dist/plugins/legend.d.ts +3 -0
  15. package/dist/plugins/legend.d.ts.map +1 -0
  16. package/dist/plugins/legend.js +37 -0
  17. package/dist/plugins/legend.js.map +1 -0
  18. package/dist/plugins/tooltip.d.ts +3 -0
  19. package/dist/plugins/tooltip.d.ts.map +1 -0
  20. package/dist/plugins/tooltip.js +50 -0
  21. package/dist/plugins/tooltip.js.map +1 -0
  22. package/dist/render/ReglBackend.d.ts +2 -0
  23. package/dist/render/ReglBackend.d.ts.map +1 -1
  24. package/dist/render/Renderer.d.ts +22 -1
  25. package/dist/render/Renderer.d.ts.map +1 -1
  26. package/dist/render/ShaderPrograms.d.ts +16 -0
  27. package/dist/render/ShaderPrograms.d.ts.map +1 -1
  28. package/dist/render/index.d.ts +1 -1
  29. package/dist/render/index.d.ts.map +1 -1
  30. package/dist/render/types.d.ts +13 -2
  31. package/dist/render/types.d.ts.map +1 -1
  32. package/dist/ui/Chart.d.ts +99 -2
  33. package/dist/ui/Chart.d.ts.map +1 -1
  34. package/dist/ui/ChartLayout.d.ts.map +1 -1
  35. package/dist/ui/Legend.d.ts +7 -1
  36. package/dist/ui/Legend.d.ts.map +1 -1
  37. package/dist/ui/Tooltip.d.ts +11 -1
  38. package/dist/ui/Tooltip.d.ts.map +1 -1
  39. package/dist/ui/index.d.ts +5 -3
  40. package/dist/ui/index.d.ts.map +1 -1
  41. package/package.json +9 -1
package/dist/index.js CHANGED
@@ -81,6 +81,32 @@ var t = 16, n = class {
81
81
  let i = new Float32Array(n);
82
82
  r && i.set(r.subarray(0, Math.min(r.length, n))), this.levels[e] = i;
83
83
  }
84
+ rangeMinMax(e, t, n) {
85
+ let r = Math.max(0, Math.floor(t)), i = Math.min(e.length, Math.ceil(n));
86
+ if (i <= r) return null;
87
+ let a = Infinity, o = -Infinity, s = r;
88
+ for (; s < i;) {
89
+ let t = -1, n = 1;
90
+ for (let e = this.levels.length - 1; e >= 0; e--) {
91
+ let r = this.levelSampleWidths[e], a = Math.floor(s / r);
92
+ if (r > 0 && s % r === 0 && s + r <= i && a < this.levelLengths[e]) {
93
+ t = e, n = r;
94
+ break;
95
+ }
96
+ }
97
+ if (t >= 0) {
98
+ let e = Math.floor(s / n), r = this.levels[t], i = r[e * 2], c = r[e * 2 + 1];
99
+ i < a && (a = i), c > o && (o = c), s += n;
100
+ } else {
101
+ let t = e.getY(s);
102
+ t < a && (a = t), t > o && (o = t), s++;
103
+ }
104
+ }
105
+ return Number.isFinite(a) && Number.isFinite(o) ? {
106
+ minY: a,
107
+ maxY: o
108
+ } : null;
109
+ }
84
110
  query(e, t, n) {
85
111
  if (t <= 0 || n.length <= 0) return {
86
112
  buckets: new Float32Array(),
@@ -114,15 +140,24 @@ var t = 16, n = class {
114
140
  samplesPerPixel: i
115
141
  };
116
142
  }
117
- }, r = class {
143
+ };
144
+ //#endregion
145
+ //#region src/core/SeriesStore.ts
146
+ function r(e) {
147
+ return "rangeMinMaxY" in e;
148
+ }
149
+ var i = class {
118
150
  config;
119
151
  style;
120
152
  dataset;
121
153
  pyramid;
122
154
  _dirty = !1;
155
+ _useRawMinMaxScan = !1;
156
+ _lastBuildLength = 0;
157
+ _lastBuildRangeStart = NaN;
123
158
  _visible = !0;
124
159
  constructor(e, t, r) {
125
- this.dataset = e, this.config = t, this.pyramid = t.downsample === "none" ? null : new n(), this.style = r, this.pyramid && e.length > 0 && this.pyramid.build(e);
160
+ this.dataset = e, this.config = t, this.pyramid = (t.mode === "line" || t.mode === "bar") && t.downsample !== "none" ? new n() : null, this.style = r, this.pyramid && e.length > 0 && this.pyramid.build(e), this._lastBuildLength = e.length, this._lastBuildRangeStart = e.range?.start ?? NaN;
126
161
  }
127
162
  get hasLOD() {
128
163
  return this.pyramid !== null;
@@ -145,10 +180,16 @@ var t = 16, n = class {
145
180
  }
146
181
  clear() {
147
182
  if (!("clear" in this.dataset)) throw TypeError("SeriesStore dataset is not clearable.");
148
- this.dataset.clear(), this.pyramid && this.pyramid.build(this.dataset), this._dirty = !1;
183
+ this.dataset.clear(), this.pyramid && this.pyramid.build(this.dataset), this._useRawMinMaxScan = !1, this._lastBuildLength = this.dataset.length, this._lastBuildRangeStart = this.dataset.range?.start ?? NaN, this._dirty = !1;
149
184
  }
150
185
  rebuildPyramid() {
151
- this._dirty &&= (this.pyramid && this.pyramid.incrementalBuild(this.dataset), !1);
186
+ if (this._dirty) {
187
+ if (this.pyramid) {
188
+ let e = this.dataset.length, t = this.dataset.range?.start ?? NaN;
189
+ e === this._lastBuildLength && t !== this._lastBuildRangeStart ? this._useRawMinMaxScan = !0 : (this.pyramid.incrementalBuild(this.dataset), this._useRawMinMaxScan = !1), this._lastBuildLength = e, this._lastBuildRangeStart = t;
190
+ }
191
+ this._dirty = !1;
192
+ }
152
193
  }
153
194
  query(e, t) {
154
195
  if (!this.pyramid || !this.dataset.range) return {
@@ -167,39 +208,127 @@ var t = 16, n = class {
167
208
  let t = this.dataset.lowerBoundX(e.xMin), n = this.dataset.upperBoundX(e.xMax);
168
209
  return Math.max(0, n - t);
169
210
  }
211
+ sampleAt(e) {
212
+ return e < 0 || e >= this.dataset.length ? null : {
213
+ index: e,
214
+ x: this.dataset.getX(e),
215
+ y: this.dataset.getY(e)
216
+ };
217
+ }
218
+ nearestSampleByX(e, t) {
219
+ let n = this.visibleIndexRange(t);
220
+ if (n.start >= n.end) return null;
221
+ let r = this.dataset.lowerBoundX(e), i = Math.min(Math.max(r, n.start), n.end - 1), a = i - 1;
222
+ if (a >= n.start) {
223
+ let t = Math.abs(this.dataset.getX(i) - e);
224
+ Math.abs(this.dataset.getX(a) - e) <= t && (i = a);
225
+ }
226
+ return this.sampleAt(i);
227
+ }
228
+ nearestSampleByPoint(e, t, n, r, i) {
229
+ let a = this.visibleIndexRange(n);
230
+ if (a.start >= a.end || r <= 0 || i <= 0) return null;
231
+ let o = r / (n.xMax - n.xMin), s = i / (n.yMax - n.yMin), c = -1, l = Infinity;
232
+ for (let n = a.start; n < a.end; n++) {
233
+ let r = (this.dataset.getX(n) - e) * o, i = (this.dataset.getY(n) - t) * s, a = r * r + i * i;
234
+ a < l && (l = a, c = n);
235
+ }
236
+ if (c < 0) return null;
237
+ let u = this.sampleAt(c);
238
+ return u ? {
239
+ ...u,
240
+ distancePx: Math.sqrt(l)
241
+ } : null;
242
+ }
170
243
  copyRawVisible(e, t, n) {
171
- if (n <= 0 || t.length < n * 2) return 0;
172
- let r = this.dataset.lowerBoundX(e.xMin), i = this.dataset.upperBoundX(e.xMax), a = i - r;
173
- if (a <= 0) return 0;
174
- let o = Math.max(1, Math.ceil(a / n)), s = 0;
175
- for (let e = r; e < i && s < n; e += o) t[s * 2] = this.dataset.getX(e), t[s * 2 + 1] = this.dataset.getY(e), s++;
176
- return s;
244
+ return this.copyVisibleSamples(e, t, n, "points", 0);
245
+ }
246
+ copyAreaVisible(e, t, n, r = 0) {
247
+ return this.copyVisibleSamples(e, t, n, "area", r) * 2;
177
248
  }
178
249
  copyMinMaxVisible(e, t, n) {
179
- if (!this.pyramid || n <= 0 || t.length < n * 4) return 0;
180
- let r = this.dataset.lowerBoundX(e.xMin), i = this.dataset.upperBoundX(e.xMax), a = i - r;
181
- if (a <= 0) return 0;
182
- let o = Math.min(n, a), s = 0;
183
- for (let e = 0; e < o; e++) {
184
- let n = r + Math.floor(e * a / o), c = r + Math.max(Math.floor((e + 1) * a / o), Math.floor(e * a / o) + 1), l = Math.min(i, c), u = Infinity, d = -Infinity;
185
- for (let e = n; e < l; e++) {
186
- let t = this.dataset.getY(e);
187
- t < u && (u = t), t > d && (d = t);
250
+ return this.copyMinMaxSegments(e, t, n, "line-list") * 2;
251
+ }
252
+ copyMinMaxInstanced(e, t, n) {
253
+ return this.copyMinMaxSegments(e, t, n, "instanced");
254
+ }
255
+ visibleIndexRange(e) {
256
+ return e ? {
257
+ start: this.dataset.lowerBoundX(e.xMin),
258
+ end: this.dataset.upperBoundX(e.xMax)
259
+ } : {
260
+ start: 0,
261
+ end: this.dataset.length
262
+ };
263
+ }
264
+ copyVisibleSamples(e, t, n, r, i) {
265
+ let a = r === "points" ? 2 : 4;
266
+ if (n <= 0 || t.length < n * a) return 0;
267
+ let o = this.dataset.lowerBoundX(e.xMin), s = this.dataset.upperBoundX(e.xMax), c = s - o;
268
+ if (c <= 0) return 0;
269
+ let l = Math.max(1, Math.ceil(c / n)), u = 0;
270
+ for (let e = o; e < s && u < n; e += l) {
271
+ let n = this.dataset.getX(e), a = this.dataset.getY(e);
272
+ if (r === "points") {
273
+ let e = u * 2;
274
+ t[e] = n, t[e + 1] = a;
275
+ } else {
276
+ let e = u * 4;
277
+ t[e] = n, t[e + 1] = i, t[e + 2] = n, t[e + 3] = a;
278
+ }
279
+ u++;
280
+ }
281
+ return u;
282
+ }
283
+ copyMinMaxSegments(e, t, n, r) {
284
+ let i = r === "line-list" ? 4 : 3;
285
+ if (!this.pyramid || n <= 0 || t.length < n * i) return 0;
286
+ let a = this.dataset.lowerBoundX(e.xMin), o = this.dataset.upperBoundX(e.xMax), s = o - a;
287
+ if (s <= 0) return 0;
288
+ let c = Math.min(n, s);
289
+ for (let e = 0; e < c; e++) {
290
+ let n = a + Math.floor(e * s / c), i = a + Math.max(Math.floor((e + 1) * s / c), Math.floor(e * s / c) + 1), l = Math.min(o, i), u = this.minMaxForRange(n, l);
291
+ if (!u) continue;
292
+ let d = this.dataset.getX(n + (l - n >> 1)), { minY: f, maxY: p } = u;
293
+ if (r === "line-list") {
294
+ let n = e * 4;
295
+ t[n] = d, t[n + 1] = f, t[n + 2] = d, t[n + 3] = p;
296
+ } else {
297
+ let n = e * 3;
298
+ t[n] = d, t[n + 1] = f, t[n + 2] = p;
188
299
  }
189
- let f = this.dataset.getX(n + (l - n >> 1));
190
- t[s * 2] = f, t[s * 2 + 1] = u, s++, t[s * 2] = f, t[s * 2 + 1] = d, s++;
191
300
  }
192
- return s;
301
+ return c;
302
+ }
303
+ minMaxForRange(e, t) {
304
+ return !this.pyramid || this._useRawMinMaxScan ? this.rawMinMaxForRange(e, t) : this.pyramid.rangeMinMax(this.dataset, e, t);
305
+ }
306
+ rawMinMaxForRange(e, t) {
307
+ if (r(this.dataset)) return this.dataset.rangeMinMaxY(e, t);
308
+ let n = Math.max(0, Math.floor(e)), i = Math.min(this.dataset.length, Math.ceil(t));
309
+ if (i <= n) return null;
310
+ let a = Infinity, o = -Infinity;
311
+ for (let e = n; e < i; e++) {
312
+ let t = this.dataset.getY(e);
313
+ t < a && (a = t), t > o && (o = t);
314
+ }
315
+ return {
316
+ minY: a,
317
+ maxY: o
318
+ };
193
319
  }
194
- }, i = class {
320
+ }, a = class e {
195
321
  capacity;
196
322
  _length = 0;
197
323
  _head = 0;
198
324
  xData;
199
325
  yData;
200
- constructor(e) {
201
- if (!Number.isInteger(e) || e <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
202
- this.capacity = e, this.xData = new Float64Array(e), this.yData = new Float32Array(e);
326
+ treeBase;
327
+ minTree;
328
+ maxTree;
329
+ constructor(t) {
330
+ if (!Number.isInteger(t) || t <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
331
+ this.capacity = t, this.xData = new Float64Array(t), this.yData = new Float32Array(t), this.treeBase = e.nextPowerOfTwo(t), this.minTree = new Float32Array(this.treeBase * 2), this.maxTree = new Float32Array(this.treeBase * 2), this.minTree.fill(Infinity), this.maxTree.fill(-Infinity);
203
332
  }
204
333
  get length() {
205
334
  return this._length;
@@ -211,11 +340,21 @@ var t = 16, n = class {
211
340
  };
212
341
  }
213
342
  push(e, t) {
214
- this.xData[this._head] = e, this.yData[this._head] = t, this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
343
+ this.xData[this._head] = e, this.yData[this._head] = t, this.setTreeLeaf(this._head, t), this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
215
344
  }
216
345
  append(e, t) {
217
346
  let n = Math.min(e.length, t.length);
218
- for (let r = 0; r < n; r++) this.push(e[r], t[r]);
347
+ if (n <= 0) return;
348
+ if (n >= this.capacity) {
349
+ let r = n - this.capacity;
350
+ this._head = 0, this._length = this.capacity, this.copyIntoPhysical(0, e, t, r, this.capacity);
351
+ return;
352
+ }
353
+ let r = 0, i = n;
354
+ for (; i > 0;) {
355
+ let n = Math.min(i, this.capacity - this._head);
356
+ this.copyIntoPhysical(this._head, e, t, r, n), this._head = (this._head + n) % this.capacity, this._length = Math.min(this.capacity, this._length + n), r += n, i -= n;
357
+ }
219
358
  }
220
359
  get(e) {
221
360
  return e < 0 || e >= this._length ? null : {
@@ -245,8 +384,64 @@ var t = 16, n = class {
245
384
  }
246
385
  return t;
247
386
  }
387
+ rangeMinMaxY(e, t) {
388
+ let n = Math.max(0, Math.floor(e)), r = Math.min(this._length, Math.ceil(t));
389
+ if (r <= n) return null;
390
+ let i = this.logicalToPhysical(n), a = r - n;
391
+ if (i + a <= this.capacity) return this.queryPhysicalMinMax(i, i + a);
392
+ let o = this.queryPhysicalMinMax(i, this.capacity), s = this.queryPhysicalMinMax(0, (i + a) % this.capacity);
393
+ return o ? s ? {
394
+ minY: Math.min(o.minY, s.minY),
395
+ maxY: Math.max(o.maxY, s.maxY)
396
+ } : o : s;
397
+ }
248
398
  clear() {
249
- this._length = 0, this._head = 0;
399
+ this._length = 0, this._head = 0, this.minTree.fill(Infinity), this.maxTree.fill(-Infinity);
400
+ }
401
+ copyIntoPhysical(e, t, n, r, i) {
402
+ for (let a = 0; a < i; a++) {
403
+ let i = e + a, o = n[r + a];
404
+ this.xData[i] = t[r + a], this.yData[i] = o;
405
+ let s = this.treeBase + i;
406
+ this.minTree[s] = o, this.maxTree[s] = o;
407
+ }
408
+ this.recomputeTreeRange(e, e + i);
409
+ }
410
+ setTreeLeaf(e, t) {
411
+ let n = this.treeBase + e;
412
+ for (this.minTree[n] = t, this.maxTree[n] = t, n >>= 1; n >= 1;) this.recomputeTreeNode(n), n >>= 1;
413
+ }
414
+ recomputeTreeRange(e, t) {
415
+ let n = this.treeBase + e >> 1, r = this.treeBase + t - 1 >> 1;
416
+ for (; n >= 1;) {
417
+ for (let e = n; e <= r; e++) this.recomputeTreeNode(e);
418
+ if (n === 1) break;
419
+ n >>= 1, r >>= 1;
420
+ }
421
+ }
422
+ recomputeTreeNode(e) {
423
+ let t = e << 1, n = t + 1, r = this.minTree[t], i = this.minTree[n], a = this.maxTree[t], o = this.maxTree[n];
424
+ this.minTree[e] = r < i ? r : i, this.maxTree[e] = a > o ? a : o;
425
+ }
426
+ queryPhysicalMinMax(e, t) {
427
+ if (t <= e) return null;
428
+ let n = this.treeBase + e, r = this.treeBase + t, i = Infinity, a = -Infinity;
429
+ for (; n < r;) {
430
+ if (n & 1) {
431
+ let e = this.minTree[n], t = this.maxTree[n];
432
+ e < i && (i = e), t > a && (a = t), n++;
433
+ }
434
+ if (r & 1) {
435
+ r--;
436
+ let e = this.minTree[r], t = this.maxTree[r];
437
+ e < i && (i = e), t > a && (a = t);
438
+ }
439
+ n >>= 1, r >>= 1;
440
+ }
441
+ return Number.isFinite(i) && Number.isFinite(a) ? {
442
+ minY: i,
443
+ maxY: a
444
+ } : null;
250
445
  }
251
446
  logicalToPhysical(e) {
252
447
  return (this._head - this._length + e + this.capacity) % this.capacity;
@@ -254,22 +449,89 @@ var t = 16, n = class {
254
449
  assertValidIndex(e) {
255
450
  if (!Number.isInteger(e) || e < 0 || e >= this._length) throw RangeError(`RingBuffer index out of range: ${e}`);
256
451
  }
257
- }, a = {
452
+ static nextPowerOfTwo(e) {
453
+ return 2 ** Math.ceil(Math.log2(e));
454
+ }
455
+ }, o = "attribute vec2 position;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", s = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", c = "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\nattribute float aSelect;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n float y = (aSelect < 0.5) ? aMinY : aMaxY;\n vec2 position = vec2(aX, y);\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", l = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", u = "attribute vec2 aPosition;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform vec2 uCanvasSize;\nuniform float uPointSize;\n\nvoid main() {\n vec2 centerClip = aPosition * uScale + uOffset;\n vec2 pointSizeClip = vec2(2.0 / uCanvasSize.x, 2.0 / uCanvasSize.y) * uPointSize * 0.5;\n vec2 clipSpace = centerClip + aCorner * pointSizeClip;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", d = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", f = "attribute vec2 aPosition;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uPointSize;\n\nvoid main() {\n vec2 clipSpace = aPosition * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n gl_PointSize = uPointSize;\n}\n", p = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n vec2 p = gl_PointCoord * 2.0 - 1.0;\n if (dot(p, p) > 1.0) discard;\n gl_FragColor = uColor;\n}\n", m = "attribute vec2 aPosition;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uBarWidth;\nuniform float uBaseline;\n\nvoid main() {\n float x = aPosition.x + aCorner.x * uBarWidth;\n float y = mix(uBaseline, aPosition.y, aCorner.y);\n vec2 clipSpace = vec2(x, y) * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", h = "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\nattribute vec2 aCorner;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\nuniform float uBarWidth;\n\nvoid main() {\n float x = aX + aCorner.x * uBarWidth;\n float y = mix(aMinY, aMaxY, aCorner.y);\n vec2 clipSpace = vec2(x, y) * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n", g = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", _ = {
258
456
  line: {
259
- vert: "attribute vec2 position;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n",
260
- frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
457
+ vert: o,
458
+ frag: s
261
459
  },
262
460
  segment: {
263
- vert: "attribute float aX;\nattribute float aMinY;\nattribute float aMaxY;\n\nuniform vec2 uScale;\nuniform vec2 uOffset;\n\nvoid main() {\n float y = (gl_VertexID == 0) ? aMinY : aMaxY;\n vec2 position = vec2(aX, y);\n vec2 clipSpace = position * uScale + uOffset;\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n}\n",
264
- frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
461
+ vert: c,
462
+ frag: l
463
+ },
464
+ point: {
465
+ vert: u,
466
+ frag: d
467
+ },
468
+ pointSprite: {
469
+ vert: f,
470
+ frag: p
471
+ },
472
+ bar: {
473
+ vert: m,
474
+ frag: g
475
+ },
476
+ barRange: {
477
+ vert: h,
478
+ frag: g
265
479
  }
266
- }, o = class {
480
+ }, v = 3, y = 2, b = 4, x = 4, S = .8, C = 0, w = class {
267
481
  backend;
268
482
  lineProgram;
483
+ segmentProgram;
484
+ pointProgram;
485
+ pointSpriteProgram;
486
+ barProgram;
487
+ barRangeProgram;
488
+ segmentSelectBuffer;
489
+ pointCornerBuffer;
490
+ barCornerBuffer;
269
491
  scaleUniform = new Float32Array(2);
270
492
  offsetUniform = new Float32Array(2);
493
+ canvasSizeUniform = new Float32Array(2);
271
494
  constructor(e) {
272
- this.backend = e, this.lineProgram = this.backend.createProgram(a.line.vert, a.line.frag);
495
+ this.backend = e, this.lineProgram = this.backend.createProgram(_.line.vert, _.line.frag), this.segmentProgram = this.backend.createProgram(_.segment.vert, _.segment.frag), this.pointProgram = this.backend.createProgram(_.point.vert, _.point.frag), this.pointSpriteProgram = this.backend.createProgram(_.pointSprite.vert, _.pointSprite.frag), this.barProgram = this.backend.createProgram(_.bar.vert, _.bar.frag), this.barRangeProgram = this.backend.createProgram(_.barRange.vert, _.barRange.frag), this.segmentSelectBuffer = this.backend.createBuffer({
496
+ usage: "static",
497
+ type: "float",
498
+ length: 2
499
+ }), this.backend.updateBuffer(this.segmentSelectBuffer, new Float32Array([0, 1])), this.pointCornerBuffer = this.backend.createBuffer({
500
+ usage: "static",
501
+ type: "float",
502
+ length: 8
503
+ }), this.backend.updateBuffer(this.pointCornerBuffer, new Float32Array([
504
+ -1,
505
+ -1,
506
+ 1,
507
+ -1,
508
+ -1,
509
+ 1,
510
+ 1,
511
+ 1
512
+ ])), this.barCornerBuffer = this.backend.createBuffer({
513
+ usage: "static",
514
+ type: "float",
515
+ length: 8
516
+ }), this.backend.updateBuffer(this.barCornerBuffer, new Float32Array([
517
+ -.5,
518
+ 0,
519
+ .5,
520
+ 0,
521
+ -.5,
522
+ 1,
523
+ .5,
524
+ 1
525
+ ]));
526
+ }
527
+ get supportsInstancedSegments() {
528
+ return this.backend.capabilities.instancing;
529
+ }
530
+ get supportsInstancedPoints() {
531
+ return this.backend.capabilities.instancing;
532
+ }
533
+ get supportsInstancedBars() {
534
+ return this.backend.capabilities.instancing;
273
535
  }
274
536
  clear(e, t, n, r) {
275
537
  this.backend.clear(e, t, n, r);
@@ -293,8 +555,191 @@ var t = 16, n = class {
293
555
  drawLineStrip(e, t, n, r) {
294
556
  this.drawLinePrimitive("line_strip", e, t, n, r);
295
557
  }
558
+ drawMinMaxSegments(e, t, n, r) {
559
+ this.drawLines(e, t, n, r);
560
+ }
561
+ drawMinMaxSegmentsInstanced(e, t, n, r) {
562
+ this.writeCameraUniforms(r);
563
+ let i = v * b, a = {
564
+ buffer: e,
565
+ divisor: 1,
566
+ stride: i,
567
+ offset: 0
568
+ }, o = {
569
+ buffer: e,
570
+ divisor: 1,
571
+ stride: i,
572
+ offset: b
573
+ }, s = {
574
+ buffer: e,
575
+ divisor: 1,
576
+ stride: i,
577
+ offset: b * 2
578
+ }, c = {
579
+ buffer: this.segmentSelectBuffer,
580
+ divisor: 0,
581
+ stride: b,
582
+ offset: 0
583
+ };
584
+ this.backend.draw({
585
+ program: this.segmentProgram,
586
+ primitive: "lines",
587
+ count: 2,
588
+ instances: t,
589
+ attributes: {
590
+ aMaxY: s,
591
+ aMinY: o,
592
+ aSelect: c,
593
+ aX: a
594
+ },
595
+ uniforms: {
596
+ uScale: this.scaleUniform,
597
+ uOffset: this.offsetUniform,
598
+ uColor: n.color
599
+ }
600
+ });
601
+ }
602
+ drawPointsInstanced(e, t, n, r, i, a) {
603
+ this.writeCameraUniforms(r), this.canvasSizeUniform[0] = Math.max(1, i), this.canvasSizeUniform[1] = Math.max(1, a);
604
+ let o = {
605
+ buffer: e,
606
+ divisor: 1,
607
+ stride: y * b,
608
+ offset: 0,
609
+ size: 2
610
+ }, s = {
611
+ buffer: this.pointCornerBuffer,
612
+ divisor: 0,
613
+ stride: y * b,
614
+ offset: 0,
615
+ size: 2
616
+ };
617
+ this.backend.draw({
618
+ program: this.pointProgram,
619
+ primitive: "triangle_strip",
620
+ count: 4,
621
+ instances: t,
622
+ attributes: {
623
+ aCorner: s,
624
+ aPosition: o
625
+ },
626
+ uniforms: {
627
+ uScale: this.scaleUniform,
628
+ uOffset: this.offsetUniform,
629
+ uCanvasSize: this.canvasSizeUniform,
630
+ uPointSize: n.pointSize ?? x,
631
+ uColor: n.color
632
+ }
633
+ });
634
+ }
635
+ drawPointSprites(e, t, n, r) {
636
+ this.writeCameraUniforms(r), this.backend.draw({
637
+ program: this.pointSpriteProgram,
638
+ primitive: "points",
639
+ count: t,
640
+ attributes: { aPosition: e },
641
+ uniforms: {
642
+ uScale: this.scaleUniform,
643
+ uOffset: this.offsetUniform,
644
+ uPointSize: n.pointSize ?? x,
645
+ uColor: n.color
646
+ }
647
+ });
648
+ }
649
+ drawAreaStrip(e, t, n, r) {
650
+ this.writeCameraUniforms(r), this.backend.draw({
651
+ program: this.lineProgram,
652
+ primitive: "triangle_strip",
653
+ count: t,
654
+ attributes: { position: e },
655
+ uniforms: {
656
+ uScale: this.scaleUniform,
657
+ uOffset: this.offsetUniform,
658
+ uColor: n.fillColor ?? n.color
659
+ }
660
+ });
661
+ }
662
+ drawBarsInstanced(e, t, n, r) {
663
+ this.writeCameraUniforms(r);
664
+ let i = {
665
+ buffer: e,
666
+ divisor: 1,
667
+ stride: y * b,
668
+ offset: 0,
669
+ size: 2
670
+ }, a = {
671
+ buffer: this.barCornerBuffer,
672
+ divisor: 0,
673
+ stride: y * b,
674
+ offset: 0,
675
+ size: 2
676
+ };
677
+ this.backend.draw({
678
+ program: this.barProgram,
679
+ primitive: "triangle_strip",
680
+ count: 4,
681
+ instances: t,
682
+ attributes: {
683
+ aCorner: a,
684
+ aPosition: i
685
+ },
686
+ uniforms: {
687
+ uScale: this.scaleUniform,
688
+ uOffset: this.offsetUniform,
689
+ uBarWidth: n.barWidth ?? S,
690
+ uBaseline: n.baseline ?? C,
691
+ uColor: n.color
692
+ }
693
+ });
694
+ }
695
+ drawBarRangesInstanced(e, t, n, r) {
696
+ this.writeCameraUniforms(r);
697
+ let i = v * b, a = {
698
+ buffer: e,
699
+ divisor: 1,
700
+ stride: i,
701
+ offset: 0
702
+ }, o = {
703
+ buffer: e,
704
+ divisor: 1,
705
+ stride: i,
706
+ offset: b
707
+ }, s = {
708
+ buffer: e,
709
+ divisor: 1,
710
+ stride: i,
711
+ offset: b * 2
712
+ }, c = {
713
+ buffer: this.barCornerBuffer,
714
+ divisor: 0,
715
+ stride: y * b,
716
+ offset: 0,
717
+ size: 2
718
+ };
719
+ this.backend.draw({
720
+ program: this.barRangeProgram,
721
+ primitive: "triangle_strip",
722
+ count: 4,
723
+ instances: t,
724
+ attributes: {
725
+ aCorner: c,
726
+ aMaxY: s,
727
+ aMinY: o,
728
+ aX: a
729
+ },
730
+ uniforms: {
731
+ uScale: this.scaleUniform,
732
+ uOffset: this.offsetUniform,
733
+ uBarWidth: n.barWidth ?? S,
734
+ uColor: n.color
735
+ }
736
+ });
737
+ }
738
+ drawBarTriangles(e, t, n, r) {
739
+ this.drawTrianglePrimitive(e, t, n, r);
740
+ }
296
741
  drawLinePrimitive(e, t, n, r, i) {
297
- this.scaleUniform[0] = i.xScale, this.scaleUniform[1] = i.yScale, this.offsetUniform[0] = i.xOffset, this.offsetUniform[1] = i.yOffset, this.backend.draw({
742
+ this.writeCameraUniforms(i), this.backend.draw({
298
743
  program: this.lineProgram,
299
744
  primitive: e,
300
745
  count: n,
@@ -306,19 +751,32 @@ var t = 16, n = class {
306
751
  }
307
752
  });
308
753
  }
309
- drawMinMaxSegments(e, t, n, r) {
310
- this.drawLines(e, t, n, r);
754
+ drawTrianglePrimitive(e, t, n, r) {
755
+ this.writeCameraUniforms(r), this.backend.draw({
756
+ program: this.lineProgram,
757
+ primitive: "triangles",
758
+ count: t,
759
+ attributes: { position: e },
760
+ uniforms: {
761
+ uScale: this.scaleUniform,
762
+ uOffset: this.offsetUniform,
763
+ uColor: n.color
764
+ }
765
+ });
766
+ }
767
+ writeCameraUniforms(e) {
768
+ this.scaleUniform[0] = e.xScale, this.scaleUniform[1] = e.yScale, this.offsetUniform[0] = e.xOffset, this.offsetUniform[1] = e.yOffset;
311
769
  }
312
770
  dispose() {
313
771
  this.backend.destroy();
314
772
  }
315
- }, s = [
773
+ }, T = [
316
774
  1024,
317
775
  4096,
318
776
  16384,
319
777
  32768,
320
778
  131072
321
- ], c = class {
779
+ ], E = class {
322
780
  regl;
323
781
  pool = [];
324
782
  preAllocated = !1;
@@ -331,7 +789,7 @@ var t = 16, n = class {
331
789
  preAllocate() {
332
790
  if (!this.preAllocated) {
333
791
  this.preAllocated = !0;
334
- for (let e of s) this.pool.push(this.createEntry(e, "stream"));
792
+ for (let e of T) this.pool.push(this.createEntry(e, "stream"));
335
793
  }
336
794
  }
337
795
  acquire(e, t = "stream") {
@@ -371,23 +829,24 @@ var t = 16, n = class {
371
829
  return this.pool.find((t) => !t.inUse && t.floatCapacity >= e);
372
830
  }
373
831
  roundUp(e) {
374
- for (let t of s) if (t >= e) return t;
375
- let t = s[s.length - 1], n = 1 << 32 - Math.clz32(e - 1);
832
+ for (let t of T) if (t >= e) return t;
833
+ let t = T[T.length - 1], n = 1 << 32 - Math.clz32(e - 1);
376
834
  return Math.max(t * 2, n);
377
835
  }
378
836
  };
379
837
  //#endregion
380
838
  //#region src/render/ReglBackend.ts
381
- function l(e) {
839
+ function D(e) {
382
840
  return e;
383
841
  }
384
- var u = class {
842
+ var O = class {
385
843
  gl;
386
844
  regl;
387
845
  resources;
388
846
  nextProgramId = 1;
389
847
  commandCache = /* @__PURE__ */ new Map();
390
848
  scissorBox = null;
849
+ capabilities;
391
850
  constructor(t) {
392
851
  let n = t.getContext("webgl2", {
393
852
  alpha: !0,
@@ -400,10 +859,10 @@ var u = class {
400
859
  });
401
860
  if (!n) throw Error("BlazePlot requires WebGL2, but this browser/context does not support it.");
402
861
  this.gl = n, this.regl = e({
403
- gl: l(this.gl),
862
+ gl: D(this.gl),
404
863
  extensions: [],
405
- optionalExtensions: ["ext_disjoint_timer_query_webgl2"]
406
- }), this.resources = new c(this.regl), this.resources.preAllocate();
864
+ optionalExtensions: ["angle_instanced_arrays", "ext_disjoint_timer_query_webgl2"]
865
+ }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new E(this.regl), this.resources.preAllocate();
407
866
  }
408
867
  createBuffer(e) {
409
868
  let { buffer: t } = this.resources.acquire(e.length, e.usage);
@@ -436,7 +895,7 @@ var u = class {
436
895
  ].join("|"), a = this.commandCache.get(i);
437
896
  a || (a = this.createDrawCommand(t, e.primitive, n, r, e.instances !== void 0), this.commandCache.set(i, a));
438
897
  let o = {};
439
- for (let t of n) o[t] = this.asReglBuffer(e.attributes[t]).buffer;
898
+ for (let t of n) o[t] = this.resolveAttribute(e.attributes[t]);
440
899
  let s = {
441
900
  count: e.count,
442
901
  instances: e.instances ?? 0,
@@ -497,6 +956,15 @@ var u = class {
497
956
  }
498
957
  });
499
958
  }
959
+ resolveAttribute(e) {
960
+ return "divisor" in e ? {
961
+ buffer: this.asReglBuffer(e.buffer).buffer,
962
+ divisor: e.divisor,
963
+ stride: e.stride,
964
+ offset: e.offset,
965
+ size: e.size
966
+ } : this.asReglBuffer(e).buffer;
967
+ }
500
968
  asReglBuffer(e) {
501
969
  return e;
502
970
  }
@@ -513,7 +981,7 @@ var u = class {
513
981
  default: return e;
514
982
  }
515
983
  }
516
- }, d = class {
984
+ }, k = class {
517
985
  canvas;
518
986
  camera;
519
987
  policy;
@@ -567,7 +1035,7 @@ var u = class {
567
1035
  dispose() {
568
1036
  this.canvas.removeEventListener("pointerdown", this.onPointerDown), this.canvas.removeEventListener("pointermove", this.onPointerMove), this.canvas.removeEventListener("pointerup", this.onPointerUp), this.canvas.removeEventListener("pointercancel", this.onPointerUp), this.canvas.removeEventListener("wheel", this.onWheel);
569
1037
  }
570
- }, f = class e {
1038
+ }, A = class e {
571
1039
  _xMin = 0;
572
1040
  _xMax = 1;
573
1041
  _yMin = 0;
@@ -652,7 +1120,7 @@ var u = class {
652
1120
  static assertFinite(e, t) {
653
1121
  if (!Number.isFinite(t)) throw RangeError(`Camera2D ${e} must be finite.`);
654
1122
  }
655
- }, p = class {
1123
+ }, j = class {
656
1124
  camera;
657
1125
  constructor(e) {
658
1126
  this.camera = e;
@@ -684,7 +1152,7 @@ var u = class {
684
1152
  let n = Math.max(0, -Math.floor(Math.log10(t)) + 2), r = Number(e.toFixed(n));
685
1153
  return Object.is(r, -0) ? 0 : r;
686
1154
  }
687
- }, m = class {
1155
+ }, M = class {
688
1156
  layout;
689
1157
  config;
690
1158
  options;
@@ -726,7 +1194,7 @@ var u = class {
726
1194
  }
727
1195
  }
728
1196
  }
729
- }, h = class {
1197
+ }, N = class {
730
1198
  root;
731
1199
  plot;
732
1200
  canvas;
@@ -751,10 +1219,10 @@ var u = class {
751
1219
  this.externalCanvas ? this.originalCanvasParent?.insertBefore(this.root, e) : e.appendChild(this.root), this.root.appendChild(this.yAxis), this.root.appendChild(this.plot), this.root.appendChild(this.corner), this.root.appendChild(this.xAxis), this.plot.appendChild(this.canvas);
752
1220
  }
753
1221
  applyBaseStyles() {
754
- this.root.style.display = "grid", this.root.style.width = "100%", this.root.style.height = "100%", this.root.style.minWidth = "0", this.root.style.minHeight = "0", this.root.style.overflow = "hidden", this.plot.style.position = "relative", this.plot.style.gridColumn = "2", this.plot.style.gridRow = "1", this.plot.style.minWidth = "0", this.plot.style.minHeight = "0", this.plot.style.overflow = "hidden", this.canvas.style.position = "absolute", this.canvas.style.inset = "0", this.canvas.style.display = "block", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.touchAction = "none", this.yAxis.style.position = "relative", this.yAxis.style.gridColumn = "1", this.yAxis.style.gridRow = "1", this.yAxis.style.minWidth = "0", this.yAxis.style.minHeight = "0", this.yAxis.style.overflow = "hidden", this.yAxis.style.pointerEvents = "none", this.xAxis.style.position = "relative", this.xAxis.style.gridColumn = "2", this.xAxis.style.gridRow = "2", this.xAxis.style.minWidth = "0", this.xAxis.style.minHeight = "0", this.xAxis.style.overflow = "hidden", this.xAxis.style.pointerEvents = "none", this.corner.style.gridColumn = "1", this.corner.style.gridRow = "2", this.corner.style.minWidth = "0", this.corner.style.minHeight = "0", this.corner.style.pointerEvents = "none";
1222
+ this.root.style.position = "relative", this.root.style.display = "grid", this.root.style.width = "100%", this.root.style.height = "100%", this.root.style.minWidth = "0", this.root.style.minHeight = "0", this.root.style.overflow = "hidden", this.plot.style.position = "relative", this.plot.style.gridColumn = "2", this.plot.style.gridRow = "1", this.plot.style.minWidth = "0", this.plot.style.minHeight = "0", this.plot.style.overflow = "hidden", this.canvas.style.position = "absolute", this.canvas.style.inset = "0", this.canvas.style.display = "block", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.touchAction = "none", this.yAxis.style.position = "relative", this.yAxis.style.gridColumn = "1", this.yAxis.style.gridRow = "1", this.yAxis.style.minWidth = "0", this.yAxis.style.minHeight = "0", this.yAxis.style.overflow = "hidden", this.yAxis.style.pointerEvents = "none", this.xAxis.style.position = "relative", this.xAxis.style.gridColumn = "2", this.xAxis.style.gridRow = "2", this.xAxis.style.minWidth = "0", this.xAxis.style.minHeight = "0", this.xAxis.style.overflow = "hidden", this.xAxis.style.pointerEvents = "none", this.corner.style.gridColumn = "1", this.corner.style.gridRow = "2", this.corner.style.minWidth = "0", this.corner.style.minHeight = "0", this.corner.style.pointerEvents = "none";
755
1223
  }
756
- }, g = 16384, _ = 64;
757
- function v(e) {
1224
+ }, P = 16384, F = P >> 1, I = P >> 1, L = 3, R = 4096, z = 12, B = 64;
1225
+ function V(e) {
758
1226
  return e === !1 ? {
759
1227
  visible: !1,
760
1228
  position: "inside"
@@ -766,7 +1234,7 @@ function v(e) {
766
1234
  position: e.position ?? "inside"
767
1235
  };
768
1236
  }
769
- var y = class {
1237
+ var H = class {
770
1238
  options;
771
1239
  series = [];
772
1240
  camera;
@@ -775,6 +1243,10 @@ var y = class {
775
1243
  input;
776
1244
  rawLineBuffer;
777
1245
  rawLineData;
1246
+ minMaxInstanceBuffer;
1247
+ minMaxInstanceData;
1248
+ barTriangleBuffer;
1249
+ barTriangleData;
778
1250
  gridBuffer;
779
1251
  gridData;
780
1252
  gridStyle;
@@ -792,8 +1264,21 @@ var y = class {
792
1264
  renderMode: "none"
793
1265
  };
794
1266
  resizeObserver = null;
1267
+ pluginDisposers = [];
1268
+ hoverSubscribers = /* @__PURE__ */ new Set();
1269
+ seriesSubscribers = /* @__PURE__ */ new Set();
1270
+ currentHover = null;
1271
+ lastPointerClientX = 0;
1272
+ lastPointerClientY = 0;
1273
+ pointerInPlot = !1;
795
1274
  lastFrameAt = 0;
796
1275
  _rafId = 0;
1276
+ handlePointerMove = (e) => {
1277
+ this.pointerInPlot = !0, this.lastPointerClientX = e.clientX, this.lastPointerClientY = e.clientY, this.refreshHover();
1278
+ };
1279
+ handlePointerLeave = () => {
1280
+ this.pointerInPlot = !1, this.emitHover(null);
1281
+ };
797
1282
  constructor(e, t = {}) {
798
1283
  this.options = t;
799
1284
  let n = t.axes;
@@ -816,9 +1301,9 @@ var y = class {
816
1301
  position: "inside"
817
1302
  }
818
1303
  } : this.normalizedAxes = {
819
- x: v(n.x),
820
- y: v(n.y)
821
- }, this.layout = new h(e, this.normalizedAxes), this.applyCanvasSize(), this.camera = new f(), this.axis = new p(this.camera), this.renderer = new o(new u(this.layout.canvas)), this.input = new d(this.layout.canvas, this.camera, t.viewportPolicy), this.rawLineData = new Float32Array(g * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.gridData = new Float32Array(_ * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
1304
+ x: V(n.x),
1305
+ y: V(n.y)
1306
+ }, this.layout = new N(e, this.normalizedAxes), this.applyCanvasSize(), this.camera = new A(), this.axis = new j(this.camera), this.renderer = new w(new O(this.layout.canvas)), this.input = new k(this.layout.canvas, this.camera, t.viewportPolicy), this.rawLineData = new Float32Array(P * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.minMaxInstanceData = new Float32Array(I * L), this.minMaxInstanceBuffer = this.renderer.createFloatBuffer(this.minMaxInstanceData.length), this.barTriangleData = new Float32Array(R * z), this.barTriangleBuffer = this.renderer.createFloatBuffer(this.barTriangleData.length), this.gridData = new Float32Array(B * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
822
1307
  color: t.gridStyle?.color ?? [
823
1308
  .22,
824
1309
  .3,
@@ -826,26 +1311,87 @@ var y = class {
826
1311
  .45
827
1312
  ],
828
1313
  lineWidth: t.gridStyle?.lineWidth ?? 1
829
- }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new m(this.layout, this.normalizedAxes)), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.resize()), this.resizeObserver.observe(this.layout.plot));
1314
+ }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new M(this.layout, this.normalizedAxes)), this.canvas.addEventListener("pointermove", this.handlePointerMove), this.canvas.addEventListener("pointerleave", this.handlePointerLeave), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.resize()), this.resizeObserver.observe(this.layout.plot));
1315
+ for (let e of t.plugins ?? []) {
1316
+ let t = e.install(this);
1317
+ typeof t == "function" ? this.pluginDisposers.push(t) : t && this.pluginDisposers.push(() => t.dispose());
1318
+ }
830
1319
  }
831
1320
  get canvas() {
832
1321
  return this.layout.canvas;
833
1322
  }
1323
+ get rootElement() {
1324
+ return this.layout.root;
1325
+ }
1326
+ get plotElement() {
1327
+ return this.layout.plot;
1328
+ }
1329
+ dataToPlot(e, t) {
1330
+ let [n, r] = this.camera.toClip(e, t);
1331
+ return this.camera.toScreen(n, r, this.canvas.clientWidth, this.canvas.clientHeight);
1332
+ }
834
1333
  addSeries(e, t) {
835
- let n = new r(e.dataset ?? new i(e.capacity), e, {
836
- color: t?.color ?? [
837
- .3,
838
- .6,
839
- 1,
840
- 1
841
- ],
842
- lineWidth: t?.lineWidth ?? 1
1334
+ let n = e.dataset ?? new a(e.capacity), r = t?.color ?? [
1335
+ .3,
1336
+ .6,
1337
+ 1,
1338
+ 1
1339
+ ], o = new i(n, e, {
1340
+ color: r,
1341
+ lineWidth: t?.lineWidth ?? 1,
1342
+ pointSize: t?.pointSize ?? 4,
1343
+ barWidth: t?.barWidth ?? .8,
1344
+ baseline: t?.baseline ?? 0,
1345
+ fillColor: t?.fillColor ?? [
1346
+ r[0],
1347
+ r[1],
1348
+ r[2],
1349
+ r[3] * .25
1350
+ ]
843
1351
  });
844
- return this.series.push(n), n;
1352
+ return this.series.push(o), this.emitSeriesChange(), o;
1353
+ }
1354
+ addLine(e, t) {
1355
+ return this.addSeries({
1356
+ ...e,
1357
+ mode: "line"
1358
+ }, t);
1359
+ }
1360
+ addArea(e, t) {
1361
+ return this.addSeries({
1362
+ ...e,
1363
+ mode: "area"
1364
+ }, t);
1365
+ }
1366
+ addScatter(e, t) {
1367
+ return this.addSeries({
1368
+ ...e,
1369
+ mode: "scatter"
1370
+ }, t);
1371
+ }
1372
+ addBar(e, t) {
1373
+ return this.addSeries({
1374
+ ...e,
1375
+ mode: "bar"
1376
+ }, t);
845
1377
  }
846
1378
  removeSeries(e) {
847
1379
  let t = this.series.indexOf(e);
848
- return t === -1 ? !1 : (this.series.splice(t, 1), !0);
1380
+ return t === -1 ? !1 : (this.series.splice(t, 1), this.emitSeriesChange(), !0);
1381
+ }
1382
+ setSeriesVisible(e, t) {
1383
+ return this.series.includes(e) ? e.visible === t ? !0 : (e.setVisible(t), this.emitSeriesChange(), !0) : !1;
1384
+ }
1385
+ getSeriesState() {
1386
+ return this.series.map((e, t) => ({
1387
+ series: e,
1388
+ index: t,
1389
+ id: e.config.id,
1390
+ name: e.config.name,
1391
+ mode: e.config.mode,
1392
+ visible: e.visible,
1393
+ color: e.style.color
1394
+ }));
849
1395
  }
850
1396
  setViewport(e) {
851
1397
  this.camera.setViewport(e);
@@ -863,6 +1409,45 @@ var y = class {
863
1409
  }) {
864
1410
  return e.fps = this.stats.fps, e.frameMs = this.stats.frameMs, e.pointsRendered = this.stats.pointsRendered, e.drawCalls = this.stats.drawCalls, e.uploadBytes = this.stats.uploadBytes, e.renderMode = this.stats.renderMode, e;
865
1411
  }
1412
+ getHoverState() {
1413
+ return this.currentHover;
1414
+ }
1415
+ subscribe(e, t) {
1416
+ if (e === "hover") {
1417
+ let e = t;
1418
+ return this.hoverSubscribers.add(e), () => this.hoverSubscribers.delete(e);
1419
+ }
1420
+ let n = t;
1421
+ return this.seriesSubscribers.add(n), () => this.seriesSubscribers.delete(n);
1422
+ }
1423
+ pick(e, t, n = {}) {
1424
+ let r = this.canvas.getBoundingClientRect();
1425
+ if (r.width <= 0 || r.height <= 0) return null;
1426
+ let i = e - r.left, a = t - r.top;
1427
+ if (i < 0 || a < 0 || i > r.width || a > r.height) return null;
1428
+ let o = this.camera.viewport, s = o.xMin + i / r.width * (o.xMax - o.xMin), c = o.yMax - a / r.height * (o.yMax - o.yMin), l = n.mode ?? this.options.hover?.mode ?? "nearest-x", u = n.maxDistancePx ?? this.options.hover?.maxDistancePx ?? Infinity, d = l === "nearest-point" ? this.findNearestPointAnchor(s, c, o, r.width, r.height, u) : this.findNearestXAnchor(s, o, r.width, u);
1429
+ return d === null ? null : {
1430
+ clientX: e,
1431
+ clientY: t,
1432
+ plotX: i,
1433
+ plotY: a,
1434
+ dataX: s,
1435
+ dataY: c,
1436
+ anchorX: d,
1437
+ mode: l,
1438
+ items: this.collectPickItems(d, e, t, o, r)
1439
+ };
1440
+ }
1441
+ async screenshot(e = {}) {
1442
+ this.render();
1443
+ let t = this.layout.root.getBoundingClientRect(), n = this.layout.plot.getBoundingClientRect(), r = Number.isFinite(e.dpr) ? Math.max(1, e.dpr) : Math.max(1, globalThis.devicePixelRatio || 1), i = Math.max(1, Math.round(t.width * r)), a = Math.max(1, Math.round(t.height * r)), o = document.createElement("canvas");
1444
+ o.width = i, o.height = a;
1445
+ let s = o.getContext("2d");
1446
+ if (!s) throw Error("Unable to create a 2D canvas context for screenshot export.");
1447
+ return e.background ? (s.fillStyle = e.background, s.fillRect(0, 0, i, a)) : s.clearRect(0, 0, i, a), s.drawImage(this.canvas, (n.left - t.left) * r, (n.top - t.top) * r, n.width * r, n.height * r), this.drawDomTextForScreenshot(s, t, r), new Promise((t, n) => {
1448
+ o.toBlob((e) => e ? t(e) : n(/* @__PURE__ */ Error("Unable to encode chart screenshot.")), e.type ?? "image/png", e.quality);
1449
+ });
1450
+ }
866
1451
  start() {
867
1452
  let e = () => {
868
1453
  this._rafId = requestAnimationFrame(e), this.render();
@@ -882,28 +1467,187 @@ var y = class {
882
1467
  }
883
1468
  for (let e of this.series) {
884
1469
  if (!e.visible) continue;
885
- let n = e.visibleSampleCount(t), r = e.hasLOD && n > g, i = r ? e.copyMinMaxVisible(t, this.rawLineData, Math.min(this.canvas.width, g >> 1)) : e.copyRawVisible(t, this.rawLineData, g);
1470
+ if (e.rebuildPyramid(), e.config.mode === "scatter") {
1471
+ this.drawScatterSeries(e, t);
1472
+ continue;
1473
+ }
1474
+ if (e.config.mode === "bar") {
1475
+ this.drawBarSeries(e, t);
1476
+ continue;
1477
+ }
1478
+ if (e.config.mode === "area") {
1479
+ this.drawAreaSeries(e, t);
1480
+ continue;
1481
+ }
1482
+ let n = e.visibleSampleCount(t), r = e.hasLOD && n > P;
1483
+ if (r && this.renderer.supportsInstancedSegments) {
1484
+ let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxMinMaxSegments());
1485
+ if (n <= 0) continue;
1486
+ this.renderer.updateFloatBuffer(this.minMaxInstanceBuffer, this.minMaxInstanceData), this.renderer.drawMinMaxSegmentsInstanced(this.minMaxInstanceBuffer, n, e.style, this.camera), this.recordRenderMode("minmax"), this.stats.pointsRendered += n * 2, this.stats.drawCalls++, this.stats.uploadBytes += this.minMaxInstanceData.byteLength;
1487
+ continue;
1488
+ }
1489
+ let i = r ? e.copyMinMaxVisible(t, this.rawLineData, this.maxMinMaxSegments()) : e.copyRawVisible(t, this.rawLineData, P);
886
1490
  i < 2 || (this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), r ? (this.renderer.drawMinMaxSegments(this.rawLineBuffer, i, e.style, this.camera), this.recordRenderMode("minmax")) : (this.renderer.drawLineStrip(this.rawLineBuffer, i, e.style, this.camera), this.recordRenderMode("raw")), this.stats.pointsRendered += i, this.stats.drawCalls++, this.stats.uploadBytes += this.rawLineData.byteLength);
887
1491
  }
888
- this.axisOverlay?.update(this.camera, this.axis), this.stats.frameMs = performance.now() - e;
1492
+ this.axisOverlay?.update(this.camera, this.axis), this.stats.frameMs = performance.now() - e, this.refreshHover();
889
1493
  }
890
1494
  dispose() {
891
- this.stop(), this.resizeObserver?.disconnect(), this.input.dispose(), this.axisOverlay?.dispose(), this.renderer.dispose(), this.layout.dispose();
1495
+ this.stop(), this.resizeObserver?.disconnect(), this.canvas.removeEventListener("pointermove", this.handlePointerMove), this.canvas.removeEventListener("pointerleave", this.handlePointerLeave);
1496
+ for (let e of this.pluginDisposers.splice(0)) e();
1497
+ this.input.dispose(), this.axisOverlay?.dispose(), this.renderer.dispose(), this.layout.dispose();
892
1498
  }
893
1499
  applyCanvasSize(e = globalThis.devicePixelRatio) {
894
1500
  let t = Number.isFinite(e) ? Math.max(1, e) : 1, n = Math.max(1, Math.floor(this.canvas.clientWidth * t)), r = Math.max(1, Math.floor(this.canvas.clientHeight * t));
895
1501
  return this.canvas.width === n && this.canvas.height === r ? !1 : (this.canvas.width = n, this.canvas.height = r, !0);
896
1502
  }
1503
+ drawAreaSeries(e, t) {
1504
+ let n = e.style.baseline ?? 0, r = e.copyAreaVisible(t, this.rawLineData, F, n);
1505
+ if (r < 4) return;
1506
+ this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), this.renderer.drawAreaStrip(this.rawLineBuffer, r, e.style, this.camera), this.stats.pointsRendered += r, this.stats.drawCalls++, this.stats.uploadBytes += this.rawLineData.byteLength;
1507
+ let i = this.uploadRawInstances(e, t, F);
1508
+ i >= 2 && (this.renderer.drawLineStrip(this.rawLineBuffer, i, e.style, this.camera), this.stats.pointsRendered += i, this.stats.drawCalls++), this.recordRenderMode("area");
1509
+ }
1510
+ drawScatterSeries(e, t) {
1511
+ let n = this.uploadRawInstances(e, t, P);
1512
+ n <= 0 || (this.renderer.supportsInstancedPoints ? this.renderer.drawPointsInstanced(this.rawLineBuffer, n, e.style, this.camera, this.canvas.width, this.canvas.height) : this.renderer.drawPointSprites(this.rawLineBuffer, n, e.style, this.camera), this.recordInstancedDraw("points", n));
1513
+ }
1514
+ drawBarSeries(e, t) {
1515
+ let n = e.visibleSampleCount(t);
1516
+ if (e.hasLOD && n > P) {
1517
+ let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxBarFallbackBars());
1518
+ if (n <= 0) return;
1519
+ this.includeBaselineInBarRanges(n, e.style.baseline ?? 0);
1520
+ let r = this.writeBarBucketTriangles(n, t);
1521
+ this.drawBarTriangleFallback(r, e.style);
1522
+ return;
1523
+ }
1524
+ let r = this.uploadRawInstances(e, t, this.maxBarFallbackBars());
1525
+ if (r <= 0) return;
1526
+ if (this.renderer.supportsInstancedBars) {
1527
+ this.renderer.drawBarsInstanced(this.rawLineBuffer, r, e.style, this.camera), this.recordInstancedDraw("bars", r);
1528
+ return;
1529
+ }
1530
+ let i = this.writeBarTriangles(r, e.style.baseline ?? 0, e.style.barWidth ?? .8);
1531
+ this.drawBarTriangleFallback(i, e.style);
1532
+ }
1533
+ uploadRawInstances(e, t, n) {
1534
+ let r = e.copyRawVisible(t, this.rawLineData, n);
1535
+ return r <= 0 ? 0 : (this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), this.stats.uploadBytes += this.rawLineData.byteLength, r);
1536
+ }
1537
+ includeBaselineInBarRanges(e, t) {
1538
+ for (let n = 0; n < e; n++) {
1539
+ let e = n * L, r = this.minMaxInstanceData[e + 1], i = this.minMaxInstanceData[e + 2];
1540
+ this.minMaxInstanceData[e + 1] = Math.min(t, r), this.minMaxInstanceData[e + 2] = Math.max(t, i);
1541
+ }
1542
+ }
1543
+ writeBarTriangles(e, t, n) {
1544
+ let r = Math.min(e, this.maxBarFallbackBars());
1545
+ for (let e = 0; e < r; e++) {
1546
+ let r = this.rawLineData[e * 2], i = this.rawLineData[e * 2 + 1];
1547
+ this.writeBarTriangle(e, r - n * .5, r + n * .5, t, i);
1548
+ }
1549
+ return r * 6;
1550
+ }
1551
+ writeBarBucketTriangles(e, t) {
1552
+ let n = Math.min(e, this.maxBarFallbackBars()), r = (t.xMax - t.xMin) / Math.max(1, n);
1553
+ for (let e = 0; e < n; e++) {
1554
+ let i = this.minMaxInstanceData[e * 3 + 1], a = this.minMaxInstanceData[e * 3 + 2], o = t.xMin + e * r, s = e === n - 1 ? t.xMax : o + r;
1555
+ this.writeBarTriangle(e, o, s, i, a);
1556
+ }
1557
+ return n * 6;
1558
+ }
1559
+ writeBarTriangle(e, t, n, r, i) {
1560
+ let a = e * z;
1561
+ this.barTriangleData[a] = t, this.barTriangleData[a + 1] = r, this.barTriangleData[a + 2] = n, this.barTriangleData[a + 3] = r, this.barTriangleData[a + 4] = t, this.barTriangleData[a + 5] = i, this.barTriangleData[a + 6] = t, this.barTriangleData[a + 7] = i, this.barTriangleData[a + 8] = n, this.barTriangleData[a + 9] = r, this.barTriangleData[a + 10] = n, this.barTriangleData[a + 11] = i;
1562
+ }
1563
+ drawBarTriangleFallback(e, t) {
1564
+ e <= 0 || (this.renderer.updateFloatBuffer(this.barTriangleBuffer, this.barTriangleData), this.stats.uploadBytes += this.barTriangleData.byteLength, this.renderer.drawBarTriangles(this.barTriangleBuffer, e, t, this.camera), this.recordInstancedDraw("bars", e));
1565
+ }
1566
+ recordInstancedDraw(e, t) {
1567
+ this.recordRenderMode(e), this.stats.pointsRendered += t, this.stats.drawCalls++;
1568
+ }
1569
+ findNearestXAnchor(e, t, n, r) {
1570
+ let i = null, a = Infinity, o = n / (t.xMax - t.xMin);
1571
+ for (let n of this.series) {
1572
+ if (!n.visible) continue;
1573
+ let r = n.nearestSampleByX(e, t);
1574
+ if (!r) continue;
1575
+ let s = Math.abs(r.x - e) * o;
1576
+ s < a && (i = r, a = s);
1577
+ }
1578
+ return !i || a > r ? null : i.x;
1579
+ }
1580
+ findNearestPointAnchor(e, t, n, r, i, a) {
1581
+ let o = null;
1582
+ for (let a of this.series) {
1583
+ if (!a.visible) continue;
1584
+ let s = a.nearestSampleByPoint(e, t, n, r, i);
1585
+ s && (!o || (s.distancePx ?? Infinity) < (o.distancePx ?? Infinity)) && (o = s);
1586
+ }
1587
+ return !o || (o.distancePx ?? Infinity) > a ? null : o.x;
1588
+ }
1589
+ collectPickItems(e, t, n, r, i) {
1590
+ let a = [];
1591
+ for (let o = 0; o < this.series.length; o++) {
1592
+ let s = this.series[o];
1593
+ if (!s.visible) continue;
1594
+ let c = s.nearestSampleByX(e, r);
1595
+ if (!c) continue;
1596
+ let [l, u] = this.camera.toClip(c.x, c.y), [d, f] = this.camera.toScreen(l, u, i.width, i.height), p = i.left + d, m = i.top + f, h = p - t, g = m - n;
1597
+ a.push({
1598
+ ...c,
1599
+ distancePx: Math.hypot(h, g),
1600
+ series: s,
1601
+ seriesIndex: o,
1602
+ id: s.config.id,
1603
+ name: s.config.name,
1604
+ mode: s.config.mode,
1605
+ plotX: d,
1606
+ plotY: f,
1607
+ clientX: p,
1608
+ clientY: m
1609
+ });
1610
+ }
1611
+ return a;
1612
+ }
1613
+ refreshHover() {
1614
+ this.pointerInPlot && this.emitHover(this.pick(this.lastPointerClientX, this.lastPointerClientY));
1615
+ }
1616
+ emitHover(e) {
1617
+ this.currentHover = e;
1618
+ for (let t of this.hoverSubscribers) t(e);
1619
+ }
1620
+ emitSeriesChange() {
1621
+ for (let e of this.seriesSubscribers) e();
1622
+ this.refreshHover();
1623
+ }
1624
+ drawDomTextForScreenshot(e, t, n) {
1625
+ let r = this.layout.root.querySelectorAll("div");
1626
+ for (let i of r) {
1627
+ let r = i.textContent;
1628
+ if (!r || i.children.length > 0) continue;
1629
+ let a = getComputedStyle(i);
1630
+ if (a.display === "none" || a.visibility === "hidden" || a.opacity === "0") continue;
1631
+ let o = i.getBoundingClientRect();
1632
+ o.width <= 0 || o.height <= 0 || (e.save(), e.scale(n, n), e.font = a.font, e.fillStyle = a.color, e.textBaseline = "top", e.textAlign = "left", e.fillText(r, o.left - t.left, o.top - t.top), e.restore());
1633
+ }
1634
+ }
1635
+ maxMinMaxSegments() {
1636
+ return Math.min(this.canvas.width, I);
1637
+ }
1638
+ maxBarFallbackBars() {
1639
+ return Math.min(R, P);
1640
+ }
897
1641
  writeGridVertices(e) {
898
1642
  let t = Math.max(1, this.canvas.clientWidth), n = Math.max(1, this.canvas.clientHeight);
899
1643
  this.axis.getXTickValues(t, 12, this.xTicks), this.axis.getYTickValues(n, 8, this.yTicks);
900
1644
  let r = 0;
901
1645
  for (let t of this.xTicks) {
902
- if (r + 2 > _) return r;
1646
+ if (r + 2 > B) return r;
903
1647
  this.gridData[r * 2] = t, this.gridData[r * 2 + 1] = e.yMin, r++, this.gridData[r * 2] = t, this.gridData[r * 2 + 1] = e.yMax, r++;
904
1648
  }
905
1649
  for (let t of this.yTicks) {
906
- if (r + 2 > _) return r;
1650
+ if (r + 2 > B) return r;
907
1651
  this.gridData[r * 2] = e.xMin, this.gridData[r * 2 + 1] = t, r++, this.gridData[r * 2] = e.xMax, this.gridData[r * 2 + 1] = t, r++;
908
1652
  }
909
1653
  return r;
@@ -911,7 +1655,7 @@ var y = class {
911
1655
  recordRenderMode(e) {
912
1656
  this.stats.renderMode === "none" ? this.stats.renderMode = e : this.stats.renderMode !== e && (this.stats.renderMode = "mixed");
913
1657
  }
914
- }, b = class {
1658
+ }, U = class {
915
1659
  xData;
916
1660
  yData;
917
1661
  constructor(e, t) {
@@ -953,6 +1697,6 @@ var y = class {
953
1697
  }
954
1698
  };
955
1699
  //#endregion
956
- export { p as AxisController, f as Camera2D, y as Chart, n as MinMaxPyramid, i as RingBuffer, r as SeriesStore, b as StaticDataset };
1700
+ export { j as AxisController, A as Camera2D, H as Chart, n as MinMaxPyramid, a as RingBuffer, i as SeriesStore, U as StaticDataset };
957
1701
 
958
1702
  //# sourceMappingURL=index.js.map