blazeplot 0.1.7 → 0.1.9

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/dist/index.js CHANGED
@@ -78,8 +78,37 @@ var t = 16, n = class {
78
78
  ensureLevelData(e, t) {
79
79
  let n = t * 2, r = this.levels[e];
80
80
  if (r && r.length >= n) return;
81
- let i = new Float32Array(n);
82
- r && i.set(r.subarray(0, Math.min(r.length, n))), this.levels[e] = i;
81
+ let i = r?.length ?? 0;
82
+ if (i <= 0) i = n;
83
+ else for (; i < n;) i = Math.max(n, Math.ceil(i * 1.5));
84
+ let a = new Float32Array(i);
85
+ r && a.set(r), this.levels[e] = a;
86
+ }
87
+ rangeMinMax(e, t, n) {
88
+ let r = Math.max(0, Math.floor(t)), i = Math.min(e.length, Math.ceil(n));
89
+ if (i <= r) return null;
90
+ let a = Infinity, o = -Infinity, s = r;
91
+ for (; s < i;) {
92
+ let t = -1, n = 1;
93
+ for (let e = this.levels.length - 1; e >= 0; e--) {
94
+ let r = this.levelSampleWidths[e], a = Math.floor(s / r);
95
+ if (r > 0 && s % r === 0 && s + r <= i && a < this.levelLengths[e]) {
96
+ t = e, n = r;
97
+ break;
98
+ }
99
+ }
100
+ if (t >= 0) {
101
+ let e = Math.floor(s / n), r = this.levels[t], i = r[e * 2], c = r[e * 2 + 1];
102
+ i < a && (a = i), c > o && (o = c), s += n;
103
+ } else {
104
+ let t = e.getY(s);
105
+ t < a && (a = t), t > o && (o = t), s++;
106
+ }
107
+ }
108
+ return Number.isFinite(a) && Number.isFinite(o) ? {
109
+ minY: a,
110
+ maxY: o
111
+ } : null;
83
112
  }
84
113
  query(e, t, n) {
85
114
  if (t <= 0 || n.length <= 0) return {
@@ -114,15 +143,25 @@ var t = 16, n = class {
114
143
  samplesPerPixel: i
115
144
  };
116
145
  }
117
- }, r = class {
146
+ };
147
+ //#endregion
148
+ //#region src/core/SeriesStore.ts
149
+ function r(e) {
150
+ return "rangeMinMaxY" in e;
151
+ }
152
+ var i = class {
118
153
  config;
119
154
  style;
120
155
  dataset;
121
156
  pyramid;
122
157
  _dirty = !1;
158
+ _useDatasetRangeMinMax = !1;
159
+ _useRawMinMaxScan = !1;
160
+ _lastBuildLength = 0;
161
+ _lastBuildRangeStart = NaN;
123
162
  _visible = !0;
124
- constructor(e, t, r) {
125
- this.dataset = e, this.config = t, this.pyramid = t.mode === "line" && t.downsample !== "none" ? new n() : null, this.style = r, this.pyramid && e.length > 0 && this.pyramid.build(e);
163
+ constructor(e, t, i) {
164
+ this.dataset = e, this.config = t, this.pyramid = (t.mode === "line" || t.mode === "bar") && t.downsample !== "none" ? new n() : null, this._useDatasetRangeMinMax = r(e), this.style = i, this.pyramid && e.length > 0 && !this._useDatasetRangeMinMax && this.pyramid.build(e), this._lastBuildLength = e.length, this._lastBuildRangeStart = e.range?.start ?? NaN;
126
165
  }
127
166
  get hasLOD() {
128
167
  return this.pyramid !== null;
@@ -145,10 +184,16 @@ var t = 16, n = class {
145
184
  }
146
185
  clear() {
147
186
  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;
187
+ this.dataset.clear(), this._useDatasetRangeMinMax = r(this.dataset), this._useRawMinMaxScan = !1, this.pyramid && !this._useDatasetRangeMinMax && this.pyramid.build(this.dataset), this._lastBuildLength = this.dataset.length, this._lastBuildRangeStart = this.dataset.range?.start ?? NaN, this._dirty = !1;
149
188
  }
150
189
  rebuildPyramid() {
151
- this._dirty &&= (this.pyramid && this.pyramid.incrementalBuild(this.dataset), !1);
190
+ if (this._dirty) {
191
+ if (this.pyramid) {
192
+ let e = this.dataset.length, t = this.dataset.range?.start ?? NaN, n = e === this._lastBuildLength && t !== this._lastBuildRangeStart;
193
+ r(this.dataset) ? (this._useDatasetRangeMinMax = !0, this._useRawMinMaxScan = !1) : n ? (this._useDatasetRangeMinMax = !1, this._useRawMinMaxScan = !0) : (this.pyramid.incrementalBuild(this.dataset), this._useDatasetRangeMinMax = !1, this._useRawMinMaxScan = !1), this._lastBuildLength = e, this._lastBuildRangeStart = t;
194
+ }
195
+ this._dirty = !1;
196
+ }
152
197
  }
153
198
  query(e, t) {
154
199
  if (!this.pyramid || !this.dataset.range) return {
@@ -157,16 +202,48 @@ var t = 16, n = class {
157
202
  level: 0,
158
203
  samplesPerPixel: 0
159
204
  };
160
- let n = this.dataset.lowerBoundX(e.xMin), r = this.dataset.upperBoundX(e.xMax);
161
- return this.pyramid.query(e, t, {
205
+ let n = this.dataset.lowerBoundX(e.xMin), r = this.dataset.upperBoundX(e.xMax), i = Math.max(0, r - n);
206
+ return this._useDatasetRangeMinMax ? this.queryRangeMinMax(n, i, t) : this.pyramid.query(e, t, {
162
207
  start: n,
163
- length: Math.max(0, r - n)
208
+ length: i
164
209
  });
165
210
  }
166
211
  visibleSampleCount(e) {
167
212
  let t = this.dataset.lowerBoundX(e.xMin), n = this.dataset.upperBoundX(e.xMax);
168
213
  return Math.max(0, n - t);
169
214
  }
215
+ sampleAt(e) {
216
+ return e < 0 || e >= this.dataset.length ? null : {
217
+ index: e,
218
+ x: this.dataset.getX(e),
219
+ y: this.dataset.getY(e)
220
+ };
221
+ }
222
+ nearestSampleByX(e, t) {
223
+ let n = this.visibleIndexRange(t);
224
+ if (n.start >= n.end) return null;
225
+ let r = this.dataset.lowerBoundX(e), i = Math.min(Math.max(r, n.start), n.end - 1), a = i - 1;
226
+ if (a >= n.start) {
227
+ let t = Math.abs(this.dataset.getX(i) - e);
228
+ Math.abs(this.dataset.getX(a) - e) <= t && (i = a);
229
+ }
230
+ return this.sampleAt(i);
231
+ }
232
+ nearestSampleByPoint(e, t, n, r, i) {
233
+ let a = this.visibleIndexRange(n);
234
+ if (a.start >= a.end || r <= 0 || i <= 0) return null;
235
+ let o = r / (n.xMax - n.xMin), s = i / (n.yMax - n.yMin), c = -1, l = Infinity;
236
+ for (let n = a.start; n < a.end; n++) {
237
+ let r = (this.dataset.getX(n) - e) * o, i = (this.dataset.getY(n) - t) * s, a = r * r + i * i;
238
+ a < l && (l = a, c = n);
239
+ }
240
+ if (c < 0) return null;
241
+ let u = this.sampleAt(c);
242
+ return u ? {
243
+ ...u,
244
+ distancePx: Math.sqrt(l)
245
+ } : null;
246
+ }
170
247
  copyRawVisible(e, t, n) {
171
248
  return this.copyVisibleSamples(e, t, n, "points", 0);
172
249
  }
@@ -179,6 +256,15 @@ var t = 16, n = class {
179
256
  copyMinMaxInstanced(e, t, n) {
180
257
  return this.copyMinMaxSegments(e, t, n, "instanced");
181
258
  }
259
+ visibleIndexRange(e) {
260
+ return e ? {
261
+ start: this.dataset.lowerBoundX(e.xMin),
262
+ end: this.dataset.upperBoundX(e.xMax)
263
+ } : {
264
+ start: 0,
265
+ end: this.dataset.length
266
+ };
267
+ }
182
268
  copyVisibleSamples(e, t, n, r, i) {
183
269
  let a = r === "points" ? 2 : 4;
184
270
  if (n <= 0 || t.length < n * a) return 0;
@@ -205,31 +291,67 @@ var t = 16, n = class {
205
291
  if (s <= 0) return 0;
206
292
  let c = Math.min(n, s);
207
293
  for (let e = 0; e < c; e++) {
208
- 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 = Infinity, d = -Infinity;
209
- for (let e = n; e < l; e++) {
210
- let t = this.dataset.getY(e);
211
- t < u && (u = t), t > d && (d = t);
212
- }
213
- let f = this.dataset.getX(n + (l - n >> 1));
294
+ 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);
295
+ if (!u) continue;
296
+ let d = this.dataset.getX(n + (l - n >> 1)), { minY: f, maxY: p } = u;
214
297
  if (r === "line-list") {
215
298
  let n = e * 4;
216
- t[n] = f, t[n + 1] = u, t[n + 2] = f, t[n + 3] = d;
299
+ t[n] = d, t[n + 1] = f, t[n + 2] = d, t[n + 3] = p;
217
300
  } else {
218
301
  let n = e * 3;
219
- t[n] = f, t[n + 1] = u, t[n + 2] = d;
302
+ t[n] = d, t[n + 1] = f, t[n + 2] = p;
220
303
  }
221
304
  }
222
305
  return c;
223
306
  }
224
- }, i = class {
307
+ minMaxForRange(e, t) {
308
+ return this._useDatasetRangeMinMax && r(this.dataset) ? this.dataset.rangeMinMaxY(e, t) : !this.pyramid || this._useRawMinMaxScan ? this.rawMinMaxForRange(e, t) : this.pyramid.rangeMinMax(this.dataset, e, t);
309
+ }
310
+ queryRangeMinMax(e, t, n) {
311
+ if (n <= 0 || t <= 0 || !r(this.dataset)) return {
312
+ buckets: new Float32Array(),
313
+ bucketCount: 0,
314
+ level: 0,
315
+ samplesPerPixel: 0
316
+ };
317
+ let i = Math.max(1, t / n), a = Math.max(0, Math.ceil(Math.log2(i)) - 1), o = 2 ** (a + 1), s = Math.max(0, e), c = s + t, l = Math.ceil(this.dataset.length / o), u = Math.max(0, Math.floor(s / o)), d = Math.min(l, Math.ceil(c / o)), f = Math.max(0, d - u), p = new Float32Array(f * 2);
318
+ for (let e = 0; e < f; e++) {
319
+ let t = (u + e) * o, n = Math.min(this.dataset.length, t + o), r = this.dataset.rangeMinMaxY(t, n);
320
+ r && (p[e * 2] = r.minY, p[e * 2 + 1] = r.maxY);
321
+ }
322
+ return {
323
+ buckets: p,
324
+ bucketCount: f,
325
+ level: a,
326
+ samplesPerPixel: i
327
+ };
328
+ }
329
+ rawMinMaxForRange(e, t) {
330
+ if (r(this.dataset)) return this.dataset.rangeMinMaxY(e, t);
331
+ let n = Math.max(0, Math.floor(e)), i = Math.min(this.dataset.length, Math.ceil(t));
332
+ if (i <= n) return null;
333
+ let a = Infinity, o = -Infinity;
334
+ for (let e = n; e < i; e++) {
335
+ let t = this.dataset.getY(e);
336
+ t < a && (a = t), t > o && (o = t);
337
+ }
338
+ return {
339
+ minY: a,
340
+ maxY: o
341
+ };
342
+ }
343
+ }, a = class e {
225
344
  capacity;
226
345
  _length = 0;
227
346
  _head = 0;
228
347
  xData;
229
348
  yData;
230
- constructor(e) {
231
- if (!Number.isInteger(e) || e <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
232
- this.capacity = e, this.xData = new Float64Array(e), this.yData = new Float32Array(e);
349
+ treeBase;
350
+ minTree;
351
+ maxTree;
352
+ constructor(t) {
353
+ if (!Number.isInteger(t) || t <= 0) throw RangeError("RingBuffer capacity must be a positive integer.");
354
+ 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);
233
355
  }
234
356
  get length() {
235
357
  return this._length;
@@ -241,11 +363,21 @@ var t = 16, n = class {
241
363
  };
242
364
  }
243
365
  push(e, t) {
244
- this.xData[this._head] = e, this.yData[this._head] = t, this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
366
+ 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++;
245
367
  }
246
368
  append(e, t) {
247
369
  let n = Math.min(e.length, t.length);
248
- for (let r = 0; r < n; r++) this.push(e[r], t[r]);
370
+ if (n <= 0) return;
371
+ if (n >= this.capacity) {
372
+ let r = n - this.capacity;
373
+ this._head = 0, this._length = this.capacity, this.copyIntoPhysical(0, e, t, r, this.capacity);
374
+ return;
375
+ }
376
+ let r = 0, i = n;
377
+ for (; i > 0;) {
378
+ let n = Math.min(i, this.capacity - this._head);
379
+ 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;
380
+ }
249
381
  }
250
382
  get(e) {
251
383
  return e < 0 || e >= this._length ? null : {
@@ -275,8 +407,64 @@ var t = 16, n = class {
275
407
  }
276
408
  return t;
277
409
  }
410
+ rangeMinMaxY(e, t) {
411
+ let n = Math.max(0, Math.floor(e)), r = Math.min(this._length, Math.ceil(t));
412
+ if (r <= n) return null;
413
+ let i = this.logicalToPhysical(n), a = r - n;
414
+ if (i + a <= this.capacity) return this.queryPhysicalMinMax(i, i + a);
415
+ let o = this.queryPhysicalMinMax(i, this.capacity), s = this.queryPhysicalMinMax(0, (i + a) % this.capacity);
416
+ return o ? s ? {
417
+ minY: Math.min(o.minY, s.minY),
418
+ maxY: Math.max(o.maxY, s.maxY)
419
+ } : o : s;
420
+ }
278
421
  clear() {
279
- this._length = 0, this._head = 0;
422
+ this._length = 0, this._head = 0, this.minTree.fill(Infinity), this.maxTree.fill(-Infinity);
423
+ }
424
+ copyIntoPhysical(e, t, n, r, i) {
425
+ for (let a = 0; a < i; a++) {
426
+ let i = e + a, o = n[r + a];
427
+ this.xData[i] = t[r + a], this.yData[i] = o;
428
+ let s = this.treeBase + i;
429
+ this.minTree[s] = o, this.maxTree[s] = o;
430
+ }
431
+ this.recomputeTreeRange(e, e + i);
432
+ }
433
+ setTreeLeaf(e, t) {
434
+ let n = this.treeBase + e;
435
+ for (this.minTree[n] = t, this.maxTree[n] = t, n >>= 1; n >= 1;) this.recomputeTreeNode(n), n >>= 1;
436
+ }
437
+ recomputeTreeRange(e, t) {
438
+ let n = this.treeBase + e >> 1, r = this.treeBase + t - 1 >> 1;
439
+ for (; n >= 1;) {
440
+ for (let e = n; e <= r; e++) this.recomputeTreeNode(e);
441
+ if (n === 1) break;
442
+ n >>= 1, r >>= 1;
443
+ }
444
+ }
445
+ recomputeTreeNode(e) {
446
+ let t = e << 1, n = t + 1, r = this.minTree[t], i = this.minTree[n], a = this.maxTree[t], o = this.maxTree[n];
447
+ this.minTree[e] = r < i ? r : i, this.maxTree[e] = a > o ? a : o;
448
+ }
449
+ queryPhysicalMinMax(e, t) {
450
+ if (t <= e) return null;
451
+ let n = this.treeBase + e, r = this.treeBase + t, i = Infinity, a = -Infinity;
452
+ for (; n < r;) {
453
+ if (n & 1) {
454
+ let e = this.minTree[n], t = this.maxTree[n];
455
+ e < i && (i = e), t > a && (a = t), n++;
456
+ }
457
+ if (r & 1) {
458
+ r--;
459
+ let e = this.minTree[r], t = this.maxTree[r];
460
+ e < i && (i = e), t > a && (a = t);
461
+ }
462
+ n >>= 1, r >>= 1;
463
+ }
464
+ return Number.isFinite(i) && Number.isFinite(a) ? {
465
+ minY: i,
466
+ maxY: a
467
+ } : null;
280
468
  }
281
469
  logicalToPhysical(e) {
282
470
  return (this._head - this._length + e + this.capacity) % this.capacity;
@@ -284,29 +472,42 @@ var t = 16, n = class {
284
472
  assertValidIndex(e) {
285
473
  if (!Number.isInteger(e) || e < 0 || e >= this._length) throw RangeError(`RingBuffer index out of range: ${e}`);
286
474
  }
287
- }, a = {
475
+ static nextPowerOfTwo(e) {
476
+ return 2 ** Math.ceil(Math.log2(e));
477
+ }
478
+ }, 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", _ = {
288
479
  line: {
289
- 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",
290
- frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
480
+ vert: o,
481
+ frag: s
291
482
  },
292
483
  segment: {
293
- vert: "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",
294
- frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
484
+ vert: c,
485
+ frag: l
295
486
  },
296
487
  point: {
297
- vert: "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",
298
- frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
488
+ vert: u,
489
+ frag: d
490
+ },
491
+ pointSprite: {
492
+ vert: f,
493
+ frag: p
299
494
  },
300
495
  bar: {
301
- vert: "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",
302
- frag: "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n"
496
+ vert: m,
497
+ frag: g
498
+ },
499
+ barRange: {
500
+ vert: h,
501
+ frag: g
303
502
  }
304
- }, o = 3, s = 2, c = 4, l = 4, u = .8, d = 0, f = class {
503
+ }, v = 3, y = 2, b = 4, x = 4, S = .8, C = 0, w = class {
305
504
  backend;
306
505
  lineProgram;
307
506
  segmentProgram;
308
507
  pointProgram;
508
+ pointSpriteProgram;
309
509
  barProgram;
510
+ barRangeProgram;
310
511
  segmentSelectBuffer;
311
512
  pointCornerBuffer;
312
513
  barCornerBuffer;
@@ -314,7 +515,7 @@ var t = 16, n = class {
314
515
  offsetUniform = new Float32Array(2);
315
516
  canvasSizeUniform = new Float32Array(2);
316
517
  constructor(e) {
317
- this.backend = e, this.lineProgram = this.backend.createProgram(a.line.vert, a.line.frag), this.segmentProgram = this.backend.createProgram(a.segment.vert, a.segment.frag), this.pointProgram = this.backend.createProgram(a.point.vert, a.point.frag), this.barProgram = this.backend.createProgram(a.bar.vert, a.bar.frag), this.segmentSelectBuffer = this.backend.createBuffer({
518
+ 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({
318
519
  usage: "static",
319
520
  type: "float",
320
521
  length: 2
@@ -382,25 +583,25 @@ var t = 16, n = class {
382
583
  }
383
584
  drawMinMaxSegmentsInstanced(e, t, n, r) {
384
585
  this.writeCameraUniforms(r);
385
- let i = o * c, a = {
586
+ let i = v * b, a = {
386
587
  buffer: e,
387
588
  divisor: 1,
388
589
  stride: i,
389
590
  offset: 0
390
- }, s = {
591
+ }, o = {
391
592
  buffer: e,
392
593
  divisor: 1,
393
594
  stride: i,
394
- offset: c
395
- }, l = {
595
+ offset: b
596
+ }, s = {
396
597
  buffer: e,
397
598
  divisor: 1,
398
599
  stride: i,
399
- offset: c * 2
400
- }, u = {
600
+ offset: b * 2
601
+ }, c = {
401
602
  buffer: this.segmentSelectBuffer,
402
603
  divisor: 0,
403
- stride: c,
604
+ stride: b,
404
605
  offset: 0
405
606
  };
406
607
  this.backend.draw({
@@ -409,9 +610,9 @@ var t = 16, n = class {
409
610
  count: 2,
410
611
  instances: t,
411
612
  attributes: {
412
- aMaxY: l,
413
- aMinY: s,
414
- aSelect: u,
613
+ aMaxY: s,
614
+ aMinY: o,
615
+ aSelect: c,
415
616
  aX: a
416
617
  },
417
618
  uniforms: {
@@ -426,13 +627,13 @@ var t = 16, n = class {
426
627
  let o = {
427
628
  buffer: e,
428
629
  divisor: 1,
429
- stride: s * c,
630
+ stride: y * b,
430
631
  offset: 0,
431
632
  size: 2
432
- }, u = {
633
+ }, s = {
433
634
  buffer: this.pointCornerBuffer,
434
635
  divisor: 0,
435
- stride: s * c,
636
+ stride: y * b,
436
637
  offset: 0,
437
638
  size: 2
438
639
  };
@@ -442,14 +643,28 @@ var t = 16, n = class {
442
643
  count: 4,
443
644
  instances: t,
444
645
  attributes: {
445
- aCorner: u,
646
+ aCorner: s,
446
647
  aPosition: o
447
648
  },
448
649
  uniforms: {
449
650
  uScale: this.scaleUniform,
450
651
  uOffset: this.offsetUniform,
451
652
  uCanvasSize: this.canvasSizeUniform,
452
- uPointSize: n.pointSize ?? l,
653
+ uPointSize: n.pointSize ?? x,
654
+ uColor: n.color
655
+ }
656
+ });
657
+ }
658
+ drawPointSprites(e, t, n, r) {
659
+ this.writeCameraUniforms(r), this.backend.draw({
660
+ program: this.pointSpriteProgram,
661
+ primitive: "points",
662
+ count: t,
663
+ attributes: { aPosition: e },
664
+ uniforms: {
665
+ uScale: this.scaleUniform,
666
+ uOffset: this.offsetUniform,
667
+ uPointSize: n.pointSize ?? x,
453
668
  uColor: n.color
454
669
  }
455
670
  });
@@ -472,13 +687,13 @@ var t = 16, n = class {
472
687
  let i = {
473
688
  buffer: e,
474
689
  divisor: 1,
475
- stride: s * c,
690
+ stride: y * b,
476
691
  offset: 0,
477
692
  size: 2
478
693
  }, a = {
479
694
  buffer: this.barCornerBuffer,
480
695
  divisor: 0,
481
- stride: s * c,
696
+ stride: y * b,
482
697
  offset: 0,
483
698
  size: 2
484
699
  };
@@ -494,12 +709,58 @@ var t = 16, n = class {
494
709
  uniforms: {
495
710
  uScale: this.scaleUniform,
496
711
  uOffset: this.offsetUniform,
497
- uBarWidth: n.barWidth ?? u,
498
- uBaseline: n.baseline ?? d,
712
+ uBarWidth: n.barWidth ?? S,
713
+ uBaseline: n.baseline ?? C,
499
714
  uColor: n.color
500
715
  }
501
716
  });
502
717
  }
718
+ drawBarRangesInstanced(e, t, n, r) {
719
+ this.writeCameraUniforms(r);
720
+ let i = v * b, a = {
721
+ buffer: e,
722
+ divisor: 1,
723
+ stride: i,
724
+ offset: 0
725
+ }, o = {
726
+ buffer: e,
727
+ divisor: 1,
728
+ stride: i,
729
+ offset: b
730
+ }, s = {
731
+ buffer: e,
732
+ divisor: 1,
733
+ stride: i,
734
+ offset: b * 2
735
+ }, c = {
736
+ buffer: this.barCornerBuffer,
737
+ divisor: 0,
738
+ stride: y * b,
739
+ offset: 0,
740
+ size: 2
741
+ };
742
+ this.backend.draw({
743
+ program: this.barRangeProgram,
744
+ primitive: "triangle_strip",
745
+ count: 4,
746
+ instances: t,
747
+ attributes: {
748
+ aCorner: c,
749
+ aMaxY: s,
750
+ aMinY: o,
751
+ aX: a
752
+ },
753
+ uniforms: {
754
+ uScale: this.scaleUniform,
755
+ uOffset: this.offsetUniform,
756
+ uBarWidth: n.barWidth ?? S,
757
+ uColor: n.color
758
+ }
759
+ });
760
+ }
761
+ drawBarTriangles(e, t, n, r) {
762
+ this.drawTrianglePrimitive(e, t, n, r);
763
+ }
503
764
  drawLinePrimitive(e, t, n, r, i) {
504
765
  this.writeCameraUniforms(i), this.backend.draw({
505
766
  program: this.lineProgram,
@@ -513,19 +774,32 @@ var t = 16, n = class {
513
774
  }
514
775
  });
515
776
  }
777
+ drawTrianglePrimitive(e, t, n, r) {
778
+ this.writeCameraUniforms(r), this.backend.draw({
779
+ program: this.lineProgram,
780
+ primitive: "triangles",
781
+ count: t,
782
+ attributes: { position: e },
783
+ uniforms: {
784
+ uScale: this.scaleUniform,
785
+ uOffset: this.offsetUniform,
786
+ uColor: n.color
787
+ }
788
+ });
789
+ }
516
790
  writeCameraUniforms(e) {
517
791
  this.scaleUniform[0] = e.xScale, this.scaleUniform[1] = e.yScale, this.offsetUniform[0] = e.xOffset, this.offsetUniform[1] = e.yOffset;
518
792
  }
519
793
  dispose() {
520
794
  this.backend.destroy();
521
795
  }
522
- }, p = [
796
+ }, T = [
523
797
  1024,
524
798
  4096,
525
799
  16384,
526
800
  32768,
527
801
  131072
528
- ], m = class {
802
+ ], E = class {
529
803
  regl;
530
804
  pool = [];
531
805
  preAllocated = !1;
@@ -538,7 +812,7 @@ var t = 16, n = class {
538
812
  preAllocate() {
539
813
  if (!this.preAllocated) {
540
814
  this.preAllocated = !0;
541
- for (let e of p) this.pool.push(this.createEntry(e, "stream"));
815
+ for (let e of T) this.pool.push(this.createEntry(e, "stream"));
542
816
  }
543
817
  }
544
818
  acquire(e, t = "stream") {
@@ -578,17 +852,17 @@ var t = 16, n = class {
578
852
  return this.pool.find((t) => !t.inUse && t.floatCapacity >= e);
579
853
  }
580
854
  roundUp(e) {
581
- for (let t of p) if (t >= e) return t;
582
- let t = p[p.length - 1], n = 1 << 32 - Math.clz32(e - 1);
855
+ for (let t of T) if (t >= e) return t;
856
+ let t = T[T.length - 1], n = 1 << 32 - Math.clz32(e - 1);
583
857
  return Math.max(t * 2, n);
584
858
  }
585
859
  };
586
860
  //#endregion
587
861
  //#region src/render/ReglBackend.ts
588
- function h(e) {
862
+ function D(e) {
589
863
  return e;
590
864
  }
591
- var g = class {
865
+ var O = class {
592
866
  gl;
593
867
  regl;
594
868
  resources;
@@ -608,10 +882,10 @@ var g = class {
608
882
  });
609
883
  if (!n) throw Error("BlazePlot requires WebGL2, but this browser/context does not support it.");
610
884
  this.gl = n, this.regl = e({
611
- gl: h(this.gl),
885
+ gl: D(this.gl),
612
886
  extensions: [],
613
887
  optionalExtensions: ["angle_instanced_arrays", "ext_disjoint_timer_query_webgl2"]
614
- }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new m(this.regl), this.resources.preAllocate();
888
+ }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new E(this.regl), this.resources.preAllocate();
615
889
  }
616
890
  createBuffer(e) {
617
891
  let { buffer: t } = this.resources.acquire(e.length, e.usage);
@@ -730,7 +1004,7 @@ var g = class {
730
1004
  default: return e;
731
1005
  }
732
1006
  }
733
- }, _ = class {
1007
+ }, k = class {
734
1008
  canvas;
735
1009
  camera;
736
1010
  policy;
@@ -784,7 +1058,7 @@ var g = class {
784
1058
  dispose() {
785
1059
  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);
786
1060
  }
787
- }, v = class e {
1061
+ }, A = class e {
788
1062
  _xMin = 0;
789
1063
  _xMax = 1;
790
1064
  _yMin = 0;
@@ -869,7 +1143,7 @@ var g = class {
869
1143
  static assertFinite(e, t) {
870
1144
  if (!Number.isFinite(t)) throw RangeError(`Camera2D ${e} must be finite.`);
871
1145
  }
872
- }, y = class {
1146
+ }, j = class {
873
1147
  camera;
874
1148
  constructor(e) {
875
1149
  this.camera = e;
@@ -901,7 +1175,7 @@ var g = class {
901
1175
  let n = Math.max(0, -Math.floor(Math.log10(t)) + 2), r = Number(e.toFixed(n));
902
1176
  return Object.is(r, -0) ? 0 : r;
903
1177
  }
904
- }, b = class {
1178
+ }, M = class {
905
1179
  layout;
906
1180
  config;
907
1181
  options;
@@ -943,7 +1217,7 @@ var g = class {
943
1217
  }
944
1218
  }
945
1219
  }
946
- }, x = class {
1220
+ }, N = class {
947
1221
  root;
948
1222
  plot;
949
1223
  canvas;
@@ -968,10 +1242,10 @@ var g = class {
968
1242
  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);
969
1243
  }
970
1244
  applyBaseStyles() {
971
- 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";
1245
+ 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";
972
1246
  }
973
- }, S = 16384, C = S >> 1, w = S >> 1, T = 3, E = 64;
974
- function D(e) {
1247
+ }, P = 16384, F = P >> 1, I = P >> 1, L = 3, R = 4096, z = 12, B = 64;
1248
+ function V(e) {
975
1249
  return e === !1 ? {
976
1250
  visible: !1,
977
1251
  position: "inside"
@@ -983,7 +1257,7 @@ function D(e) {
983
1257
  position: e.position ?? "inside"
984
1258
  };
985
1259
  }
986
- var O = class {
1260
+ var H = class {
987
1261
  options;
988
1262
  series = [];
989
1263
  camera;
@@ -994,6 +1268,8 @@ var O = class {
994
1268
  rawLineData;
995
1269
  minMaxInstanceBuffer;
996
1270
  minMaxInstanceData;
1271
+ barTriangleBuffer;
1272
+ barTriangleData;
997
1273
  gridBuffer;
998
1274
  gridData;
999
1275
  gridStyle;
@@ -1011,8 +1287,21 @@ var O = class {
1011
1287
  renderMode: "none"
1012
1288
  };
1013
1289
  resizeObserver = null;
1290
+ pluginDisposers = [];
1291
+ hoverSubscribers = /* @__PURE__ */ new Set();
1292
+ seriesSubscribers = /* @__PURE__ */ new Set();
1293
+ currentHover = null;
1294
+ lastPointerClientX = 0;
1295
+ lastPointerClientY = 0;
1296
+ pointerInPlot = !1;
1014
1297
  lastFrameAt = 0;
1015
1298
  _rafId = 0;
1299
+ handlePointerMove = (e) => {
1300
+ this.pointerInPlot = !0, this.lastPointerClientX = e.clientX, this.lastPointerClientY = e.clientY, this.refreshHover();
1301
+ };
1302
+ handlePointerLeave = () => {
1303
+ this.pointerInPlot = !1, this.emitHover(null);
1304
+ };
1016
1305
  constructor(e, t = {}) {
1017
1306
  this.options = t;
1018
1307
  let n = t.axes;
@@ -1035,9 +1324,9 @@ var O = class {
1035
1324
  position: "inside"
1036
1325
  }
1037
1326
  } : this.normalizedAxes = {
1038
- x: D(n.x),
1039
- y: D(n.y)
1040
- }, this.layout = new x(e, this.normalizedAxes), this.applyCanvasSize(), this.camera = new v(), this.axis = new y(this.camera), this.renderer = new f(new g(this.layout.canvas)), this.input = new _(this.layout.canvas, this.camera, t.viewportPolicy), this.rawLineData = new Float32Array(S * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.minMaxInstanceData = new Float32Array(w * T), this.minMaxInstanceBuffer = this.renderer.createFloatBuffer(this.minMaxInstanceData.length), this.gridData = new Float32Array(E * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
1327
+ x: V(n.x),
1328
+ y: V(n.y)
1329
+ }, 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 = {
1041
1330
  color: t.gridStyle?.color ?? [
1042
1331
  .22,
1043
1332
  .3,
@@ -1045,35 +1334,87 @@ var O = class {
1045
1334
  .45
1046
1335
  ],
1047
1336
  lineWidth: t.gridStyle?.lineWidth ?? 1
1048
- }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new b(this.layout, this.normalizedAxes)), typeof ResizeObserver < "u" && (this.resizeObserver = new ResizeObserver(() => this.resize()), this.resizeObserver.observe(this.layout.plot));
1337
+ }, (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));
1338
+ for (let e of t.plugins ?? []) {
1339
+ let t = e.install(this);
1340
+ typeof t == "function" ? this.pluginDisposers.push(t) : t && this.pluginDisposers.push(() => t.dispose());
1341
+ }
1049
1342
  }
1050
1343
  get canvas() {
1051
1344
  return this.layout.canvas;
1052
1345
  }
1346
+ get rootElement() {
1347
+ return this.layout.root;
1348
+ }
1349
+ get plotElement() {
1350
+ return this.layout.plot;
1351
+ }
1352
+ dataToPlot(e, t) {
1353
+ let [n, r] = this.camera.toClip(e, t);
1354
+ return this.camera.toScreen(n, r, this.canvas.clientWidth, this.canvas.clientHeight);
1355
+ }
1053
1356
  addSeries(e, t) {
1054
- let n = e.dataset ?? new i(e.capacity), a = t?.color ?? [
1357
+ let n = e.dataset ?? new a(e.capacity), r = t?.color ?? [
1055
1358
  .3,
1056
1359
  .6,
1057
1360
  1,
1058
1361
  1
1059
- ], o = new r(n, e, {
1060
- color: a,
1362
+ ], o = new i(n, e, {
1363
+ color: r,
1061
1364
  lineWidth: t?.lineWidth ?? 1,
1062
1365
  pointSize: t?.pointSize ?? 4,
1063
1366
  barWidth: t?.barWidth ?? .8,
1064
1367
  baseline: t?.baseline ?? 0,
1065
1368
  fillColor: t?.fillColor ?? [
1066
- a[0],
1067
- a[1],
1068
- a[2],
1069
- a[3] * .25
1369
+ r[0],
1370
+ r[1],
1371
+ r[2],
1372
+ r[3] * .25
1070
1373
  ]
1071
1374
  });
1072
- return this.series.push(o), o;
1375
+ return this.series.push(o), this.emitSeriesChange(), o;
1376
+ }
1377
+ addLine(e, t) {
1378
+ return this.addSeries({
1379
+ ...e,
1380
+ mode: "line"
1381
+ }, t);
1382
+ }
1383
+ addArea(e, t) {
1384
+ return this.addSeries({
1385
+ ...e,
1386
+ mode: "area"
1387
+ }, t);
1388
+ }
1389
+ addScatter(e, t) {
1390
+ return this.addSeries({
1391
+ ...e,
1392
+ mode: "scatter"
1393
+ }, t);
1394
+ }
1395
+ addBar(e, t) {
1396
+ return this.addSeries({
1397
+ ...e,
1398
+ mode: "bar"
1399
+ }, t);
1073
1400
  }
1074
1401
  removeSeries(e) {
1075
1402
  let t = this.series.indexOf(e);
1076
- return t === -1 ? !1 : (this.series.splice(t, 1), !0);
1403
+ return t === -1 ? !1 : (this.series.splice(t, 1), this.emitSeriesChange(), !0);
1404
+ }
1405
+ setSeriesVisible(e, t) {
1406
+ return this.series.includes(e) ? e.visible === t ? !0 : (e.setVisible(t), this.emitSeriesChange(), !0) : !1;
1407
+ }
1408
+ getSeriesState() {
1409
+ return this.series.map((e, t) => ({
1410
+ series: e,
1411
+ index: t,
1412
+ id: e.config.id,
1413
+ name: e.config.name,
1414
+ mode: e.config.mode,
1415
+ visible: e.visible,
1416
+ color: e.style.color
1417
+ }));
1077
1418
  }
1078
1419
  setViewport(e) {
1079
1420
  this.camera.setViewport(e);
@@ -1091,6 +1432,45 @@ var O = class {
1091
1432
  }) {
1092
1433
  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;
1093
1434
  }
1435
+ getHoverState() {
1436
+ return this.currentHover;
1437
+ }
1438
+ subscribe(e, t) {
1439
+ if (e === "hover") {
1440
+ let e = t;
1441
+ return this.hoverSubscribers.add(e), () => this.hoverSubscribers.delete(e);
1442
+ }
1443
+ let n = t;
1444
+ return this.seriesSubscribers.add(n), () => this.seriesSubscribers.delete(n);
1445
+ }
1446
+ pick(e, t, n = {}) {
1447
+ let r = this.canvas.getBoundingClientRect();
1448
+ if (r.width <= 0 || r.height <= 0) return null;
1449
+ let i = e - r.left, a = t - r.top;
1450
+ if (i < 0 || a < 0 || i > r.width || a > r.height) return null;
1451
+ 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);
1452
+ return d === null ? null : {
1453
+ clientX: e,
1454
+ clientY: t,
1455
+ plotX: i,
1456
+ plotY: a,
1457
+ dataX: s,
1458
+ dataY: c,
1459
+ anchorX: d,
1460
+ mode: l,
1461
+ items: this.collectPickItems(d, e, t, o, r)
1462
+ };
1463
+ }
1464
+ async screenshot(e = {}) {
1465
+ this.render();
1466
+ 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");
1467
+ o.width = i, o.height = a;
1468
+ let s = o.getContext("2d");
1469
+ if (!s) throw Error("Unable to create a 2D canvas context for screenshot export.");
1470
+ 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) => {
1471
+ o.toBlob((e) => e ? t(e) : n(/* @__PURE__ */ Error("Unable to encode chart screenshot.")), e.type ?? "image/png", e.quality);
1472
+ });
1473
+ }
1094
1474
  start() {
1095
1475
  let e = () => {
1096
1476
  this._rafId = requestAnimationFrame(e), this.render();
@@ -1110,7 +1490,7 @@ var O = class {
1110
1490
  }
1111
1491
  for (let e of this.series) {
1112
1492
  if (!e.visible) continue;
1113
- if (e.config.mode === "scatter") {
1493
+ if (e.rebuildPyramid(), e.config.mode === "scatter") {
1114
1494
  this.drawScatterSeries(e, t);
1115
1495
  continue;
1116
1496
  }
@@ -1122,62 +1502,191 @@ var O = class {
1122
1502
  this.drawAreaSeries(e, t);
1123
1503
  continue;
1124
1504
  }
1125
- let n = e.visibleSampleCount(t), r = e.hasLOD && n > S;
1505
+ let n = e.visibleSampleCount(t), r = e.hasLOD && n > P;
1126
1506
  if (r && this.renderer.supportsInstancedSegments) {
1127
1507
  let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxMinMaxSegments());
1128
1508
  if (n <= 0) continue;
1129
1509
  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;
1130
1510
  continue;
1131
1511
  }
1132
- let i = r ? e.copyMinMaxVisible(t, this.rawLineData, this.maxMinMaxSegments()) : e.copyRawVisible(t, this.rawLineData, S);
1512
+ let i = r ? e.copyMinMaxVisible(t, this.rawLineData, this.maxMinMaxSegments()) : e.copyRawVisible(t, this.rawLineData, P);
1133
1513
  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);
1134
1514
  }
1135
- this.axisOverlay?.update(this.camera, this.axis), this.stats.frameMs = performance.now() - e;
1515
+ this.axisOverlay?.update(this.camera, this.axis), this.stats.frameMs = performance.now() - e, this.refreshHover();
1136
1516
  }
1137
1517
  dispose() {
1138
- this.stop(), this.resizeObserver?.disconnect(), this.input.dispose(), this.axisOverlay?.dispose(), this.renderer.dispose(), this.layout.dispose();
1518
+ this.stop(), this.resizeObserver?.disconnect(), this.canvas.removeEventListener("pointermove", this.handlePointerMove), this.canvas.removeEventListener("pointerleave", this.handlePointerLeave);
1519
+ for (let e of this.pluginDisposers.splice(0)) e();
1520
+ this.input.dispose(), this.axisOverlay?.dispose(), this.renderer.dispose(), this.layout.dispose();
1139
1521
  }
1140
1522
  applyCanvasSize(e = globalThis.devicePixelRatio) {
1141
1523
  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));
1142
1524
  return this.canvas.width === n && this.canvas.height === r ? !1 : (this.canvas.width = n, this.canvas.height = r, !0);
1143
1525
  }
1144
1526
  drawAreaSeries(e, t) {
1145
- let n = e.style.baseline ?? 0, r = e.copyAreaVisible(t, this.rawLineData, C, n);
1527
+ let n = e.style.baseline ?? 0, r = e.copyAreaVisible(t, this.rawLineData, F, n);
1146
1528
  if (r < 4) return;
1147
1529
  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;
1148
- let i = this.uploadRawInstances(e, t, C);
1530
+ let i = this.uploadRawInstances(e, t, F);
1149
1531
  i >= 2 && (this.renderer.drawLineStrip(this.rawLineBuffer, i, e.style, this.camera), this.stats.pointsRendered += i, this.stats.drawCalls++), this.recordRenderMode("area");
1150
1532
  }
1151
1533
  drawScatterSeries(e, t) {
1152
- if (!this.renderer.supportsInstancedPoints) return;
1153
- let n = this.uploadRawInstances(e, t, S);
1154
- n <= 0 || (this.renderer.drawPointsInstanced(this.rawLineBuffer, n, e.style, this.camera, this.canvas.width, this.canvas.height), this.recordInstancedDraw("points", n));
1534
+ let n = this.uploadRawInstances(e, t, P);
1535
+ 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));
1155
1536
  }
1156
1537
  drawBarSeries(e, t) {
1157
- if (!this.renderer.supportsInstancedBars) return;
1158
- let n = this.uploadRawInstances(e, t, S);
1159
- n <= 0 || (this.renderer.drawBarsInstanced(this.rawLineBuffer, n, e.style, this.camera), this.recordInstancedDraw("bars", n));
1538
+ let n = e.visibleSampleCount(t), r = this.maxRawBarInstances();
1539
+ if (e.hasLOD && n > r) {
1540
+ let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxBarFallbackBars());
1541
+ if (n <= 0) return;
1542
+ this.includeBaselineInBarRanges(n, e.style.baseline ?? 0);
1543
+ let r = this.writeBarBucketTriangles(n, t);
1544
+ this.drawBarTriangleFallback(r, e.style);
1545
+ return;
1546
+ }
1547
+ let i = this.uploadRawInstances(e, t, r);
1548
+ if (i <= 0) return;
1549
+ if (this.renderer.supportsInstancedBars) {
1550
+ this.renderer.drawBarsInstanced(this.rawLineBuffer, i, e.style, this.camera), this.recordInstancedDraw("bars", i);
1551
+ return;
1552
+ }
1553
+ let a = this.writeBarTriangles(i, e.style.baseline ?? 0, e.style.barWidth ?? .8);
1554
+ this.drawBarTriangleFallback(a, e.style);
1160
1555
  }
1161
1556
  uploadRawInstances(e, t, n) {
1162
1557
  let r = e.copyRawVisible(t, this.rawLineData, n);
1163
1558
  return r <= 0 ? 0 : (this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), this.stats.uploadBytes += this.rawLineData.byteLength, r);
1164
1559
  }
1560
+ includeBaselineInBarRanges(e, t) {
1561
+ for (let n = 0; n < e; n++) {
1562
+ let e = n * L, r = this.minMaxInstanceData[e + 1], i = this.minMaxInstanceData[e + 2];
1563
+ this.minMaxInstanceData[e + 1] = Math.min(t, r), this.minMaxInstanceData[e + 2] = Math.max(t, i);
1564
+ }
1565
+ }
1566
+ writeBarTriangles(e, t, n) {
1567
+ let r = Math.min(e, this.maxBarFallbackBars());
1568
+ for (let e = 0; e < r; e++) {
1569
+ let r = this.rawLineData[e * 2], i = this.rawLineData[e * 2 + 1];
1570
+ this.writeBarTriangle(e, r - n * .5, r + n * .5, t, i);
1571
+ }
1572
+ return r * 6;
1573
+ }
1574
+ writeBarBucketTriangles(e, t) {
1575
+ let n = Math.min(e, this.maxBarFallbackBars());
1576
+ for (let e = 0; e < n; e++) {
1577
+ let r = this.minMaxInstanceData[e * 3 + 1], i = this.minMaxInstanceData[e * 3 + 2], [a, o] = this.barBucketBounds(e, n, t);
1578
+ this.writeBarTriangle(e, a, o, r, i);
1579
+ }
1580
+ return n * 6;
1581
+ }
1582
+ barBucketBounds(e, t, n) {
1583
+ let r = this.minMaxInstanceData[e * 3], i = n.xMax - n.xMin;
1584
+ if (t <= 1) {
1585
+ let e = Math.max(0, i * .5);
1586
+ return [Math.max(n.xMin, r - e), Math.min(n.xMax, r + e)];
1587
+ }
1588
+ let a = e > 0 ? this.minMaxInstanceData[(e - 1) * 3] : NaN, o = e + 1 < t ? this.minMaxInstanceData[(e + 1) * 3] : NaN, s = e === 0 ? r - (o - r) * .5 : (a + r) * .5, c = e + 1 === t ? r + (r - a) * .5 : (r + o) * .5;
1589
+ if (!Number.isFinite(s) || !Number.isFinite(c) || c <= s) {
1590
+ let r = i / Math.max(1, t);
1591
+ s = n.xMin + e * r, c = e + 1 === t ? n.xMax : s + r;
1592
+ }
1593
+ return [Math.max(n.xMin, s), Math.min(n.xMax, c)];
1594
+ }
1595
+ writeBarTriangle(e, t, n, r, i) {
1596
+ let a = e * z;
1597
+ 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;
1598
+ }
1599
+ drawBarTriangleFallback(e, t) {
1600
+ 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));
1601
+ }
1165
1602
  recordInstancedDraw(e, t) {
1166
1603
  this.recordRenderMode(e), this.stats.pointsRendered += t, this.stats.drawCalls++;
1167
1604
  }
1605
+ findNearestXAnchor(e, t, n, r) {
1606
+ let i = null, a = Infinity, o = n / (t.xMax - t.xMin);
1607
+ for (let n of this.series) {
1608
+ if (!n.visible) continue;
1609
+ let r = n.nearestSampleByX(e, t);
1610
+ if (!r) continue;
1611
+ let s = Math.abs(r.x - e) * o;
1612
+ s < a && (i = r, a = s);
1613
+ }
1614
+ return !i || a > r ? null : i.x;
1615
+ }
1616
+ findNearestPointAnchor(e, t, n, r, i, a) {
1617
+ let o = null;
1618
+ for (let a of this.series) {
1619
+ if (!a.visible) continue;
1620
+ let s = a.nearestSampleByPoint(e, t, n, r, i);
1621
+ s && (!o || (s.distancePx ?? Infinity) < (o.distancePx ?? Infinity)) && (o = s);
1622
+ }
1623
+ return !o || (o.distancePx ?? Infinity) > a ? null : o.x;
1624
+ }
1625
+ collectPickItems(e, t, n, r, i) {
1626
+ let a = [];
1627
+ for (let o = 0; o < this.series.length; o++) {
1628
+ let s = this.series[o];
1629
+ if (!s.visible) continue;
1630
+ let c = s.nearestSampleByX(e, r);
1631
+ if (!c) continue;
1632
+ 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;
1633
+ a.push({
1634
+ ...c,
1635
+ distancePx: Math.hypot(h, g),
1636
+ series: s,
1637
+ seriesIndex: o,
1638
+ id: s.config.id,
1639
+ name: s.config.name,
1640
+ mode: s.config.mode,
1641
+ plotX: d,
1642
+ plotY: f,
1643
+ clientX: p,
1644
+ clientY: m
1645
+ });
1646
+ }
1647
+ return a;
1648
+ }
1649
+ refreshHover() {
1650
+ this.pointerInPlot && this.emitHover(this.pick(this.lastPointerClientX, this.lastPointerClientY));
1651
+ }
1652
+ emitHover(e) {
1653
+ this.currentHover = e;
1654
+ for (let t of this.hoverSubscribers) t(e);
1655
+ }
1656
+ emitSeriesChange() {
1657
+ for (let e of this.seriesSubscribers) e();
1658
+ this.refreshHover();
1659
+ }
1660
+ drawDomTextForScreenshot(e, t, n) {
1661
+ let r = this.layout.root.querySelectorAll("div");
1662
+ for (let i of r) {
1663
+ let r = i.textContent;
1664
+ if (!r || i.children.length > 0) continue;
1665
+ let a = getComputedStyle(i);
1666
+ if (a.display === "none" || a.visibility === "hidden" || a.opacity === "0") continue;
1667
+ let o = i.getBoundingClientRect();
1668
+ 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());
1669
+ }
1670
+ }
1168
1671
  maxMinMaxSegments() {
1169
- return Math.min(this.canvas.width, w);
1672
+ return Math.min(this.canvas.width, I);
1673
+ }
1674
+ maxBarFallbackBars() {
1675
+ return Math.min(R, P);
1676
+ }
1677
+ maxRawBarInstances() {
1678
+ return this.renderer.supportsInstancedBars ? P : this.maxBarFallbackBars();
1170
1679
  }
1171
1680
  writeGridVertices(e) {
1172
1681
  let t = Math.max(1, this.canvas.clientWidth), n = Math.max(1, this.canvas.clientHeight);
1173
1682
  this.axis.getXTickValues(t, 12, this.xTicks), this.axis.getYTickValues(n, 8, this.yTicks);
1174
1683
  let r = 0;
1175
1684
  for (let t of this.xTicks) {
1176
- if (r + 2 > E) return r;
1685
+ if (r + 2 > B) return r;
1177
1686
  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++;
1178
1687
  }
1179
1688
  for (let t of this.yTicks) {
1180
- if (r + 2 > E) return r;
1689
+ if (r + 2 > B) return r;
1181
1690
  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++;
1182
1691
  }
1183
1692
  return r;
@@ -1185,7 +1694,7 @@ var O = class {
1185
1694
  recordRenderMode(e) {
1186
1695
  this.stats.renderMode === "none" ? this.stats.renderMode = e : this.stats.renderMode !== e && (this.stats.renderMode = "mixed");
1187
1696
  }
1188
- }, k = class {
1697
+ }, U = class {
1189
1698
  xData;
1190
1699
  yData;
1191
1700
  constructor(e, t) {
@@ -1227,6 +1736,6 @@ var O = class {
1227
1736
  }
1228
1737
  };
1229
1738
  //#endregion
1230
- export { y as AxisController, v as Camera2D, O as Chart, n as MinMaxPyramid, i as RingBuffer, r as SeriesStore, k as StaticDataset };
1739
+ export { j as AxisController, A as Camera2D, H as Chart, n as MinMaxPyramid, a as RingBuffer, i as SeriesStore, U as StaticDataset };
1231
1740
 
1232
1741
  //# sourceMappingURL=index.js.map