blazeplot 0.1.12 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +43 -62
  2. package/dist/core/DataCursor.d.ts.map +1 -1
  3. package/dist/core/OhlcDataset.d.ts +51 -0
  4. package/dist/core/OhlcDataset.d.ts.map +1 -0
  5. package/dist/core/RingBuffer.d.ts +7 -1
  6. package/dist/core/RingBuffer.d.ts.map +1 -1
  7. package/dist/core/SeriesStore.d.ts +21 -6
  8. package/dist/core/SeriesStore.d.ts.map +1 -1
  9. package/dist/core/StaticDataset.d.ts.map +1 -1
  10. package/dist/core/index.d.ts +1 -1
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/search.d.ts +3 -0
  13. package/dist/core/search.d.ts.map +1 -0
  14. package/dist/core/types.d.ts +49 -1
  15. package/dist/core/types.d.ts.map +1 -1
  16. package/dist/index.d.ts +5 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +827 -341
  19. package/dist/index.js.map +1 -1
  20. package/dist/plugins/interactions.d.ts +1 -1
  21. package/dist/plugins/interactions.d.ts.map +1 -1
  22. package/dist/plugins/interactions.js +44 -41
  23. package/dist/plugins/interactions.js.map +1 -1
  24. package/dist/plugins/tooltip.js +31 -20
  25. package/dist/plugins/tooltip.js.map +1 -1
  26. package/dist/render/Renderer.d.ts +9 -3
  27. package/dist/render/Renderer.d.ts.map +1 -1
  28. package/dist/ui/AxisOverlay.d.ts +3 -1
  29. package/dist/ui/AxisOverlay.d.ts.map +1 -1
  30. package/dist/ui/Chart.d.ts +42 -16
  31. package/dist/ui/Chart.d.ts.map +1 -1
  32. package/dist/ui/ChartLayout.d.ts +6 -0
  33. package/dist/ui/ChartLayout.d.ts.map +1 -1
  34. package/dist/ui/Interactions.d.ts +2 -1
  35. package/dist/ui/Interactions.d.ts.map +1 -1
  36. package/dist/ui/Tooltip.d.ts +4 -1
  37. package/dist/ui/Tooltip.d.ts.map +1 -1
  38. package/dist/ui/index.d.ts +1 -1
  39. package/dist/ui/index.d.ts.map +1 -1
  40. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -149,7 +149,25 @@ var t = 16, n = class {
149
149
  function r(e) {
150
150
  return "rangeMinMaxY" in e;
151
151
  }
152
- var i = class {
152
+ function i(e) {
153
+ return "getOpen" in e && "getHigh" in e && "getLow" in e && "getClose" in e;
154
+ }
155
+ function a(e) {
156
+ return "copySamplesRange" in e;
157
+ }
158
+ function o(e) {
159
+ return "copyMinMaxSegments" in e;
160
+ }
161
+ function s(e) {
162
+ return "copyVisibleSamples" in e;
163
+ }
164
+ var c = 64;
165
+ function l(e, t, n, r, i) {
166
+ if (n === e) return t;
167
+ let a = (i - e) / (n - e);
168
+ return t + (r - t) * a;
169
+ }
170
+ var u = class {
153
171
  config;
154
172
  style;
155
173
  dataset;
@@ -229,80 +247,207 @@ var i = class {
229
247
  }
230
248
  return this.sampleAt(i);
231
249
  }
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)
250
+ nearestSampleByPoint(e, t, n, r, i, a = Infinity) {
251
+ let o = this.visibleIndexRange(n), s = n.xMax - n.xMin, l = n.yMax - n.yMin;
252
+ if (o.start >= o.end || r <= 0 || i <= 0 || s <= 0 || l <= 0) return null;
253
+ let u = r / s, d = i / l, f = -1, p = a < 0 ? -1 : Number.isFinite(a) ? a * a : Infinity, m = (n) => {
254
+ let r = (this.dataset.getX(n) - e) * u, i = (this.dataset.getY(n) - t) * d, a = r * r + i * i;
255
+ (a < p || f < 0 && a <= p) && (p = a, f = n);
256
+ }, h = this.dataset.lowerBoundX(e), g = Math.min(Math.max(h, o.start), o.end - 1);
257
+ if (m(g), g > o.start && m(g - 1), g + 1 < o.end && m(g + 1), this.hasPointIntervalBounds() && o.end - o.start > c) {
258
+ let n = this.pointIntervalDistanceSq(o.start, o.end, e, t, u, d), r = n <= p ? [{
259
+ start: o.start,
260
+ end: o.end,
261
+ lowerBoundSq: n
262
+ }] : [];
263
+ for (; r.length > 0;) {
264
+ let n = r.pop();
265
+ if (n.lowerBoundSq > p) continue;
266
+ let i = n.end - n.start;
267
+ if (i <= c) {
268
+ for (let e = n.start; e < n.end; e++) m(e);
269
+ continue;
270
+ }
271
+ let a = n.start + (i >> 1), o = this.pointIntervalDistanceSq(n.start, a, e, t, u, d), s = this.pointIntervalDistanceSq(a, n.end, e, t, u, d), l = {
272
+ start: n.start,
273
+ end: a,
274
+ lowerBoundSq: o
275
+ }, f = {
276
+ start: a,
277
+ end: n.end,
278
+ lowerBoundSq: s
279
+ };
280
+ o < s ? (s <= p && r.push(f), o <= p && r.push(l)) : (o <= p && r.push(l), s <= p && r.push(f));
281
+ }
282
+ } else {
283
+ let t = Math.min(h - 1, o.end - 1), n = Math.max(h, o.start);
284
+ for (; t >= o.start || n < o.end;) {
285
+ let r = t >= o.start ? this.pointXDistanceSq(t, e, u) : Infinity, i = n < o.end ? this.pointXDistanceSq(n, e, u) : Infinity;
286
+ if (r > p && i > p) break;
287
+ r <= i ? (r <= p && m(t), t--) : (i <= p && m(n), n++);
288
+ }
289
+ }
290
+ if (f < 0) return null;
291
+ let _ = this.sampleAt(f);
292
+ return _ ? {
293
+ ..._,
294
+ distancePx: Math.sqrt(p)
245
295
  } : null;
246
296
  }
247
- copyRawVisible(e, t, n) {
248
- return this.copyVisibleSamples(e, t, n, "points", 0);
297
+ copyRawVisible(e, t, n, r = 0) {
298
+ return this.copyVisibleSamples(e, t, n, "points", 0, r);
299
+ }
300
+ copyRawVisibleClipped(e, t, n, r = 0) {
301
+ return this.copyClippedVisibleLine(e, t, n, r, "data");
302
+ }
303
+ copyRawVisibleClipSpace(e, t, n) {
304
+ return this.copyClippedVisibleLine(e, t, n, 0, "clip");
249
305
  }
250
- copyAreaVisible(e, t, n, r = 0) {
251
- return this.copyVisibleSamples(e, t, n, "area", r) * 2;
306
+ copyRawRange(e, t, n, r, i = 0) {
307
+ return this.copySampleRange(e, t, n, r, "points", 0, i);
252
308
  }
253
- copyMinMaxVisible(e, t, n) {
254
- return this.copyMinMaxSegments(e, t, n, "line-list") * 2;
309
+ copyAreaVisible(e, t, n, r = 0, i = 0) {
310
+ return this.copyVisibleSamples(e, t, n, "area", r, i) * 2;
255
311
  }
256
- copyMinMaxInstanced(e, t, n) {
257
- return this.copyMinMaxSegments(e, t, n, "instanced");
312
+ copyAreaRange(e, t, n, r, i = 0, a = 0) {
313
+ return this.copySampleRange(e, t, n, r, "area", i, a) * 2;
258
314
  }
259
- visibleIndexRange(e) {
260
- return e ? {
261
- start: this.dataset.lowerBoundX(e.xMin),
262
- end: this.dataset.upperBoundX(e.xMax)
263
- } : {
315
+ copyMinMaxVisible(e, t, n, r = 0) {
316
+ return this.copyMinMaxSegments(e, t, n, "line-list", r) * 2;
317
+ }
318
+ copyMinMaxInstanced(e, t, n, r = 0) {
319
+ return this.copyMinMaxSegments(e, t, n, "instanced", r);
320
+ }
321
+ copyOhlcRange(e, t, n, r, a, o = 0) {
322
+ if (!i(this.dataset) || r <= 0 || n.length < r * 12) return 0;
323
+ let s = Math.max(0, Math.floor(e)), c = Math.min(this.dataset.length, Math.ceil(t)), l = Math.min(r, Math.max(0, c - s)), u = a * .5;
324
+ for (let e = 0; e < l; e++) {
325
+ let t = s + e, r = this.dataset.getX(t) - o, i = this.dataset.getOpen(t), a = this.dataset.getHigh(t), c = this.dataset.getLow(t), l = this.dataset.getClose(t), d = e * 12;
326
+ n[d] = r, n[d + 1] = c, n[d + 2] = r, n[d + 3] = a, n[d + 4] = r - u, n[d + 5] = i, n[d + 6] = r, n[d + 7] = i, n[d + 8] = r, n[d + 9] = l, n[d + 10] = r + u, n[d + 11] = l;
327
+ }
328
+ return l;
329
+ }
330
+ copyOhlcTuplesRange(e, t, n, r, a = 0) {
331
+ if (!i(this.dataset) || r <= 0 || n.length < r * 5) return 0;
332
+ let o = Math.max(0, Math.floor(e)), s = Math.min(this.dataset.length, Math.ceil(t)), c = Math.min(r, Math.max(0, s - o));
333
+ for (let e = 0; e < c; e++) {
334
+ let t = o + e, r = e * 5;
335
+ n[r] = this.dataset.getX(t) - a, n[r + 1] = this.dataset.getOpen(t), n[r + 2] = this.dataset.getHigh(t), n[r + 3] = this.dataset.getLow(t), n[r + 4] = this.dataset.getClose(t);
336
+ }
337
+ return c;
338
+ }
339
+ visibleIndexRange(e, t = 0) {
340
+ if (!e) return {
264
341
  start: 0,
265
342
  end: this.dataset.length
266
343
  };
344
+ let n = Math.max(0, Math.floor(t));
345
+ return {
346
+ start: Math.max(0, this.dataset.lowerBoundX(e.xMin) - n),
347
+ end: Math.min(this.dataset.length, this.dataset.upperBoundX(e.xMax) + n)
348
+ };
267
349
  }
268
- copyVisibleSamples(e, t, n, r, i) {
269
- let a = r === "points" ? 2 : 4;
270
- if (n <= 0 || t.length < n * a) return 0;
271
- let o = this.dataset.lowerBoundX(e.xMin), s = this.dataset.upperBoundX(e.xMax), c = s - o;
272
- if (c <= 0) return 0;
273
- let l = Math.max(1, Math.ceil(c / n)), u = 0;
274
- for (let e = o; e < s && u < n; e += l) {
275
- let n = this.dataset.getX(e), a = this.dataset.getY(e);
350
+ pointXDistanceSq(e, t, n) {
351
+ let r = (this.dataset.getX(e) - t) * n;
352
+ return r * r;
353
+ }
354
+ pointIntervalDistanceSq(e, t, n, r, i, a) {
355
+ if (t <= e) return Infinity;
356
+ let o = this.dataset.getX(e), s = this.dataset.getX(t - 1), c = n < o ? (o - n) * i : n > s ? (n - s) * i : 0, l = this.pointIntervalMinMaxY(e, t);
357
+ if (!l) return Infinity;
358
+ let u = r < l.minY ? (l.minY - r) * a : r > l.maxY ? (r - l.maxY) * a : 0;
359
+ return c * c + u * u;
360
+ }
361
+ hasPointIntervalBounds() {
362
+ return r(this.dataset) || this.pyramid !== null && !this._dirty && !this._useRawMinMaxScan;
363
+ }
364
+ pointIntervalMinMaxY(e, t) {
365
+ return r(this.dataset) ? this.dataset.rangeMinMaxY(e, t) : this.pyramid && !this._dirty && !this._useRawMinMaxScan ? this.pyramid.rangeMinMax(this.dataset, e, t) : null;
366
+ }
367
+ copyClippedVisibleLine(e, t, n, r, i) {
368
+ if (n <= 0 || t.length < n * 2) return 0;
369
+ let a = e.xMax - e.xMin, o = e.yMax - e.yMin;
370
+ if (i === "clip" && (a <= 0 || o <= 0)) return 0;
371
+ let s = Math.max(0, this.dataset.lowerBoundX(e.xMin) - 1), c = Math.min(this.dataset.length, this.dataset.upperBoundX(e.xMax) + 1);
372
+ if (c - s <= 0) return 0;
373
+ let u = 0, d = NaN, f = NaN, p = (s, c) => {
374
+ let l = i === "clip" ? (s - e.xMin) / a * 2 - 1 : s - r, p = i === "clip" ? (c - e.yMin) / o * 2 - 1 : c;
375
+ if (u > 0 && l === d && p === f) return !0;
376
+ if (u >= n) return !1;
377
+ let m = u * 2;
378
+ return t[m] = l, t[m + 1] = p, u++, d = l, f = p, !0;
379
+ };
380
+ if (c - s === 1) {
381
+ let t = this.dataset.getX(s);
382
+ return t < e.xMin || t > e.xMax ? 0 : p(t, this.dataset.getY(s)) ? u : 0;
383
+ }
384
+ for (let t = s; t + 1 < c; t++) {
385
+ let n = this.dataset.getX(t), r = this.dataset.getY(t), i = this.dataset.getX(t + 1), a = this.dataset.getY(t + 1);
386
+ if (i < e.xMin || n > e.xMax) continue;
387
+ let o = Math.max(n, e.xMin), s = Math.min(i, e.xMax);
388
+ if (s < o) continue;
389
+ let c = l(n, r, i, a, o), u = l(n, r, i, a, s);
390
+ if (!p(o, c) || !p(s, u)) break;
391
+ }
392
+ return u;
393
+ }
394
+ copyVisibleSamples(e, t, n, r, i, a) {
395
+ if (s(this.dataset)) return this.dataset.copyVisibleSamples(e, t, n, r, i, a);
396
+ let o = r === "points" ? 2 : 4;
397
+ if (n <= 0 || t.length < n * o) return 0;
398
+ let c = this.dataset.lowerBoundX(e.xMin), l = this.dataset.upperBoundX(e.xMax), u = l - c;
399
+ if (u <= 0) return 0;
400
+ let d = Math.max(1, Math.ceil(u / n)), f = 0;
401
+ for (let e = c; e < l && f < n; e += d) {
402
+ let n = this.dataset.getX(e) - a, o = this.dataset.getY(e);
276
403
  if (r === "points") {
277
- let e = u * 2;
278
- t[e] = n, t[e + 1] = a;
404
+ let e = f * 2;
405
+ t[e] = n, t[e + 1] = o;
279
406
  } else {
280
- let e = u * 4;
281
- t[e] = n, t[e + 1] = i, t[e + 2] = n, t[e + 3] = a;
407
+ let e = f * 4;
408
+ t[e] = n, t[e + 1] = i, t[e + 2] = n, t[e + 3] = o;
282
409
  }
283
- u++;
410
+ f++;
284
411
  }
285
- return u;
286
- }
287
- copyMinMaxSegments(e, t, n, r) {
288
- let i = r === "line-list" ? 4 : 3;
289
- if (!this.pyramid || n <= 0 || t.length < n * i) return 0;
290
- let a = this.dataset.lowerBoundX(e.xMin), o = this.dataset.upperBoundX(e.xMax), s = o - a;
291
- if (s <= 0) return 0;
292
- let c = Math.min(n, s);
293
- for (let e = 0; e < c; e++) {
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;
412
+ return f;
413
+ }
414
+ copySampleRange(e, t, n, r, i, o, s) {
415
+ if (a(this.dataset)) return this.dataset.copySamplesRange(e, t, n, r, i, o, s);
416
+ let c = i === "points" ? 2 : 4;
417
+ if (r <= 0 || n.length < r * c) return 0;
418
+ let l = Math.max(0, Math.floor(e)), u = Math.min(this.dataset.length, Math.ceil(t)), d = Math.min(r, Math.max(0, u - l));
419
+ for (let e = 0; e < d; e++) {
420
+ let t = l + e, r = this.dataset.getX(t) - s, a = this.dataset.getY(t);
421
+ if (i === "points") {
422
+ let t = e * 2;
423
+ n[t] = r, n[t + 1] = a;
424
+ } else {
425
+ let t = e * 4;
426
+ n[t] = r, n[t + 1] = o, n[t + 2] = r, n[t + 3] = a;
427
+ }
428
+ }
429
+ return d;
430
+ }
431
+ copyMinMaxSegments(e, t, n, r, i) {
432
+ if (o(this.dataset)) return this.dataset.copyMinMaxSegments(e, t, n, r, i);
433
+ let a = r === "line-list" ? 4 : 3;
434
+ if (!this.pyramid || n <= 0 || t.length < n * a) return 0;
435
+ let s = this.dataset.lowerBoundX(e.xMin), c = this.dataset.upperBoundX(e.xMax), l = c - s;
436
+ if (l <= 0) return 0;
437
+ let u = Math.min(n, l);
438
+ for (let e = 0; e < u; e++) {
439
+ let n = s + Math.floor(e * l / u), a = s + Math.max(Math.floor((e + 1) * l / u), Math.floor(e * l / u) + 1), o = Math.min(c, a), d = this.minMaxForRange(n, o);
440
+ if (!d) continue;
441
+ let f = this.dataset.getX(n + (o - n >> 1)) - i, { minY: p, maxY: m } = d;
297
442
  if (r === "line-list") {
298
443
  let n = e * 4;
299
- t[n] = d, t[n + 1] = f, t[n + 2] = d, t[n + 3] = p;
444
+ t[n] = f, t[n + 1] = p, t[n + 2] = f, t[n + 3] = m;
300
445
  } else {
301
446
  let n = e * 3;
302
- t[n] = d, t[n + 1] = f, t[n + 2] = p;
447
+ t[n] = f, t[n + 1] = p, t[n + 2] = m;
303
448
  }
304
449
  }
305
- return c;
450
+ return u;
306
451
  }
307
452
  minMaxForRange(e, t) {
308
453
  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);
@@ -340,7 +485,28 @@ var i = class {
340
485
  maxY: o
341
486
  };
342
487
  }
343
- }, a = class e {
488
+ };
489
+ //#endregion
490
+ //#region src/core/search.ts
491
+ function d(e, t, n) {
492
+ let r = 0, i = e;
493
+ for (; r < i;) {
494
+ let e = r + (i - r >> 1);
495
+ t(e) < n ? r = e + 1 : i = e;
496
+ }
497
+ return r;
498
+ }
499
+ function f(e, t, n) {
500
+ let r = 0, i = e;
501
+ for (; r < i;) {
502
+ let e = r + (i - r >> 1);
503
+ t(e) <= n ? r = e + 1 : i = e;
504
+ }
505
+ return r;
506
+ }
507
+ //#endregion
508
+ //#region src/core/RingBuffer.ts
509
+ var p = class e {
344
510
  capacity;
345
511
  _length = 0;
346
512
  _head = 0;
@@ -349,9 +515,10 @@ var i = class {
349
515
  treeBase;
350
516
  minTree;
351
517
  maxTree;
352
- constructor(t) {
518
+ overflow;
519
+ constructor(t, n = {}) {
353
520
  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);
521
+ this.capacity = t, this.overflow = n.overflow ?? "wrap", 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);
355
522
  }
356
523
  get length() {
357
524
  return this._length;
@@ -363,20 +530,29 @@ var i = class {
363
530
  };
364
531
  }
365
532
  push(e, t) {
533
+ if (this._length >= this.capacity) {
534
+ if (this.overflow === "drop-new") return;
535
+ if (this.overflow === "error") throw RangeError("RingBuffer capacity exceeded.");
536
+ }
366
537
  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++;
367
538
  }
368
539
  append(e, t) {
369
540
  let n = Math.min(e.length, t.length);
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;
541
+ if (!(n <= 0)) {
542
+ if (this.overflow !== "wrap") {
543
+ let r = this.capacity - this._length;
544
+ if (n > r && this.overflow === "error") throw RangeError("RingBuffer capacity exceeded.");
545
+ let i = Math.min(n, r);
546
+ if (i <= 0) return;
547
+ this.appendNoWrap(e, t, 0, i);
548
+ return;
549
+ }
550
+ if (n >= this.capacity) {
551
+ let r = n - this.capacity;
552
+ this._head = 0, this._length = this.capacity, this.copyIntoPhysical(0, e, t, r, this.capacity);
553
+ return;
554
+ }
555
+ this.appendNoWrap(e, t, 0, n);
380
556
  }
381
557
  }
382
558
  get(e) {
@@ -392,20 +568,10 @@ var i = class {
392
568
  return this.assertValidIndex(e), this.yData[this.logicalToPhysical(e)];
393
569
  }
394
570
  lowerBoundX(e) {
395
- let t = 0, n = this._length;
396
- for (; t < n;) {
397
- let r = t + (n - t >> 1);
398
- this.getX(r) < e ? t = r + 1 : n = r;
399
- }
400
- return t;
571
+ return d(this._length, (e) => this.getX(e), e);
401
572
  }
402
573
  upperBoundX(e) {
403
- let t = 0, n = this._length;
404
- for (; t < n;) {
405
- let r = t + (n - t >> 1);
406
- this.getX(r) <= e ? t = r + 1 : n = r;
407
- }
408
- return t;
574
+ return f(this._length, (e) => this.getX(e), e);
409
575
  }
410
576
  rangeMinMaxY(e, t) {
411
577
  let n = Math.max(0, Math.floor(e)), r = Math.min(this._length, Math.ceil(t));
@@ -421,6 +587,13 @@ var i = class {
421
587
  clear() {
422
588
  this._length = 0, this._head = 0, this.minTree.fill(Infinity), this.maxTree.fill(-Infinity);
423
589
  }
590
+ appendNoWrap(e, t, n, r) {
591
+ let i = n, a = r;
592
+ for (; a > 0;) {
593
+ let n = Math.min(a, this.capacity - this._head);
594
+ this.copyIntoPhysical(this._head, e, t, i, n), this._head = (this._head + n) % this.capacity, this._length = Math.min(this.capacity, this._length + n), i += n, a -= n;
595
+ }
596
+ }
424
597
  copyIntoPhysical(e, t, n, r, i) {
425
598
  for (let a = 0; a < i; a++) {
426
599
  let i = e + a, o = n[r + a];
@@ -475,32 +648,32 @@ var i = class {
475
648
  static nextPowerOfTwo(e) {
476
649
  return 2 ** Math.ceil(Math.log2(e));
477
650
  }
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", _ = {
651
+ }, m = "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", h = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", g = "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", _ = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", v = "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", y = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", ee = "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", te = "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", ne = "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", re = "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", b = "precision mediump float;\n\nuniform vec4 uColor;\n\nvoid main() {\n gl_FragColor = uColor;\n}\n", x = {
479
652
  line: {
480
- vert: o,
481
- frag: s
653
+ vert: m,
654
+ frag: h
482
655
  },
483
656
  segment: {
484
- vert: c,
485
- frag: l
657
+ vert: g,
658
+ frag: _
486
659
  },
487
660
  point: {
488
- vert: u,
489
- frag: d
661
+ vert: v,
662
+ frag: y
490
663
  },
491
664
  pointSprite: {
492
- vert: f,
493
- frag: p
665
+ vert: ee,
666
+ frag: te
494
667
  },
495
668
  bar: {
496
- vert: m,
497
- frag: g
669
+ vert: ne,
670
+ frag: b
498
671
  },
499
672
  barRange: {
500
- vert: h,
501
- frag: g
673
+ vert: re,
674
+ frag: b
502
675
  }
503
- }, v = 3, y = 2, b = 4, x = 4, S = .8, C = 0, ee = class {
676
+ }, S = 3, C = 2, w = 4, T = 4, E = .8, D = 0, O = class {
504
677
  backend;
505
678
  lineProgram;
506
679
  segmentProgram;
@@ -514,8 +687,9 @@ var i = class {
514
687
  scaleUniform = new Float32Array(2);
515
688
  offsetUniform = new Float32Array(2);
516
689
  canvasSizeUniform = new Float32Array(2);
690
+ xOrigin = 0;
517
691
  constructor(e) {
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({
692
+ this.backend = e, this.lineProgram = this.backend.createProgram(x.line.vert, x.line.frag), this.segmentProgram = this.backend.createProgram(x.segment.vert, x.segment.frag), this.pointProgram = this.backend.createProgram(x.point.vert, x.point.frag), this.pointSpriteProgram = this.backend.createProgram(x.pointSprite.vert, x.pointSprite.frag), this.barProgram = this.backend.createProgram(x.bar.vert, x.bar.frag), this.barRangeProgram = this.backend.createProgram(x.barRange.vert, x.barRange.frag), this.segmentSelectBuffer = this.backend.createBuffer({
519
693
  usage: "static",
520
694
  type: "float",
521
695
  length: 2
@@ -566,24 +740,34 @@ var i = class {
566
740
  length: e
567
741
  });
568
742
  }
569
- updateFloatBuffer(e, t) {
570
- this.backend.updateBuffer(e, t);
743
+ updateFloatBuffer(e, t, n = t.length) {
744
+ let r = Math.max(0, Math.min(n, t.length));
745
+ this.backend.updateBuffer(e, r === t.length ? t : t.subarray(0, r));
571
746
  }
572
747
  viewport(e, t, n, r) {
573
748
  this.backend.viewport(e, t, n, r);
574
749
  }
750
+ setXOrigin(e) {
751
+ this.xOrigin = Number.isFinite(e) ? e : 0;
752
+ }
575
753
  drawLines(e, t, n, r) {
576
754
  this.drawLinePrimitive("lines", e, t, n, r);
577
755
  }
578
756
  drawLineStrip(e, t, n, r) {
579
757
  this.drawLinePrimitive("line_strip", e, t, n, r);
580
758
  }
759
+ drawClipLineStrip(e, t, n) {
760
+ this.drawClipPrimitive("line_strip", e, t, n);
761
+ }
762
+ drawClipLines(e, t, n) {
763
+ this.drawClipPrimitive("lines", e, t, n);
764
+ }
581
765
  drawMinMaxSegments(e, t, n, r) {
582
766
  this.drawLines(e, t, n, r);
583
767
  }
584
768
  drawMinMaxSegmentsInstanced(e, t, n, r) {
585
769
  this.writeCameraUniforms(r);
586
- let i = v * b, a = {
770
+ let i = S * w, a = {
587
771
  buffer: e,
588
772
  divisor: 1,
589
773
  stride: i,
@@ -592,16 +776,16 @@ var i = class {
592
776
  buffer: e,
593
777
  divisor: 1,
594
778
  stride: i,
595
- offset: b
779
+ offset: w
596
780
  }, s = {
597
781
  buffer: e,
598
782
  divisor: 1,
599
783
  stride: i,
600
- offset: b * 2
784
+ offset: w * 2
601
785
  }, c = {
602
786
  buffer: this.segmentSelectBuffer,
603
787
  divisor: 0,
604
- stride: b,
788
+ stride: w,
605
789
  offset: 0
606
790
  };
607
791
  this.backend.draw({
@@ -622,18 +806,21 @@ var i = class {
622
806
  }
623
807
  });
624
808
  }
809
+ drawPoints(e, t, n, r, i, a) {
810
+ this.supportsInstancedPoints ? this.drawPointsInstanced(e, t, n, r, i, a) : this.drawPointSprites(e, t, n, r);
811
+ }
625
812
  drawPointsInstanced(e, t, n, r, i, a) {
626
813
  this.writeCameraUniforms(r), this.canvasSizeUniform[0] = Math.max(1, i), this.canvasSizeUniform[1] = Math.max(1, a);
627
814
  let o = {
628
815
  buffer: e,
629
816
  divisor: 1,
630
- stride: y * b,
817
+ stride: C * w,
631
818
  offset: 0,
632
819
  size: 2
633
820
  }, s = {
634
821
  buffer: this.pointCornerBuffer,
635
822
  divisor: 0,
636
- stride: y * b,
823
+ stride: C * w,
637
824
  offset: 0,
638
825
  size: 2
639
826
  };
@@ -650,7 +837,7 @@ var i = class {
650
837
  uScale: this.scaleUniform,
651
838
  uOffset: this.offsetUniform,
652
839
  uCanvasSize: this.canvasSizeUniform,
653
- uPointSize: n.pointSize ?? x,
840
+ uPointSize: n.pointSize ?? T,
654
841
  uColor: n.color
655
842
  }
656
843
  });
@@ -664,7 +851,7 @@ var i = class {
664
851
  uniforms: {
665
852
  uScale: this.scaleUniform,
666
853
  uOffset: this.offsetUniform,
667
- uPointSize: n.pointSize ?? x,
854
+ uPointSize: n.pointSize ?? T,
668
855
  uColor: n.color
669
856
  }
670
857
  });
@@ -687,13 +874,13 @@ var i = class {
687
874
  let i = {
688
875
  buffer: e,
689
876
  divisor: 1,
690
- stride: y * b,
877
+ stride: C * w,
691
878
  offset: 0,
692
879
  size: 2
693
880
  }, a = {
694
881
  buffer: this.barCornerBuffer,
695
882
  divisor: 0,
696
- stride: y * b,
883
+ stride: C * w,
697
884
  offset: 0,
698
885
  size: 2
699
886
  };
@@ -709,15 +896,15 @@ var i = class {
709
896
  uniforms: {
710
897
  uScale: this.scaleUniform,
711
898
  uOffset: this.offsetUniform,
712
- uBarWidth: n.barWidth ?? S,
713
- uBaseline: n.baseline ?? C,
899
+ uBarWidth: n.barWidth ?? E,
900
+ uBaseline: n.baseline ?? D,
714
901
  uColor: n.color
715
902
  }
716
903
  });
717
904
  }
718
905
  drawBarRangesInstanced(e, t, n, r) {
719
906
  this.writeCameraUniforms(r);
720
- let i = v * b, a = {
907
+ let i = S * w, a = {
721
908
  buffer: e,
722
909
  divisor: 1,
723
910
  stride: i,
@@ -726,16 +913,16 @@ var i = class {
726
913
  buffer: e,
727
914
  divisor: 1,
728
915
  stride: i,
729
- offset: b
916
+ offset: w
730
917
  }, s = {
731
918
  buffer: e,
732
919
  divisor: 1,
733
920
  stride: i,
734
- offset: b * 2
921
+ offset: w * 2
735
922
  }, c = {
736
923
  buffer: this.barCornerBuffer,
737
924
  divisor: 0,
738
- stride: y * b,
925
+ stride: C * w,
739
926
  offset: 0,
740
927
  size: 2
741
928
  };
@@ -753,7 +940,7 @@ var i = class {
753
940
  uniforms: {
754
941
  uScale: this.scaleUniform,
755
942
  uOffset: this.offsetUniform,
756
- uBarWidth: n.barWidth ?? S,
943
+ uBarWidth: n.barWidth ?? E,
757
944
  uColor: n.color
758
945
  }
759
946
  });
@@ -787,19 +974,33 @@ var i = class {
787
974
  }
788
975
  });
789
976
  }
977
+ drawClipPrimitive(e, t, n, r) {
978
+ this.scaleUniform[0] = 1, this.scaleUniform[1] = 1, this.offsetUniform[0] = 0, this.offsetUniform[1] = 0, this.backend.draw({
979
+ program: this.lineProgram,
980
+ primitive: e,
981
+ count: n,
982
+ attributes: { position: t },
983
+ uniforms: {
984
+ uScale: this.scaleUniform,
985
+ uOffset: this.offsetUniform,
986
+ uColor: r.color
987
+ }
988
+ });
989
+ }
790
990
  writeCameraUniforms(e) {
791
- this.scaleUniform[0] = e.xScale, this.scaleUniform[1] = e.yScale, this.offsetUniform[0] = e.xOffset, this.offsetUniform[1] = e.yOffset;
991
+ let t = e.xMin - this.xOrigin, n = e.xMax - this.xOrigin;
992
+ this.scaleUniform[0] = e.xScale, this.scaleUniform[1] = e.yScale, this.offsetUniform[0] = -(t + n) / (n - t), this.offsetUniform[1] = e.yOffset;
792
993
  }
793
994
  dispose() {
794
995
  this.backend.destroy();
795
996
  }
796
- }, w = [
997
+ }, k = [
797
998
  1024,
798
999
  4096,
799
1000
  16384,
800
1001
  32768,
801
1002
  131072
802
- ], te = class {
1003
+ ], ie = class {
803
1004
  regl;
804
1005
  pool = [];
805
1006
  preAllocated = !1;
@@ -812,7 +1013,7 @@ var i = class {
812
1013
  preAllocate() {
813
1014
  if (!this.preAllocated) {
814
1015
  this.preAllocated = !0;
815
- for (let e of w) this.pool.push(this.createEntry(e, "stream"));
1016
+ for (let e of k) this.pool.push(this.createEntry(e, "stream"));
816
1017
  }
817
1018
  }
818
1019
  acquire(e, t = "stream") {
@@ -852,17 +1053,17 @@ var i = class {
852
1053
  return this.pool.find((t) => !t.inUse && t.floatCapacity >= e);
853
1054
  }
854
1055
  roundUp(e) {
855
- for (let t of w) if (t >= e) return t;
856
- let t = w[w.length - 1], n = 1 << 32 - Math.clz32(e - 1);
1056
+ for (let t of k) if (t >= e) return t;
1057
+ let t = k[k.length - 1], n = 1 << 32 - Math.clz32(e - 1);
857
1058
  return Math.max(t * 2, n);
858
1059
  }
859
1060
  };
860
1061
  //#endregion
861
1062
  //#region src/render/ReglBackend.ts
862
- function ne(e) {
1063
+ function ae(e) {
863
1064
  return e;
864
1065
  }
865
- var T = class {
1066
+ var oe = class {
866
1067
  gl;
867
1068
  regl;
868
1069
  resources;
@@ -882,10 +1083,10 @@ var T = class {
882
1083
  });
883
1084
  if (!n) throw Error("BlazePlot requires WebGL2, but this browser/context does not support it.");
884
1085
  this.gl = n, this.regl = e({
885
- gl: ne(this.gl),
1086
+ gl: ae(this.gl),
886
1087
  extensions: [],
887
1088
  optionalExtensions: ["angle_instanced_arrays", "ext_disjoint_timer_query_webgl2"]
888
- }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new te(this.regl), this.resources.preAllocate();
1089
+ }), this.capabilities = { instancing: this.regl.hasExtension("angle_instanced_arrays") }, this.resources = new ie(this.regl), this.resources.preAllocate();
889
1090
  }
890
1091
  createBuffer(e) {
891
1092
  let { buffer: t } = this.resources.acquire(e.length, e.usage);
@@ -1004,7 +1205,7 @@ var T = class {
1004
1205
  default: return e;
1005
1206
  }
1006
1207
  }
1007
- }, E = class e {
1208
+ }, A = class e {
1008
1209
  _xMin = 0;
1009
1210
  _xMax = 1;
1010
1211
  _yMin = 0;
@@ -1089,7 +1290,7 @@ var T = class {
1089
1290
  static assertFinite(e, t) {
1090
1291
  if (!Number.isFinite(t)) throw RangeError(`Camera2D ${e} must be finite.`);
1091
1292
  }
1092
- }, D = class {
1293
+ }, j = class {
1093
1294
  camera;
1094
1295
  constructor(e) {
1095
1296
  this.camera = e;
@@ -1121,33 +1322,39 @@ var T = class {
1121
1322
  let n = Math.max(0, -Math.floor(Math.log10(t)) + 2), r = Number(e.toFixed(n));
1122
1323
  return Object.is(r, -0) ? 0 : r;
1123
1324
  }
1124
- }, O = class {
1325
+ }, M = class {
1125
1326
  layout;
1126
1327
  config;
1127
1328
  options;
1128
1329
  xPool = [];
1129
1330
  yPool = [];
1331
+ y2Pool = [];
1130
1332
  xTicks = [];
1131
1333
  yTicks = [];
1334
+ y2Ticks = [];
1132
1335
  constructor(e, t, n = {}) {
1133
1336
  this.layout = e, this.config = t, this.options = n;
1134
1337
  }
1135
1338
  setOptions(e) {
1136
1339
  this.options = e;
1137
- for (let e of this.xPool) e.style.font = this.options.font ?? "11px ui-monospace, monospace, sans-serif", e.style.color = this.options.color ?? "#bfd6ff";
1138
- for (let e of this.yPool) e.style.font = this.options.font ?? "11px ui-monospace, monospace, sans-serif", e.style.color = this.options.color ?? "#bfd6ff";
1340
+ for (let e of [
1341
+ ...this.xPool,
1342
+ ...this.yPool,
1343
+ ...this.y2Pool
1344
+ ]) e.style.font = this.options.font ?? "11px ui-monospace, monospace, sans-serif", e.style.color = this.options.color ?? "#bfd6ff";
1139
1345
  }
1140
- update(e, t) {
1141
- let n = Math.max(1, this.layout.plot.clientWidth), r = Math.max(1, this.layout.plot.clientHeight);
1142
- this.config.x.visible ? t.getXTickValues(n, 12, this.xTicks) : this.xTicks.length = 0, this.config.y.visible ? t.getYTickValues(r, 8, this.yTicks) : this.yTicks.length = 0, this.updateAxis(this.xPool, this.xTicks, "x", e, n, r, t), this.updateAxis(this.yPool, this.yTicks, "y", e, n, r, t);
1346
+ update(e, t, n = e, r = t) {
1347
+ let i = Math.max(1, this.layout.plot.clientWidth), a = Math.max(1, this.layout.plot.clientHeight);
1348
+ this.config.x.visible ? t.getXTickValues(i, 12, this.xTicks) : this.xTicks.length = 0, this.config.y.visible ? t.getYTickValues(a, 8, this.yTicks) : this.yTicks.length = 0, this.config.y2.visible ? r.getYTickValues(a, 8, this.y2Ticks) : this.y2Ticks.length = 0, this.updateAxis(this.xPool, this.xTicks, "x", e, i, a, t), this.updateAxis(this.yPool, this.yTicks, "y", e, i, a, t), this.updateAxis(this.y2Pool, this.y2Ticks, "y2", n, i, a, r);
1143
1349
  }
1144
1350
  dispose() {
1145
1351
  for (let e of this.xPool) e.remove();
1146
1352
  for (let e of this.yPool) e.remove();
1147
- this.xPool = [], this.yPool = [];
1353
+ for (let e of this.y2Pool) e.remove();
1354
+ this.xPool = [], this.yPool = [], this.y2Pool = [];
1148
1355
  }
1149
1356
  parentForAxis(e) {
1150
- return e === "x" ? this.config.x.position === "outside" ? this.layout.xAxis : this.layout.plot : this.config.y.position === "outside" ? this.layout.yAxis : this.layout.plot;
1357
+ return e === "x" ? this.config.x.position === "outside" ? this.layout.xAxis : this.layout.plot : e === "y2" ? this.config.y2.position === "outside" ? this.layout.y2Axis : this.layout.plot : this.config.y.position === "outside" ? this.layout.yAxis : this.layout.plot;
1151
1358
  }
1152
1359
  updateAxis(e, t, n, r, i, a, o) {
1153
1360
  let s = this.parentForAxis(n);
@@ -1163,39 +1370,41 @@ var T = class {
1163
1370
  let [e] = r.toClip(l, r.yMin), t = (e + 1) * .5 * i;
1164
1371
  c.style.left = `${t}px`, c.style.right = "auto", c.style.transform = "translateX(-50%)", this.config.x.position === "outside" ? (c.style.top = "4px", c.style.bottom = "auto") : (c.style.top = "auto", c.style.bottom = "4px");
1165
1372
  } else {
1166
- let [, e] = r.toClip(r.xMin, l), t = (1 - e) * .5 * a;
1167
- c.style.top = `${t}px`, c.style.bottom = "auto", c.style.transform = "translateY(-50%)", this.config.y.position === "outside" ? (c.style.left = "auto", c.style.right = "4px") : (c.style.left = "4px", c.style.right = "auto");
1373
+ let e = n === "y2", t = e ? this.config.y2 : this.config.y, [, i] = r.toClip(r.xMin, l), o = (1 - i) * .5 * a;
1374
+ c.style.top = `${o}px`, c.style.bottom = "auto", c.style.transform = "translateY(-50%)", t.position === "outside" ? (c.style.left = e ? "4px" : "auto", c.style.right = e ? "auto" : "4px") : (c.style.left = e ? "auto" : "4px", c.style.right = e ? "4px" : "auto");
1168
1375
  }
1169
1376
  }
1170
1377
  }
1171
- }, k = class {
1378
+ }, se = class {
1172
1379
  root;
1173
1380
  plot;
1174
1381
  canvas;
1175
1382
  xAxis;
1176
1383
  yAxis;
1384
+ y2Axis;
1177
1385
  corner;
1386
+ cornerRight;
1178
1387
  externalCanvas;
1179
1388
  originalCanvasCssText;
1180
1389
  originalCanvasParent;
1181
1390
  constructor(e, t) {
1182
1391
  let n = e instanceof HTMLCanvasElement ? e : null;
1183
- this.externalCanvas = n !== null, this.originalCanvasCssText = n?.style.cssText ?? "", this.originalCanvasParent = n?.parentElement ?? null, this.root = document.createElement("div"), this.plot = document.createElement("div"), this.canvas = n ?? document.createElement("canvas"), this.xAxis = document.createElement("div"), this.yAxis = document.createElement("div"), this.corner = document.createElement("div"), this.root.className = "blazeplot-root", this.plot.className = "blazeplot-plot", this.canvas.classList.add("blazeplot-canvas"), this.xAxis.className = "blazeplot-axis blazeplot-axis-x", this.yAxis.className = "blazeplot-axis blazeplot-axis-y", this.corner.className = "blazeplot-axis-corner", this.applyBaseStyles(), this.mount(e), this.update(t);
1392
+ this.externalCanvas = n !== null, this.originalCanvasCssText = n?.style.cssText ?? "", this.originalCanvasParent = n?.parentElement ?? null, this.root = document.createElement("div"), this.plot = document.createElement("div"), this.canvas = n ?? document.createElement("canvas"), this.xAxis = document.createElement("div"), this.yAxis = document.createElement("div"), this.y2Axis = document.createElement("div"), this.corner = document.createElement("div"), this.cornerRight = document.createElement("div"), this.root.className = "blazeplot-root", this.plot.className = "blazeplot-plot", this.canvas.classList.add("blazeplot-canvas"), this.xAxis.className = "blazeplot-axis blazeplot-axis-x", this.yAxis.className = "blazeplot-axis blazeplot-axis-y", this.y2Axis.className = "blazeplot-axis blazeplot-axis-y2", this.corner.className = "blazeplot-axis-corner", this.cornerRight.className = "blazeplot-axis-corner blazeplot-axis-corner-right", this.applyBaseStyles(), this.mount(e), this.update(t);
1184
1393
  }
1185
1394
  update(e) {
1186
- let t = e.y.visible && e.y.position === "outside", n = e.x.visible && e.x.position === "outside";
1187
- this.root.style.gridTemplateColumns = `${t ? 52 : 0}px minmax(0, 1fr)`, this.root.style.gridTemplateRows = `minmax(0, 1fr) ${n ? 28 : 0}px`, this.yAxis.style.display = t ? "block" : "none", this.xAxis.style.display = n ? "block" : "none", this.corner.style.display = n && t ? "block" : "none";
1395
+ let t = e.y.visible && e.y.position === "outside", n = e.y2.visible && e.y2.position === "outside", r = e.x.visible && e.x.position === "outside";
1396
+ this.root.style.gridTemplateColumns = `${t ? 52 : 0}px minmax(0, 1fr) ${n ? 52 : 0}px`, this.root.style.gridTemplateRows = `minmax(0, 1fr) ${r ? 28 : 0}px`, this.yAxis.style.display = t ? "block" : "none", this.y2Axis.style.display = n ? "block" : "none", this.xAxis.style.display = r ? "block" : "none", this.corner.style.display = r && t ? "block" : "none", this.cornerRight.style.display = r && n ? "block" : "none";
1188
1397
  }
1189
1398
  dispose() {
1190
1399
  this.externalCanvas && this.originalCanvasParent && (this.canvas.style.cssText = this.originalCanvasCssText, this.originalCanvasParent.insertBefore(this.canvas, this.root)), this.root.remove();
1191
1400
  }
1192
1401
  mount(e) {
1193
- 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);
1402
+ 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.y2Axis), this.root.appendChild(this.corner), this.root.appendChild(this.xAxis), this.root.appendChild(this.cornerRight), this.plot.appendChild(this.canvas);
1194
1403
  }
1195
1404
  applyBaseStyles() {
1196
- 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";
1405
+ 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.y2Axis.style.position = "relative", this.y2Axis.style.gridColumn = "3", this.y2Axis.style.gridRow = "1", this.y2Axis.style.minWidth = "0", this.y2Axis.style.minHeight = "0", this.y2Axis.style.overflow = "hidden", this.y2Axis.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", this.cornerRight.style.gridColumn = "3", this.cornerRight.style.gridRow = "2", this.cornerRight.style.minWidth = "0", this.cornerRight.style.minHeight = "0", this.cornerRight.style.pointerEvents = "none";
1197
1406
  }
1198
- }, A = {
1407
+ }, N = {
1199
1408
  backgroundColor: [
1200
1409
  .08,
1201
1410
  .1,
@@ -1258,39 +1467,39 @@ var T = class {
1258
1467
  legendMutedTextColor: "#789",
1259
1468
  legendFont: "11px/1.35 ui-monospace, monospace"
1260
1469
  };
1261
- function j(e, t) {
1262
- if (!e) return A;
1263
- let n = M(e.backgroundColor, A.backgroundColor, t), r = e.seriesColors?.length ? e.seriesColors.map((e, n) => M(e, A.seriesColors[n % A.seriesColors.length], t)) : A.seriesColors;
1470
+ function P(e, t) {
1471
+ if (!e) return N;
1472
+ let n = F(e.backgroundColor, N.backgroundColor, t), r = e.seriesColors?.length ? e.seriesColors.map((e, n) => F(e, N.seriesColors[n % N.seriesColors.length], t)) : N.seriesColors;
1264
1473
  return {
1265
1474
  backgroundColor: n,
1266
- backgroundCssColor: N(e.backgroundColor, A.backgroundCssColor),
1267
- gridColor: M(e.gridColor, A.gridColor, t),
1268
- axisColor: e.axisColor ?? A.axisColor,
1269
- axisFont: e.axisFont ?? A.axisFont,
1475
+ backgroundCssColor: ce(e.backgroundColor, N.backgroundCssColor),
1476
+ gridColor: F(e.gridColor, N.gridColor, t),
1477
+ axisColor: e.axisColor ?? N.axisColor,
1478
+ axisFont: e.axisFont ?? N.axisFont,
1270
1479
  seriesColors: r,
1271
- tooltipBackgroundColor: e.tooltipBackgroundColor ?? A.tooltipBackgroundColor,
1272
- tooltipTextColor: e.tooltipTextColor ?? A.tooltipTextColor,
1273
- tooltipFont: e.tooltipFont ?? A.tooltipFont,
1274
- legendBackgroundColor: e.legendBackgroundColor ?? A.legendBackgroundColor,
1275
- legendBorderColor: e.legendBorderColor ?? A.legendBorderColor,
1276
- legendTextColor: e.legendTextColor ?? A.legendTextColor,
1277
- legendMutedTextColor: e.legendMutedTextColor ?? A.legendMutedTextColor,
1278
- legendFont: e.legendFont ?? A.legendFont
1480
+ tooltipBackgroundColor: e.tooltipBackgroundColor ?? N.tooltipBackgroundColor,
1481
+ tooltipTextColor: e.tooltipTextColor ?? N.tooltipTextColor,
1482
+ tooltipFont: e.tooltipFont ?? N.tooltipFont,
1483
+ legendBackgroundColor: e.legendBackgroundColor ?? N.legendBackgroundColor,
1484
+ legendBorderColor: e.legendBorderColor ?? N.legendBorderColor,
1485
+ legendTextColor: e.legendTextColor ?? N.legendTextColor,
1486
+ legendMutedTextColor: e.legendMutedTextColor ?? N.legendMutedTextColor,
1487
+ legendFont: e.legendFont ?? N.legendFont
1279
1488
  };
1280
1489
  }
1281
- function M(e, t, n) {
1490
+ function F(e, t, n) {
1282
1491
  if (!e) return t;
1283
1492
  if (typeof e != "string") return e;
1284
- let r = F(e, n), i = L(r ?? e, n);
1285
- return I(r ?? e) ?? I(i ?? "") ?? t;
1493
+ let r = le(e, n), i = ue(r ?? e, n);
1494
+ return L(r ?? e) ?? L(i ?? "") ?? t;
1286
1495
  }
1287
- function N(e, t) {
1288
- return e ? typeof e == "string" ? e : P(e) : t;
1496
+ function ce(e, t) {
1497
+ return e ? typeof e == "string" ? e : I(e) : t;
1289
1498
  }
1290
- function P(e) {
1499
+ function I(e) {
1291
1500
  return `rgba(${Math.round(e[0] * 255)}, ${Math.round(e[1] * 255)}, ${Math.round(e[2] * 255)}, ${e[3]})`;
1292
1501
  }
1293
- function F(e, t) {
1502
+ function le(e, t) {
1294
1503
  let n = t?.ownerDocument ?? globalThis.document;
1295
1504
  if (!n?.documentElement || typeof getComputedStyle > "u") return null;
1296
1505
  let r = t instanceof HTMLElement ? t : n.documentElement, i = n.createElement("span");
@@ -1298,11 +1507,11 @@ function F(e, t) {
1298
1507
  let a = getComputedStyle(i).color;
1299
1508
  return i.remove(), a || null;
1300
1509
  }
1301
- function I(e) {
1510
+ function L(e) {
1302
1511
  let t = e.trim();
1303
- return R(t) ?? z(t) ?? B(t);
1512
+ return de(t) ?? R(t) ?? z(t);
1304
1513
  }
1305
- function L(e, t) {
1514
+ function ue(e, t) {
1306
1515
  let n = t?.ownerDocument ?? globalThis.document;
1307
1516
  if (!n?.createElement) return null;
1308
1517
  let r = n.createElement("canvas").getContext("2d");
@@ -1312,12 +1521,12 @@ function L(e, t) {
1312
1521
  let a = String(r.fillStyle);
1313
1522
  return a === i ? null : a;
1314
1523
  }
1315
- function R(e) {
1524
+ function de(e) {
1316
1525
  let t = e.match(/^rgba?\((.*)\)$/i);
1317
1526
  if (!t) return null;
1318
1527
  let n = t[1].trim().split("/").map((e) => e.trim()), r = n[0], i = n[1], a = r.includes(",") ? r.split(",").map((e) => e.trim()).filter(Boolean) : r.split(/\s+/).filter(Boolean);
1319
1528
  if (a.length < 3) return null;
1320
- let o = V(a[0]), s = V(a[1]), c = V(a[2]), l = U(i ?? (a.length > 3 ? a[3] : void 0));
1529
+ let o = B(a[0]), s = B(a[1]), c = B(a[2]), l = H(i ?? (a.length > 3 ? a[3] : void 0));
1321
1530
  return o === null || s === null || c === null || l === null ? null : [
1322
1531
  o,
1323
1532
  s,
@@ -1325,12 +1534,12 @@ function R(e) {
1325
1534
  l
1326
1535
  ];
1327
1536
  }
1328
- function z(e) {
1537
+ function R(e) {
1329
1538
  let t = e.match(/^color\(\s*srgb\s+(.+)\)$/i);
1330
1539
  if (!t) return null;
1331
1540
  let n = t[1].split("/").map((e) => e.trim()), r = n[0].split(/\s+/).filter(Boolean);
1332
1541
  if (r.length < 3) return null;
1333
- let i = H(r[0]), a = H(r[1]), o = H(r[2]), s = U(n[1]);
1542
+ let i = V(r[0]), a = V(r[1]), o = V(r[2]), s = H(n[1]);
1334
1543
  return i === null || a === null || o === null || s === null ? null : [
1335
1544
  i,
1336
1545
  a,
@@ -1338,7 +1547,7 @@ function z(e) {
1338
1547
  s
1339
1548
  ];
1340
1549
  }
1341
- function B(e) {
1550
+ function z(e) {
1342
1551
  let t = e.startsWith("#") ? e.slice(1) : "";
1343
1552
  if (![
1344
1553
  3,
@@ -1354,21 +1563,21 @@ function B(e) {
1354
1563
  n.length === 8 ? (r & 255) / 255 : 1
1355
1564
  ] : null;
1356
1565
  }
1566
+ function B(e) {
1567
+ return e.endsWith("%") ? U(Number.parseFloat(e) / 100) : U(Number.parseFloat(e) / 255);
1568
+ }
1357
1569
  function V(e) {
1358
- return e.endsWith("%") ? W(Number.parseFloat(e) / 100) : W(Number.parseFloat(e) / 255);
1570
+ return e.endsWith("%") ? U(Number.parseFloat(e) / 100) : U(Number.parseFloat(e));
1359
1571
  }
1360
1572
  function H(e) {
1361
- return e.endsWith("%") ? W(Number.parseFloat(e) / 100) : W(Number.parseFloat(e));
1573
+ return e ? e.endsWith("%") ? U(Number.parseFloat(e) / 100) : U(Number.parseFloat(e)) : 1;
1362
1574
  }
1363
1575
  function U(e) {
1364
- return e ? e.endsWith("%") ? W(Number.parseFloat(e) / 100) : W(Number.parseFloat(e)) : 1;
1365
- }
1366
- function W(e) {
1367
1576
  return Number.isFinite(e) ? Math.min(1, Math.max(0, e)) : null;
1368
1577
  }
1369
1578
  //#endregion
1370
1579
  //#region src/ui/Chart.ts
1371
- var G = 16384, K = G >> 1, q = G >> 1, J = 3, Y = 4096, X = 12, Z = 64;
1580
+ var W = 16384, G = W >> 1, K = W >> 1, q = 3, J = 4096, Y = 12, fe = 12, X = 5, Z = 64;
1372
1581
  function Q(e) {
1373
1582
  return e === !1 ? {
1374
1583
  visible: !1,
@@ -1390,6 +1599,10 @@ function $(e) {
1390
1599
  y: {
1391
1600
  visible: !1,
1392
1601
  position: "inside"
1602
+ },
1603
+ y2: {
1604
+ visible: !1,
1605
+ position: "inside"
1393
1606
  }
1394
1607
  } : e === !0 || e === void 0 ? {
1395
1608
  x: {
@@ -1399,17 +1612,24 @@ function $(e) {
1399
1612
  y: {
1400
1613
  visible: !0,
1401
1614
  position: "inside"
1615
+ },
1616
+ y2: {
1617
+ visible: !1,
1618
+ position: "inside"
1402
1619
  }
1403
1620
  } : {
1404
1621
  x: Q(e.x),
1405
- y: Q(e.y)
1622
+ y: Q(e.y),
1623
+ y2: Q(e.y2 ?? !1)
1406
1624
  };
1407
1625
  }
1408
- var re = class {
1626
+ var pe = class {
1409
1627
  options;
1410
1628
  series = [];
1411
1629
  camera;
1630
+ rightCamera;
1412
1631
  axis;
1632
+ rightAxis;
1413
1633
  renderer;
1414
1634
  rawLineBuffer;
1415
1635
  rawLineData;
@@ -1445,6 +1665,7 @@ var re = class {
1445
1665
  lastPointerClientY = 0;
1446
1666
  pointerInPlot = !1;
1447
1667
  lastFrameAt = 0;
1668
+ currentXOrigin = 0;
1448
1669
  _rafId = 0;
1449
1670
  handlePointerMove = (e) => {
1450
1671
  this.pointerInPlot = !0, this.lastPointerClientX = e.clientX, this.lastPointerClientY = e.clientY, this.refreshHover();
@@ -1453,10 +1674,10 @@ var re = class {
1453
1674
  this.pointerInPlot = !1, this.emitHover(null);
1454
1675
  };
1455
1676
  constructor(e, t = {}) {
1456
- this.options = t, this.resolvedTheme = j(t.theme, e), this.normalizedAxes = $(t.axes), this._gridVisible = t.grid !== !1, this.layout = new k(e, this.normalizedAxes), this.layout.root.style.background = this.resolvedTheme.backgroundCssColor, this.applyCanvasSize(), this.camera = new E(), this.axis = new D(this.camera), this.renderer = new ee(new T(this.layout.canvas)), this.rawLineData = new Float32Array(G * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.minMaxInstanceData = new Float32Array(q * J), this.minMaxInstanceBuffer = this.renderer.createFloatBuffer(this.minMaxInstanceData.length), this.barTriangleData = new Float32Array(Y * X), this.barTriangleBuffer = this.renderer.createFloatBuffer(this.barTriangleData.length), this.gridData = new Float32Array(Z * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
1677
+ this.options = t, this.resolvedTheme = P(t.theme, e), this.normalizedAxes = $(t.axes), this._gridVisible = t.grid !== !1, this.layout = new se(e, this.normalizedAxes), this.layout.root.style.background = this.resolvedTheme.backgroundCssColor, this.applyCanvasSize(), this.camera = new A(), this.rightCamera = new A(), this.axis = new j(this.camera), this.rightAxis = new j(this.rightCamera), this.renderer = new O(new oe(this.layout.canvas)), this.rawLineData = new Float32Array(W * 2), this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length), this.minMaxInstanceData = new Float32Array(K * q), this.minMaxInstanceBuffer = this.renderer.createFloatBuffer(this.minMaxInstanceData.length), this.barTriangleData = new Float32Array(J * Y), this.barTriangleBuffer = this.renderer.createFloatBuffer(this.barTriangleData.length), this.gridData = new Float32Array(Z * 2), this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length), this.gridStyle = {
1457
1678
  color: t.gridStyle?.color ?? this.resolvedTheme.gridColor,
1458
1679
  lineWidth: t.gridStyle?.lineWidth ?? 1
1459
- }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new O(this.layout, this.normalizedAxes, {
1680
+ }, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible || this.normalizedAxes.y2.visible) && (this.axisOverlay = new M(this.layout, this.normalizedAxes, {
1460
1681
  color: this.resolvedTheme.axisColor,
1461
1682
  font: this.resolvedTheme.axisFont
1462
1683
  })), 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));
@@ -1480,48 +1701,61 @@ var re = class {
1480
1701
  get yAxisElement() {
1481
1702
  return this.layout.yAxis;
1482
1703
  }
1704
+ get y2AxisElement() {
1705
+ return this.layout.y2Axis;
1706
+ }
1483
1707
  get theme() {
1484
1708
  return this.resolvedTheme;
1485
1709
  }
1486
- getCamera() {
1487
- return this.camera;
1710
+ getCamera(e = "left") {
1711
+ return e === "right" ? this.rightCamera : this.camera;
1488
1712
  }
1489
- dataToPlot(e, t) {
1490
- let [n, r] = this.camera.toClip(e, t);
1491
- return this.camera.toScreen(n, r, this.canvas.clientWidth, this.canvas.clientHeight);
1713
+ dataToPlot(e, t, n = "left") {
1714
+ let r = this.getCamera(n), [i, a] = r.toClip(e, t);
1715
+ return r.toScreen(i, a, this.canvas.clientWidth, this.canvas.clientHeight);
1492
1716
  }
1493
- clientToData(e, t) {
1494
- let n = this.canvas.getBoundingClientRect();
1495
- if (n.width <= 0 || n.height <= 0) return null;
1496
- let r = e - n.left, i = t - n.top;
1497
- if (r < 0 || i < 0 || r > n.width || i > n.height) return null;
1498
- let a = this.camera.viewport;
1499
- return [a.xMin + r / n.width * (a.xMax - a.xMin), a.yMax - i / n.height * (a.yMax - a.yMin)];
1717
+ clientToData(e, t, n = "left") {
1718
+ let r = this.canvas.getBoundingClientRect();
1719
+ if (r.width <= 0 || r.height <= 0) return null;
1720
+ let i = e - r.left, a = t - r.top;
1721
+ if (i < 0 || a < 0 || i > r.width || a > r.height) return null;
1722
+ let o = this.getCamera(n).viewport;
1723
+ return [o.xMin + i / r.width * (o.xMax - o.xMin), o.yMax - a / r.height * (o.yMax - o.yMin)];
1500
1724
  }
1501
- getViewport() {
1502
- return this.camera.viewport;
1725
+ getViewport(e = "left") {
1726
+ return this.getCamera(e).viewport;
1503
1727
  }
1504
1728
  pan(e) {
1505
- this.camera.pan(e), this.refreshHover();
1729
+ this.camera.pan(e), this.syncRightCameraX(), this.refreshHover();
1506
1730
  }
1507
1731
  zoom(e) {
1508
- this.camera.zoom(e), this.refreshHover();
1732
+ this.camera.zoom(e), this.syncRightCameraX(), this.refreshHover();
1509
1733
  }
1510
1734
  addSeries(e, t) {
1511
- let n = e.dataset ?? new a(e.capacity), r = this.resolvedTheme.seriesColors, o = r[this.series.length % r.length] ?? this.resolvedTheme.seriesColors[0], s = t?.color ?? o, c = new i(n, e, {
1512
- color: s,
1735
+ if ((e.mode === "ohlc" || e.mode === "candlestick") && !e.dataset) throw TypeError("OHLC and candlestick series require an OhlcDataset.");
1736
+ let n = e.dataset ?? new p(e.capacity, { overflow: e.overflow }), r = this.resolvedTheme.seriesColors, i = r[this.series.length % r.length] ?? this.resolvedTheme.seriesColors[0], a = t?.color ?? i, o = new u(n, e, {
1737
+ color: a,
1513
1738
  lineWidth: t?.lineWidth ?? 1,
1514
1739
  pointSize: t?.pointSize ?? 4,
1515
1740
  barWidth: t?.barWidth ?? .8,
1516
1741
  baseline: t?.baseline ?? 0,
1517
1742
  fillColor: t?.fillColor ?? [
1518
- s[0],
1519
- s[1],
1520
- s[2],
1521
- s[3] * .25
1522
- ]
1743
+ a[0],
1744
+ a[1],
1745
+ a[2],
1746
+ a[3] * .25
1747
+ ],
1748
+ tickWidth: t?.tickWidth ?? t?.barWidth ?? .8,
1749
+ upColor: t?.upColor ?? a,
1750
+ downColor: t?.downColor ?? t?.fillColor ?? [
1751
+ a[0],
1752
+ a[1],
1753
+ a[2],
1754
+ a[3] * .45
1755
+ ],
1756
+ wickColor: t?.wickColor ?? a
1523
1757
  });
1524
- return this.series.push(c), this.emitSeriesChange(), c;
1758
+ return this.series.push(o), this.emitSeriesChange(), o;
1525
1759
  }
1526
1760
  addLine(e, t) {
1527
1761
  return this.addSeries({
@@ -1547,6 +1781,18 @@ var re = class {
1547
1781
  mode: "bar"
1548
1782
  }, t);
1549
1783
  }
1784
+ addOhlc(e, t) {
1785
+ return this.addSeries({
1786
+ ...e,
1787
+ mode: "ohlc"
1788
+ }, t);
1789
+ }
1790
+ addCandlestick(e, t) {
1791
+ return this.addSeries({
1792
+ ...e,
1793
+ mode: "candlestick"
1794
+ }, t);
1795
+ }
1550
1796
  removeSeries(e) {
1551
1797
  let t = this.series.indexOf(e);
1552
1798
  return t === -1 ? !1 : (this.series.splice(t, 1), this.emitSeriesChange(), !0);
@@ -1562,11 +1808,15 @@ var re = class {
1562
1808
  name: e.config.name,
1563
1809
  mode: e.config.mode,
1564
1810
  visible: e.visible,
1565
- color: e.style.color
1811
+ color: e.style.color,
1812
+ yAxis: e.config.yAxis ?? "left"
1566
1813
  }));
1567
1814
  }
1568
1815
  setViewport(e) {
1569
- this.camera.setViewport(e), this.refreshHover();
1816
+ this.camera.setViewport(e), this.rightCamera.setViewport(e), this.refreshHover();
1817
+ }
1818
+ setYViewport(e, t) {
1819
+ this.getCamera(e).setViewport(t), this.refreshHover();
1570
1820
  }
1571
1821
  resize(e = globalThis.devicePixelRatio) {
1572
1822
  let t = this.applyCanvasSize(e);
@@ -1598,7 +1848,7 @@ var re = class {
1598
1848
  return this.seriesSubscribers.add(n), () => this.seriesSubscribers.delete(n);
1599
1849
  }
1600
1850
  setTheme(e) {
1601
- this.resolvedTheme = j(e, this.layout.root), this.applyTheme(), this.emitThemeChange(), this.refreshHover();
1851
+ this.resolvedTheme = P(e, this.layout.root), this.applyTheme(), this.emitThemeChange(), this.refreshHover();
1602
1852
  }
1603
1853
  setGridVisible(e) {
1604
1854
  this._gridVisible = e;
@@ -1607,7 +1857,7 @@ var re = class {
1607
1857
  return this._gridVisible;
1608
1858
  }
1609
1859
  setAxes(e) {
1610
- this.normalizedAxes = $(e), this.layout.update(this.normalizedAxes), this.axisOverlay?.dispose(), this.axisOverlay = null, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible) && (this.axisOverlay = new O(this.layout, this.normalizedAxes, {
1860
+ this.normalizedAxes = $(e), this.layout.update(this.normalizedAxes), this.axisOverlay?.dispose(), this.axisOverlay = null, (this.normalizedAxes.x.visible || this.normalizedAxes.y.visible || this.normalizedAxes.y2.visible) && (this.axisOverlay = new M(this.layout, this.normalizedAxes, {
1611
1861
  color: this.resolvedTheme.axisColor,
1612
1862
  font: this.resolvedTheme.axisFont
1613
1863
  })), this.resize(), this.refreshHover();
@@ -1617,17 +1867,21 @@ var re = class {
1617
1867
  if (r.width <= 0 || r.height <= 0) return null;
1618
1868
  let i = e - r.left, a = t - r.top;
1619
1869
  if (i < 0 || a < 0 || i > r.width || a > r.height) return null;
1620
- 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);
1621
- return d === null ? null : {
1870
+ 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.group ?? this.options.hover?.group ?? "x", d = n.maxDistancePx ?? this.options.hover?.maxDistancePx ?? Infinity, f = l === "nearest-point" ? this.findNearestPointCandidate(s, a, r.width, r.height, d) : this.findNearestXCandidate(s, r.width, d);
1871
+ if (!f) return null;
1872
+ let p = f.sample.x;
1873
+ return {
1622
1874
  clientX: e,
1623
1875
  clientY: t,
1624
1876
  plotX: i,
1625
1877
  plotY: a,
1626
1878
  dataX: s,
1627
1879
  dataY: c,
1628
- anchorX: d,
1880
+ anchorX: p,
1629
1881
  mode: l,
1630
- items: this.collectPickItems(d, e, t, o, r)
1882
+ group: u,
1883
+ maxDistancePx: d,
1884
+ items: u === "none" ? [this.createPickItem(f.sample, f.series, f.seriesIndex, e, t, r)] : this.collectPickItems(p, e, t, r)
1631
1885
  };
1632
1886
  }
1633
1887
  async screenshot(e = {}) {
@@ -1636,7 +1890,7 @@ var re = class {
1636
1890
  o.width = i, o.height = a;
1637
1891
  let s = o.getContext("2d");
1638
1892
  if (!s) throw Error("Unable to create a 2D canvas context for screenshot export.");
1639
- return s.fillStyle = e.background ?? P(this.resolvedTheme.backgroundColor), s.fillRect(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) => {
1893
+ return s.fillStyle = e.background ?? I(this.resolvedTheme.backgroundColor), s.fillRect(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) => {
1640
1894
  o.toBlob((e) => e ? t(e) : n(/* @__PURE__ */ Error("Unable to encode chart screenshot.")), e.type ?? "image/png", e.quality);
1641
1895
  });
1642
1896
  }
@@ -1651,39 +1905,16 @@ var re = class {
1651
1905
  }
1652
1906
  render() {
1653
1907
  let e = performance.now();
1654
- this.lastFrameAt > 0 && (this.stats.fps = 1e3 / (e - this.lastFrameAt)), this.lastFrameAt = e, this.stats.pointsRendered = 0, this.stats.drawCalls = 0, this.stats.uploadBytes = 0, this.stats.renderMode = "none", this.options.viewportPolicy?.beforeRender?.(this.camera);
1908
+ this.lastFrameAt > 0 && (this.stats.fps = 1e3 / (e - this.lastFrameAt)), this.lastFrameAt = e, this.stats.pointsRendered = 0, this.stats.drawCalls = 0, this.stats.uploadBytes = 0, this.stats.renderMode = "none", this.options.viewportPolicy?.beforeRender?.(this.camera), this.syncRightCameraX();
1655
1909
  let [t, n, r, i] = this.resolvedTheme.backgroundColor;
1656
1910
  this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height), this.renderer.clear(t, n, r, i);
1657
1911
  let a = this.camera.viewport;
1658
- if (this._gridVisible) {
1912
+ if (this.currentXOrigin = a.xMin, this.renderer.setXOrigin(this.currentXOrigin), this._gridVisible) {
1659
1913
  let e = this.writeGridVertices(a);
1660
- e > 0 && (this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData), this.renderer.drawLines(this.gridBuffer, e, this.gridStyle, this.camera), this.stats.drawCalls++, this.stats.uploadBytes += this.gridData.byteLength);
1914
+ e > 0 && (this.uploadGridData(e), this.renderer.drawClipLines(this.gridBuffer, e, this.gridStyle), this.stats.drawCalls++);
1661
1915
  }
1662
- for (let e of this.series) {
1663
- if (!e.visible) continue;
1664
- if (e.rebuildPyramid(), e.config.mode === "scatter") {
1665
- this.drawScatterSeries(e, a);
1666
- continue;
1667
- }
1668
- if (e.config.mode === "bar") {
1669
- this.drawBarSeries(e, a);
1670
- continue;
1671
- }
1672
- if (e.config.mode === "area") {
1673
- this.drawAreaSeries(e, a);
1674
- continue;
1675
- }
1676
- let t = e.visibleSampleCount(a), n = e.hasLOD && t > G;
1677
- if (n && this.renderer.supportsInstancedSegments) {
1678
- let t = e.copyMinMaxInstanced(a, this.minMaxInstanceData, this.maxMinMaxSegments());
1679
- if (t <= 0) continue;
1680
- this.renderer.updateFloatBuffer(this.minMaxInstanceBuffer, this.minMaxInstanceData), this.renderer.drawMinMaxSegmentsInstanced(this.minMaxInstanceBuffer, t, e.style, this.camera), this.recordRenderMode("minmax"), this.stats.pointsRendered += t * 2, this.stats.drawCalls++, this.stats.uploadBytes += this.minMaxInstanceData.byteLength;
1681
- continue;
1682
- }
1683
- let r = n ? e.copyMinMaxVisible(a, this.rawLineData, this.maxMinMaxSegments()) : e.copyRawVisible(a, this.rawLineData, G);
1684
- r < 2 || (this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), n ? (this.renderer.drawMinMaxSegments(this.rawLineBuffer, r, e.style, this.camera), this.recordRenderMode("minmax")) : (this.renderer.drawLineStrip(this.rawLineBuffer, r, e.style, this.camera), this.recordRenderMode("raw")), this.stats.pointsRendered += r, this.stats.drawCalls++, this.stats.uploadBytes += this.rawLineData.byteLength);
1685
- }
1686
- this.axisOverlay?.update(this.camera, this.axis), this.stats.frameMs = performance.now() - e, this.refreshHover();
1916
+ for (let e of this.series) e.visible && (e.rebuildPyramid(), this.drawSeries(e));
1917
+ this.axisOverlay?.update(this.camera, this.axis, this.rightCamera, this.rightAxis), this.stats.frameMs = performance.now() - e, this.refreshHover();
1687
1918
  }
1688
1919
  dispose() {
1689
1920
  this.stop(), this.resizeObserver?.disconnect(), this.canvas.removeEventListener("pointermove", this.handlePointerMove), this.canvas.removeEventListener("pointerleave", this.handlePointerLeave);
@@ -1703,48 +1934,161 @@ var re = class {
1703
1934
  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));
1704
1935
  return this.canvas.width === n && this.canvas.height === r ? !1 : (this.canvas.width = n, this.canvas.height = r, !0);
1705
1936
  }
1706
- drawAreaSeries(e, t) {
1707
- let n = e.style.baseline ?? 0, r = e.copyAreaVisible(t, this.rawLineData, K, n);
1708
- if (r < 4) return;
1709
- 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;
1710
- let i = this.uploadRawInstances(e, t, K);
1711
- i >= 2 && (this.renderer.drawLineStrip(this.rawLineBuffer, i, e.style, this.camera), this.stats.pointsRendered += i, this.stats.drawCalls++), this.recordRenderMode("area");
1712
- }
1713
- drawScatterSeries(e, t) {
1714
- let n = this.uploadRawInstances(e, t, G);
1715
- 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));
1716
- }
1717
- drawBarSeries(e, t) {
1718
- let n = e.visibleSampleCount(t), r = this.maxRawBarInstances();
1719
- if (e.hasLOD && n > r) {
1720
- let n = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxBarFallbackBars());
1721
- if (n <= 0) return;
1722
- this.includeBaselineInBarRanges(n, e.style.baseline ?? 0);
1723
- let r = this.writeBarBucketTriangles(n, t);
1724
- this.drawBarTriangleFallback(r, e.style);
1937
+ cameraForSeries(e) {
1938
+ return e.config.yAxis === "right" ? this.rightCamera : this.camera;
1939
+ }
1940
+ syncRightCameraX() {
1941
+ this.rightCamera.setViewport({
1942
+ xMin: this.camera.xMin,
1943
+ xMax: this.camera.xMax
1944
+ });
1945
+ }
1946
+ drawSeries(e) {
1947
+ let t = this.cameraForSeries(e), n = t.viewport;
1948
+ switch (e.config.mode) {
1949
+ case "area":
1950
+ this.drawAreaSeries(e, n, t);
1951
+ return;
1952
+ case "bar":
1953
+ this.drawBarSeries(e, n, t);
1954
+ return;
1955
+ case "ohlc":
1956
+ this.drawOhlcSeries(e, n, t);
1957
+ return;
1958
+ case "candlestick":
1959
+ this.drawCandlestickSeries(e, n, t);
1960
+ return;
1961
+ case "scatter":
1962
+ this.drawScatterSeries(e, n, t);
1963
+ return;
1964
+ default: this.drawLineSeries(e, n, t);
1965
+ }
1966
+ }
1967
+ drawLineSeries(e, t, n) {
1968
+ let r = e.visibleSampleCount(t), i = e.hasLOD && r > W - 2;
1969
+ if (i && this.renderer.supportsInstancedSegments) {
1970
+ let r = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxMinMaxSegments(), this.currentXOrigin);
1971
+ if (r <= 0) return;
1972
+ this.uploadMinMaxInstanceData(r), this.renderer.drawMinMaxSegmentsInstanced(this.minMaxInstanceBuffer, r, e.style, n), this.recordDraw("minmax", r * 2);
1973
+ return;
1974
+ }
1975
+ if (i) {
1976
+ let r = e.copyMinMaxVisible(t, this.rawLineData, this.maxMinMaxSegments(), this.currentXOrigin);
1977
+ if (r < 2) return;
1978
+ this.uploadRawLineData(r), this.renderer.drawMinMaxSegments(this.rawLineBuffer, r, e.style, n), this.recordDraw("minmax", r);
1979
+ return;
1980
+ }
1981
+ let a = e.copyRawVisibleClipSpace(t, this.rawLineData, W);
1982
+ a < 2 || (this.uploadRawLineData(a), this.renderer.drawClipLineStrip(this.rawLineBuffer, a, e.style), this.recordDraw("raw", a));
1983
+ }
1984
+ drawAreaSeries(e, t, n) {
1985
+ let r = e.visibleIndexRange(t, 1);
1986
+ if (r.end - r.start < 2) return;
1987
+ let i = e.style.baseline ?? 0;
1988
+ if (r.end - r.start > G) {
1989
+ let r = e.copyAreaVisible(t, this.rawLineData, G, i, this.currentXOrigin);
1990
+ r >= 4 && (this.uploadRawLineData(r), this.renderer.drawAreaStrip(this.rawLineBuffer, r, e.style, n), this.recordDraw("area", r));
1991
+ let a = e.copyRawVisible(t, this.rawLineData, G, this.currentXOrigin);
1992
+ a >= 2 && (this.uploadRawLineData(a), this.renderer.drawLineStrip(this.rawLineBuffer, a, e.style, n), this.recordDraw("area", a));
1725
1993
  return;
1726
1994
  }
1727
- let i = this.uploadRawInstances(e, t, r);
1728
- if (i <= 0) return;
1995
+ for (let t = r.start; t < r.end;) {
1996
+ let a = e.copyAreaRange(t, r.end, this.rawLineData, G, i, this.currentXOrigin);
1997
+ if (a < 4) break;
1998
+ this.uploadRawLineData(a), this.renderer.drawAreaStrip(this.rawLineBuffer, a, e.style, n), this.recordDraw("area", a), t += Math.max(1, (a >> 1) - 1);
1999
+ }
2000
+ for (let t = r.start; t < r.end;) {
2001
+ let i = e.copyRawRange(t, r.end, this.rawLineData, G, this.currentXOrigin);
2002
+ if (i < 2) break;
2003
+ this.uploadRawLineData(i), this.renderer.drawLineStrip(this.rawLineBuffer, i, e.style, n), this.recordDraw("area", i), t += Math.max(1, i - 1);
2004
+ }
2005
+ }
2006
+ drawOhlcSeries(e, t, n) {
2007
+ let r = e.visibleIndexRange(t), i = Math.floor(this.rawLineData.length / fe);
2008
+ for (let t = r.start; t < r.end;) {
2009
+ let a = e.copyOhlcRange(t, r.end, this.rawLineData, i, e.style.tickWidth ?? e.style.barWidth ?? .8, this.currentXOrigin);
2010
+ if (a <= 0) break;
2011
+ let o = a * 6;
2012
+ this.uploadRawLineData(o), this.renderer.drawLines(this.rawLineBuffer, o, e.style, n), this.recordDraw("raw", o), t += a;
2013
+ }
2014
+ }
2015
+ drawCandlestickSeries(e, t, n) {
2016
+ let r = e.visibleIndexRange(t, 1), i = Math.min(Math.floor(this.rawLineData.length / X), this.maxBarTriangleBars()), a = {
2017
+ ...e.style,
2018
+ color: e.style.wickColor ?? e.style.color
2019
+ }, o = {
2020
+ ...e.style,
2021
+ color: e.style.upColor ?? e.style.color
2022
+ }, s = {
2023
+ ...e.style,
2024
+ color: e.style.downColor ?? e.style.fillColor ?? e.style.color
2025
+ };
2026
+ for (let t = r.start; t < r.end;) {
2027
+ let c = e.copyOhlcTuplesRange(t, r.end, this.rawLineData, i, this.currentXOrigin);
2028
+ if (c <= 0) break;
2029
+ let l = this.writeCandlestickWicks(c);
2030
+ l > 0 && (this.uploadBarTriangleData(l), this.renderer.drawLines(this.barTriangleBuffer, l, a, n), this.recordDraw("raw", l));
2031
+ let u = e.style.barWidth ?? e.style.tickWidth ?? .8;
2032
+ this.drawCandlestickBodies(c, u, "up", o, n), this.drawCandlestickBodies(c, u, "down", s, n), t += c;
2033
+ }
2034
+ }
2035
+ drawScatterSeries(e, t, n) {
2036
+ if (e.visibleSampleCount(t) > W) {
2037
+ let r = e.copyRawVisible(t, this.rawLineData, W, this.currentXOrigin);
2038
+ if (r <= 0) return;
2039
+ this.uploadRawLineData(r), this.renderer.drawPoints(this.rawLineBuffer, r, e.style, n, this.canvas.width, this.canvas.height), this.recordDraw("points", r);
2040
+ return;
2041
+ }
2042
+ let r = e.visibleIndexRange(t);
2043
+ for (let t = r.start; t < r.end;) {
2044
+ let i = e.copyRawRange(t, r.end, this.rawLineData, W, this.currentXOrigin);
2045
+ if (i <= 0) break;
2046
+ this.uploadRawLineData(i), this.renderer.drawPoints(this.rawLineBuffer, i, e.style, n, this.canvas.width, this.canvas.height), this.recordDraw("points", i), t += i;
2047
+ }
2048
+ }
2049
+ drawBarSeries(e, t, n) {
2050
+ let r = e.visibleSampleCount(t), i = this.maxRawBarInstances();
2051
+ if (e.hasLOD && r > i) {
2052
+ let r = e.copyMinMaxInstanced(t, this.minMaxInstanceData, this.maxBarTriangleBars(), this.currentXOrigin);
2053
+ if (r <= 0) return;
2054
+ this.includeBaselineInBarRanges(r, e.style.baseline ?? 0);
2055
+ let i = this.writeBarBucketTriangles(r, t);
2056
+ this.drawBarTriangles(i, e.style, n);
2057
+ return;
2058
+ }
2059
+ let a = e.visibleIndexRange(t, 1), o = e.copyRawRange(a.start, a.end, this.rawLineData, i, this.currentXOrigin);
2060
+ if (o <= 0) return;
1729
2061
  if (this.renderer.supportsInstancedBars) {
1730
- this.renderer.drawBarsInstanced(this.rawLineBuffer, i, e.style, this.camera), this.recordInstancedDraw("bars", i);
2062
+ this.uploadRawLineData(o), this.renderer.drawBarsInstanced(this.rawLineBuffer, o, e.style, n), this.recordDraw("bars", o);
1731
2063
  return;
1732
2064
  }
1733
- let a = this.writeBarTriangles(i, e.style.baseline ?? 0, e.style.barWidth ?? .8);
1734
- this.drawBarTriangleFallback(a, e.style);
2065
+ let s = this.writeBarTriangles(o, e.style.baseline ?? 0, e.style.barWidth ?? .8);
2066
+ this.drawBarTriangles(s, e.style, n);
2067
+ }
2068
+ uploadRawLineData(e) {
2069
+ this.uploadFloatData(this.rawLineBuffer, this.rawLineData, e * 2);
2070
+ }
2071
+ uploadMinMaxInstanceData(e) {
2072
+ this.uploadFloatData(this.minMaxInstanceBuffer, this.minMaxInstanceData, e * q);
2073
+ }
2074
+ uploadBarTriangleData(e) {
2075
+ this.uploadFloatData(this.barTriangleBuffer, this.barTriangleData, e * 2);
1735
2076
  }
1736
- uploadRawInstances(e, t, n) {
1737
- let r = e.copyRawVisible(t, this.rawLineData, n);
1738
- return r <= 0 ? 0 : (this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData), this.stats.uploadBytes += this.rawLineData.byteLength, r);
2077
+ uploadGridData(e) {
2078
+ this.uploadFloatData(this.gridBuffer, this.gridData, e * 2);
2079
+ }
2080
+ uploadFloatData(e, t, n) {
2081
+ let r = Math.max(0, Math.min(n, t.length));
2082
+ this.renderer.updateFloatBuffer(e, t, r), this.stats.uploadBytes += r * Float32Array.BYTES_PER_ELEMENT;
1739
2083
  }
1740
2084
  includeBaselineInBarRanges(e, t) {
1741
2085
  for (let n = 0; n < e; n++) {
1742
- let e = n * J, r = this.minMaxInstanceData[e + 1], i = this.minMaxInstanceData[e + 2];
2086
+ let e = n * q, r = this.minMaxInstanceData[e + 1], i = this.minMaxInstanceData[e + 2];
1743
2087
  this.minMaxInstanceData[e + 1] = Math.min(t, r), this.minMaxInstanceData[e + 2] = Math.max(t, i);
1744
2088
  }
1745
2089
  }
1746
2090
  writeBarTriangles(e, t, n) {
1747
- let r = Math.min(e, this.maxBarFallbackBars());
2091
+ let r = Math.min(e, this.maxBarTriangleBars());
1748
2092
  for (let e = 0; e < r; e++) {
1749
2093
  let r = this.rawLineData[e * 2], i = this.rawLineData[e * 2 + 1];
1750
2094
  this.writeBarTriangle(e, r - n * .5, r + n * .5, t, i);
@@ -1752,7 +2096,7 @@ var re = class {
1752
2096
  return r * 6;
1753
2097
  }
1754
2098
  writeBarBucketTriangles(e, t) {
1755
- let n = Math.min(e, this.maxBarFallbackBars());
2099
+ let n = Math.min(e, this.maxBarTriangleBars());
1756
2100
  for (let e = 0; e < n; e++) {
1757
2101
  let r = this.minMaxInstanceData[e * 3 + 1], i = this.minMaxInstanceData[e * 3 + 2], [a, o] = this.barBucketBounds(e, n, t);
1758
2102
  this.writeBarTriangle(e, a, o, r, i);
@@ -1760,71 +2104,98 @@ var re = class {
1760
2104
  return n * 6;
1761
2105
  }
1762
2106
  barBucketBounds(e, t, n) {
1763
- let r = this.minMaxInstanceData[e * 3], i = n.xMax - n.xMin;
2107
+ let r = this.minMaxInstanceData[e * 3], i = n.xMin - this.currentXOrigin, a = n.xMax - this.currentXOrigin, o = a - i;
1764
2108
  if (t <= 1) {
1765
- let e = Math.max(0, i * .5);
1766
- return [Math.max(n.xMin, r - e), Math.min(n.xMax, r + e)];
2109
+ let e = Math.max(0, o * .5);
2110
+ return [Math.max(i, r - e), Math.min(a, r + e)];
2111
+ }
2112
+ let s = e > 0 ? this.minMaxInstanceData[(e - 1) * 3] : NaN, c = e + 1 < t ? this.minMaxInstanceData[(e + 1) * 3] : NaN, l = e === 0 ? r - (c - r) * .5 : (s + r) * .5, u = e + 1 === t ? r + (r - s) * .5 : (r + c) * .5;
2113
+ if (!Number.isFinite(l) || !Number.isFinite(u) || u <= l) {
2114
+ let n = o / Math.max(1, t);
2115
+ l = i + e * n, u = e + 1 === t ? a : l + n;
1767
2116
  }
1768
- 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;
1769
- if (!Number.isFinite(s) || !Number.isFinite(c) || c <= s) {
1770
- let r = i / Math.max(1, t);
1771
- s = n.xMin + e * r, c = e + 1 === t ? n.xMax : s + r;
2117
+ return [Math.max(i, l), Math.min(a, u)];
2118
+ }
2119
+ writeCandlestickWicks(e) {
2120
+ for (let t = 0; t < e; t++) {
2121
+ let e = t * X, n = t * 4, r = this.rawLineData[e], i = this.rawLineData[e + 2], a = this.rawLineData[e + 3];
2122
+ this.barTriangleData[n] = r, this.barTriangleData[n + 1] = a, this.barTriangleData[n + 2] = r, this.barTriangleData[n + 3] = i;
1772
2123
  }
1773
- return [Math.max(n.xMin, s), Math.min(n.xMax, c)];
2124
+ return e * 2;
2125
+ }
2126
+ drawCandlestickBodies(e, t, n, r, i) {
2127
+ let a = t * .5, o = 0;
2128
+ for (let t = 0; t < e && o < this.maxBarTriangleBars(); t++) {
2129
+ let e = t * X, r = this.rawLineData[e], i = this.rawLineData[e + 1], s = this.rawLineData[e + 4];
2130
+ n === "up" == s >= i && (this.writeBarTriangle(o, r - a, r + a, Math.min(i, s), Math.max(i, s)), o++);
2131
+ }
2132
+ this.drawBarTriangles(o * 6, r, i);
1774
2133
  }
1775
2134
  writeBarTriangle(e, t, n, r, i) {
1776
- let a = e * X;
2135
+ let a = e * Y;
1777
2136
  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;
1778
2137
  }
1779
- drawBarTriangleFallback(e, t) {
1780
- 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));
1781
- }
1782
- recordInstancedDraw(e, t) {
1783
- this.recordRenderMode(e), this.stats.pointsRendered += t, this.stats.drawCalls++;
2138
+ drawBarTriangles(e, t, n, r = "bars") {
2139
+ e <= 0 || (this.uploadBarTriangleData(e), this.renderer.drawBarTriangles(this.barTriangleBuffer, e, t, n), this.recordDraw(r, e));
1784
2140
  }
1785
- findNearestXAnchor(e, t, n, r) {
1786
- let i = null, a = Infinity, o = n / (t.xMax - t.xMin);
1787
- for (let n of this.series) {
1788
- if (!n.visible) continue;
1789
- let r = n.nearestSampleByX(e, t);
1790
- if (!r) continue;
1791
- let s = Math.abs(r.x - e) * o;
1792
- s < a && (i = r, a = s);
1793
- }
1794
- return !i || a > r ? null : i.x;
2141
+ recordDraw(e, t, n = 1) {
2142
+ this.recordRenderMode(e), this.stats.pointsRendered += t, this.stats.drawCalls += n;
1795
2143
  }
1796
- findNearestPointAnchor(e, t, n, r, i, a) {
1797
- let o = null;
1798
- for (let a of this.series) {
2144
+ findNearestXCandidate(e, t, n) {
2145
+ let r = null, i = Infinity;
2146
+ for (let n = 0; n < this.series.length; n++) {
2147
+ let a = this.series[n];
1799
2148
  if (!a.visible) continue;
1800
- let s = a.nearestSampleByPoint(e, t, n, r, i);
1801
- s && (!o || (s.distancePx ?? Infinity) < (o.distancePx ?? Infinity)) && (o = s);
2149
+ let o = this.cameraForSeries(a).viewport, s = t / (o.xMax - o.xMin), c = a.nearestSampleByX(e, o);
2150
+ if (!c) continue;
2151
+ let l = Math.abs(c.x - e) * s;
2152
+ l < i && (r = {
2153
+ sample: c,
2154
+ series: a,
2155
+ seriesIndex: n
2156
+ }, i = l);
1802
2157
  }
1803
- return !o || (o.distancePx ?? Infinity) > a ? null : o.x;
2158
+ return r && i <= n ? r : null;
1804
2159
  }
1805
- collectPickItems(e, t, n, r, i) {
1806
- let a = [];
2160
+ findNearestPointCandidate(e, t, n, r, i) {
2161
+ let a = null;
1807
2162
  for (let o = 0; o < this.series.length; o++) {
1808
2163
  let s = this.series[o];
1809
2164
  if (!s.visible) continue;
1810
- let c = s.nearestSampleByX(e, r);
1811
- if (!c) continue;
1812
- 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;
1813
- a.push({
1814
- ...c,
1815
- distancePx: Math.hypot(h, g),
2165
+ let c = this.cameraForSeries(s).viewport, l = c.yMax - t / r * (c.yMax - c.yMin), u = s.nearestSampleByPoint(e, l, c, n, r, i);
2166
+ u && (!a || (u.distancePx ?? Infinity) < (a.sample.distancePx ?? Infinity)) && (a = {
2167
+ sample: u,
1816
2168
  series: s,
1817
- seriesIndex: o,
1818
- id: s.config.id,
1819
- name: s.config.name,
1820
- mode: s.config.mode,
1821
- plotX: d,
1822
- plotY: f,
1823
- clientX: p,
1824
- clientY: m
2169
+ seriesIndex: o
1825
2170
  });
1826
2171
  }
1827
- return a;
2172
+ return a && (a.sample.distancePx ?? Infinity) <= i ? a : null;
2173
+ }
2174
+ collectPickItems(e, t, n, r) {
2175
+ let i = [];
2176
+ for (let a = 0; a < this.series.length; a++) {
2177
+ let o = this.series[a];
2178
+ if (!o.visible) continue;
2179
+ let s = o.nearestSampleByX(e, this.cameraForSeries(o).viewport);
2180
+ s && i.push(this.createPickItem(s, o, a, t, n, r));
2181
+ }
2182
+ return i;
2183
+ }
2184
+ createPickItem(e, t, n, r, i, a) {
2185
+ let o = this.cameraForSeries(t), [s, c] = o.toClip(e.x, e.y), [l, u] = o.toScreen(s, c, a.width, a.height), d = a.left + l, f = a.top + u, p = d - r, m = f - i;
2186
+ return {
2187
+ ...e,
2188
+ distancePx: Math.hypot(p, m),
2189
+ series: t,
2190
+ seriesIndex: n,
2191
+ id: t.config.id,
2192
+ name: t.config.name,
2193
+ mode: t.config.mode,
2194
+ plotX: l,
2195
+ plotY: u,
2196
+ clientX: d,
2197
+ clientY: f
2198
+ };
1828
2199
  }
1829
2200
  refreshHover() {
1830
2201
  this.pointerInPlot && this.emitHover(this.pick(this.lastPointerClientX, this.lastPointerClientY));
@@ -1852,13 +2223,13 @@ var re = class {
1852
2223
  }
1853
2224
  }
1854
2225
  maxMinMaxSegments() {
1855
- return Math.min(this.canvas.width, q);
2226
+ return Math.min(this.canvas.width, K);
1856
2227
  }
1857
- maxBarFallbackBars() {
1858
- return Math.min(Y, G);
2228
+ maxBarTriangleBars() {
2229
+ return Math.min(J, W);
1859
2230
  }
1860
2231
  maxRawBarInstances() {
1861
- return this.renderer.supportsInstancedBars ? G : this.maxBarFallbackBars();
2232
+ return this.renderer.supportsInstancedBars ? W : this.maxBarTriangleBars();
1862
2233
  }
1863
2234
  writeGridVertices(e) {
1864
2235
  let t = Math.max(1, this.canvas.clientWidth), n = Math.max(1, this.canvas.clientHeight);
@@ -1866,18 +2237,24 @@ var re = class {
1866
2237
  let r = 0;
1867
2238
  for (let t of this.xTicks) {
1868
2239
  if (r + 2 > Z) return r;
1869
- 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++;
2240
+ this.gridData[r * 2] = this.xToClip(t, e), this.gridData[r * 2 + 1] = -1, r++, this.gridData[r * 2] = this.xToClip(t, e), this.gridData[r * 2 + 1] = 1, r++;
1870
2241
  }
1871
2242
  for (let t of this.yTicks) {
1872
2243
  if (r + 2 > Z) return r;
1873
- 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++;
2244
+ this.gridData[r * 2] = -1, this.gridData[r * 2 + 1] = this.yToClip(t, e), r++, this.gridData[r * 2] = 1, this.gridData[r * 2 + 1] = this.yToClip(t, e), r++;
1874
2245
  }
1875
2246
  return r;
1876
2247
  }
2248
+ xToClip(e, t) {
2249
+ return (e - t.xMin) / (t.xMax - t.xMin) * 2 - 1;
2250
+ }
2251
+ yToClip(e, t) {
2252
+ return (e - t.yMin) / (t.yMax - t.yMin) * 2 - 1;
2253
+ }
1877
2254
  recordRenderMode(e) {
1878
2255
  this.stats.renderMode === "none" ? this.stats.renderMode = e : this.stats.renderMode !== e && (this.stats.renderMode = "mixed");
1879
2256
  }
1880
- }, ie = class {
2257
+ }, me = class {
1881
2258
  xData;
1882
2259
  yData;
1883
2260
  constructor(e, t) {
@@ -1899,26 +2276,135 @@ var re = class {
1899
2276
  return this.assertValidIndex(e), this.yData[e];
1900
2277
  }
1901
2278
  lowerBoundX(e) {
1902
- let t = 0, n = this.length;
1903
- for (; t < n;) {
1904
- let r = t + (n - t >> 1);
1905
- this.xData[r] < e ? t = r + 1 : n = r;
1906
- }
1907
- return t;
2279
+ return d(this.length, (e) => this.xData[e], e);
1908
2280
  }
1909
2281
  upperBoundX(e) {
1910
- let t = 0, n = this.length;
1911
- for (; t < n;) {
1912
- let r = t + (n - t >> 1);
1913
- this.xData[r] <= e ? t = r + 1 : n = r;
1914
- }
1915
- return t;
2282
+ return f(this.length, (e) => this.xData[e], e);
1916
2283
  }
1917
2284
  assertValidIndex(e) {
1918
2285
  if (!Number.isInteger(e) || e < 0 || e >= this.length) throw RangeError(`StaticDataset index out of range: ${e}`);
1919
2286
  }
2287
+ }, he = class {
2288
+ length;
2289
+ xs;
2290
+ opens;
2291
+ highs;
2292
+ lows;
2293
+ closes;
2294
+ constructor(e, t, n, r, i) {
2295
+ this.length = Math.min(e.length, t.length, n.length, r.length, i.length), this.xs = e, this.opens = t, this.highs = n, this.lows = r, this.closes = i;
2296
+ }
2297
+ get range() {
2298
+ return this.length === 0 ? null : {
2299
+ start: this.getX(0),
2300
+ end: this.getX(this.length - 1)
2301
+ };
2302
+ }
2303
+ getX(e) {
2304
+ return this.assertValidIndex(e), this.xs[e];
2305
+ }
2306
+ getY(e) {
2307
+ return this.getClose(e);
2308
+ }
2309
+ getOpen(e) {
2310
+ return this.assertValidIndex(e), this.opens[e];
2311
+ }
2312
+ getHigh(e) {
2313
+ return this.assertValidIndex(e), this.highs[e];
2314
+ }
2315
+ getLow(e) {
2316
+ return this.assertValidIndex(e), this.lows[e];
2317
+ }
2318
+ getClose(e) {
2319
+ return this.assertValidIndex(e), this.closes[e];
2320
+ }
2321
+ lowerBoundX(e) {
2322
+ return d(this.length, (e) => this.xs[e], e);
2323
+ }
2324
+ upperBoundX(e) {
2325
+ return f(this.length, (e) => this.xs[e], e);
2326
+ }
2327
+ assertValidIndex(e) {
2328
+ if (!Number.isInteger(e) || e < 0 || e >= this.length) throw RangeError(`StaticOhlcDataset index out of range: ${e}`);
2329
+ }
2330
+ }, ge = class {
2331
+ capacity;
2332
+ overflow;
2333
+ xData;
2334
+ openData;
2335
+ highData;
2336
+ lowData;
2337
+ closeData;
2338
+ _length = 0;
2339
+ _head = 0;
2340
+ constructor(e, t = {}) {
2341
+ if (!Number.isInteger(e) || e <= 0) throw RangeError("OhlcRingBuffer capacity must be a positive integer.");
2342
+ this.capacity = e, this.overflow = t.overflow ?? "wrap", this.xData = new Float64Array(e), this.openData = new Float32Array(e), this.highData = new Float32Array(e), this.lowData = new Float32Array(e), this.closeData = new Float32Array(e);
2343
+ }
2344
+ get length() {
2345
+ return this._length;
2346
+ }
2347
+ get range() {
2348
+ return this._length === 0 ? null : {
2349
+ start: this.getX(0),
2350
+ end: this.getX(this._length - 1)
2351
+ };
2352
+ }
2353
+ push(e, t, n, r, i) {
2354
+ if (this._length >= this.capacity) {
2355
+ if (this.overflow === "drop-new") return;
2356
+ if (this.overflow === "error") throw RangeError("OhlcRingBuffer capacity exceeded.");
2357
+ }
2358
+ this.xData[this._head] = e, this.openData[this._head] = t, this.highData[this._head] = n, this.lowData[this._head] = r, this.closeData[this._head] = i, this._head = (this._head + 1) % this.capacity, this._length < this.capacity && this._length++;
2359
+ }
2360
+ append(e, t, n, r, i) {
2361
+ let a = Math.min(e.length, t.length, n.length, r.length, i.length);
2362
+ if (a <= 0) return;
2363
+ if (this.overflow !== "wrap") {
2364
+ let o = this.capacity - this._length;
2365
+ if (a > o && this.overflow === "error") throw RangeError("OhlcRingBuffer capacity exceeded.");
2366
+ let s = Math.min(a, o);
2367
+ for (let a = 0; a < s; a++) this.push(e[a], t[a], n[a], r[a], i[a]);
2368
+ return;
2369
+ }
2370
+ let o = Math.max(0, a - this.capacity);
2371
+ for (let s = o; s < a; s++) this.push(e[s], t[s], n[s], r[s], i[s]);
2372
+ }
2373
+ clear() {
2374
+ this._length = 0, this._head = 0;
2375
+ }
2376
+ getX(e) {
2377
+ return this.assertValidIndex(e), this.xData[this.logicalToPhysical(e)];
2378
+ }
2379
+ getY(e) {
2380
+ return this.getClose(e);
2381
+ }
2382
+ getOpen(e) {
2383
+ return this.assertValidIndex(e), this.openData[this.logicalToPhysical(e)];
2384
+ }
2385
+ getHigh(e) {
2386
+ return this.assertValidIndex(e), this.highData[this.logicalToPhysical(e)];
2387
+ }
2388
+ getLow(e) {
2389
+ return this.assertValidIndex(e), this.lowData[this.logicalToPhysical(e)];
2390
+ }
2391
+ getClose(e) {
2392
+ return this.assertValidIndex(e), this.closeData[this.logicalToPhysical(e)];
2393
+ }
2394
+ lowerBoundX(e) {
2395
+ return d(this._length, (e) => this.getX(e), e);
2396
+ }
2397
+ upperBoundX(e) {
2398
+ return f(this._length, (e) => this.getX(e), e);
2399
+ }
2400
+ logicalToPhysical(e) {
2401
+ return (this._head - this._length + e + this.capacity) % this.capacity;
2402
+ }
2403
+ assertValidIndex(e) {
2404
+ if (!Number.isInteger(e) || e < 0 || e >= this._length) throw RangeError(`OhlcRingBuffer index out of range: ${e}`);
2405
+ }
1920
2406
  };
1921
2407
  //#endregion
1922
- export { D as AxisController, E as Camera2D, re as Chart, A as DEFAULT_CHART_THEME, n as MinMaxPyramid, a as RingBuffer, i as SeriesStore, ie as StaticDataset };
2408
+ export { j as AxisController, A as Camera2D, pe as Chart, N as DEFAULT_CHART_THEME, n as MinMaxPyramid, ge as OhlcRingBuffer, p as RingBuffer, u as SeriesStore, me as StaticDataset, he as StaticOhlcDataset };
1923
2409
 
1924
2410
  //# sourceMappingURL=index.js.map